Compare commits

...

181 Commits

Author SHA1 Message Date
40862fcf12 0.90.2 released. 2011-02-24 17:40:24 +09:00
110b25a64b Update translation. 2011-02-24 17:39:15 +09:00
f1a44ddebb Rebuild eek.types when compiling doc from tarball. 2011-02-24 17:38:22 +09:00
fc00d86c7e Avoid I_() from being translated. 2011-02-24 17:37:42 +09:00
4a822fe52c Fix typo. 2011-02-24 14:45:19 +09:00
6587f00c2a Reuse window. 2011-02-24 14:43:13 +09:00
3b77502b97 Add Python binding. 2011-02-24 13:14:33 +09:00
d7554b9735 Doc fix. 2011-02-24 11:43:15 +09:00
798df5c136 Use g_intern_static_string for signal names. 2011-02-24 10:37:48 +09:00
22c70976db Remove unused get_keyboard function. 2011-02-24 10:37:48 +09:00
3eeb7cd8ab Rename EekboardServer to EekboardEekboard. 2011-02-24 10:37:48 +09:00
7ef245d739 Fix clutter build. 2011-02-24 10:36:00 +09:00
9a6b3b3e2d Update ServerContext#enabled before showing/hiding window. 2011-02-23 19:40:01 +09:00
715c9ca022 Add padding to EekboardServerClass and EekboardContextClass. 2011-02-23 18:48:40 +09:00
5f57ea7fe6 0.90.1 released. 2011-02-23 15:12:39 +09:00
37b2e60e99 Minor fixes for make distcheck. 2011-02-23 15:11:33 +09:00
95024543cc Rename system-client to desktop-client. 2011-02-23 14:52:40 +09:00
3f1abe8350 Add some keysym labels. 2011-02-23 14:52:32 +09:00
50895d08e1 Avoid to send KeyboardVisibilityChanged on SetKeyboard and SetGroup. 2011-02-23 14:51:25 +09:00
6747e07166 Quit system-client when user closed a keyboard window. 2011-02-23 14:31:42 +09:00
994d0a9a7e Show keyboard if --listen-focus is not passed to eekboard-system-client. 2011-02-23 13:16:12 +09:00
3f7562809e Clear all input contexts associated with disconnected client. 2011-02-23 13:15:39 +09:00
5fd8477a21 Add icons. 2011-02-23 13:13:49 +09:00
faa5d60bea Make the default border width to 1. 2011-02-23 05:45:46 +09:00
02d41b8dfe Add aliases of known keysyms. 2011-02-23 05:45:27 +09:00
caf105cbd9 Add doc. 2011-02-23 05:14:14 +09:00
2c067482de Enable the previous context if the current context is vanished. 2011-02-22 22:55:20 +09:00
bf8d119a0e Make sure to remove context from the stack if the client is disconnected. 2011-02-22 22:41:12 +09:00
3f83b578de Add some libs to avoid implicit DSO linking. 2011-02-22 22:08:17 +09:00
16fe4a3565 Fix fakekey modifier handling. 2011-02-22 19:33:39 +09:00
abf16370ad Update README. 2011-02-22 19:18:55 +09:00
a93b84c32e Add D-Bus service entry. 2011-02-22 19:07:36 +09:00
267f983ca1 Fix window title and icon. 2011-02-22 18:59:52 +09:00
50e9f3186a Tune input context suspend/resume behavior. 2011-02-22 18:38:11 +09:00
d25114b370 Allow the server to have multiple input contexts. 2011-02-22 17:22:36 +09:00
12cc310e38 Make sure that a key is not pressed when sending new "pressed" event of it. 2011-02-21 16:13:19 +09:00
bf2b9c968d Move name owning code from server.c to server-main.c. 2011-02-21 16:13:14 +09:00
4a0cda72a2 Maintain group in EekboardKeyboard. 2011-02-18 19:13:25 +09:00
e3e3b60f1e Add VisibilityChanged signal. 2011-02-18 18:06:42 +09:00
ddfc0422b4 Add assertions. 2011-02-18 17:18:48 +09:00
42bf50f6a3 Fix indent. 2011-02-18 17:13:45 +09:00
47428b8959 Define eek_symbol_is_modifier as function. 2011-02-18 17:13:14 +09:00
0965ed680d Make eek-xml-layout.h public. 2011-02-18 17:12:30 +09:00
8f8139e7dc Maintain EekKeyboard in EekboardKeyboardPrivate. 2011-02-18 17:11:16 +09:00
c3e10343b4 Cosmetic fixes. 2011-02-18 14:03:51 +09:00
3aa2e6f425 Strip prefix "Eekboard". 2011-02-18 14:03:37 +09:00
66bfa4da1d Fix GI annotation. 2011-02-18 14:03:19 +09:00
d09ca88101 Export class definitions to eekboard-keyboard.h 2011-02-18 12:19:28 +09:00
453429f860 Fix include path for GISCAN and GICOMP. 2011-02-18 11:42:53 +09:00
fdd9c3d0ee Rename EekboardDevice to EekboardKeyboard. 2011-02-18 11:39:16 +09:00
22a51a2813 Fix the last commit. 2011-02-14 18:49:28 +09:00
89c5c46dbb Rename EekboardProxy to EekboardDevice. 2011-02-14 18:47:23 +09:00
ab43010a98 Seperate out GDBus proxy into libeekboard from src/. 2011-02-14 18:27:49 +09:00
7916930160 Implement serialization to GVariant. 2011-02-14 14:13:02 +09:00
11026923bd Ignore some files. 2011-02-07 03:50:00 +01:00
2d50b96881 Don't mention --listen-keystroke option. 2011-02-06 11:45:33 +01:00
23d1819f40 Make sure to include config.h to check HAVE_CSPI and HAVE_FAKEKEY. 2011-02-05 03:36:46 +01:00
b631f54a54 Implement serialization to GVariant (WIP). 2011-02-02 18:41:26 +09:00
453c3fee79 Make EekLayout abstract. 2011-02-02 16:59:13 +09:00
d7c9626df9 Remove debug print. 2011-02-02 13:10:25 +09:00
c7a2be629f Set empty keysym matrix if keycode is 0. 2011-02-02 13:10:07 +09:00
a2c9aa6742 Add libxklavier option to eekboard-xml. 2011-02-02 13:09:39 +09:00
56abc55bb2 Make fakekey and CSPI optional. 2011-02-02 06:51:27 +09:00
d2fc32f2a7 Doc fix. 2011-02-01 22:50:14 +09:00
b221010800 Doc fix. 2011-02-01 22:39:24 +09:00
8537c42756 Rename eek-example-xml to eekboard-xml. 2011-02-01 19:04:43 +09:00
aae296696d Doc fix. 2011-02-01 18:28:04 +09:00
74eb0f3c35 Set "keep-above" property to the window. 2011-02-01 18:27:39 +09:00
68b0d64fee Use 0 as EEK_INVALID_KEYCODE/KEYSYM instead of -1. 2011-02-01 18:27:13 +09:00
fd6035c54a Hide window when focus listener detects focus out. 2011-02-01 17:54:15 +09:00
a1dd32b121 Ignore modifier keys in AccessibleKeystrokeListener. 2011-02-01 17:37:52 +09:00
c9c9a3297b Coding style fix. 2011-02-01 16:54:31 +09:00
0422352139 Make sure to disconnect signal handlers in dispose(). 2011-02-01 16:48:15 +09:00
4b590dc05d Fix modifier handling using libfakekey. 2011-02-01 16:40:49 +09:00
0f33ced9bc Doc fix. 2011-02-01 15:20:36 +09:00
2831d58dcd Reimplement keystroke listener. 2011-02-01 13:04:48 +09:00
eb646ff769 Separate --listen-focus/--listen-keystroke option of eekboard-system-client. 2011-02-01 12:43:33 +09:00
aed12cd831 Make sure to disconnect signal handlers on dispose. 2011-02-01 12:25:34 +09:00
30d88ceb78 Add Clutter support to eekboard-server. 2011-02-01 11:24:51 +09:00
f66d20972d Doc fix: keycode is not necessarily the same as the X keycode. 2011-02-01 11:07:39 +09:00
7055f5fa50 Fix doc. 2011-02-01 11:01:16 +09:00
6bbbe27c9a Add eekboard-client. 2011-02-01 11:01:03 +09:00
5cb5e057e7 Don't use libnotify. 2011-02-01 07:48:39 +09:00
134faacb5e Reimplement eekboard as a D-Bus server. 2011-02-01 07:48:02 +09:00
b2ad88bd01 Fix #include ordering. 2011-02-01 07:35:35 +09:00
e999883c58 Generate unique id for <key id="...">. 2011-02-01 07:33:44 +09:00
6258476713 Don't ignore unknown keysym category. 2011-02-01 07:32:23 +09:00
53b96d3f44 Fix unicode keysym. 2011-02-01 07:31:48 +09:00
da4552c61c Use 0 as fallback group, instead of -1. 2011-02-01 07:31:20 +09:00
8b563740f5 Simplify test-keyboard.xml. 2011-01-31 23:49:30 +09:00
6137b7e1f5 Add a sample program eek-example-xml. 2011-01-31 23:39:56 +09:00
a7b276c3c4 Use "M" to calculate font size if a keyboard has no letter key. 2011-01-29 10:59:34 +09:00
6a063c9d76 Uncomment XML layout scaling code. 2011-01-29 10:58:37 +09:00
ac71ea0035 Make sure to chain-up finalize method. 2011-01-28 21:19:43 +09:00
879c50a6b8 Fix typo. 2011-01-28 21:17:01 +09:00
4e1ad08e90 Doc fix. 2011-01-28 18:49:16 +09:00
45b18c7ada Embed keycode as <key id="key<keycode>"> in the XML output. 2011-01-28 17:39:37 +09:00
ca5873022a Add license text. 2011-01-28 17:06:17 +09:00
b004a92e8a Fix EEK_MODIFIER_BEHAVIOR_LATCH when pressing Shift twice. 2011-01-28 16:55:01 +09:00
e6df7d90fe Use GObject instead of guint to represent keysyms. 2011-01-28 16:19:18 +09:00
4ff254df97 Remove unused funcdecl. 2011-01-28 15:53:17 +09:00
0c77bd45f2 Don't embed native keycode/keysym values in XML layout data. 2011-01-27 19:06:59 +09:00
880ba76bd8 Update copyright year. 2011-01-27 16:58:59 +09:00
327817e7ea Add license header to eek-xml*.[ch]. 2011-01-27 16:56:16 +09:00
2c98207799 Add --xml option to eekboard. 2011-01-27 16:49:45 +09:00
6c2ef567c4 Doc fix. 2011-01-27 16:49:35 +09:00
4f9b504d90 Add version macro for XML schema. 2011-01-27 16:48:48 +09:00
b811796bbc Finish XML layout engine. 2011-01-27 16:27:06 +09:00
4008706bb0 Remove useless get_group method and group_changed signal of EekLayout. 2011-01-27 11:09:24 +09:00
20acd11425 Don't use floating object for EekElement. 2011-01-27 09:55:24 +09:00
b36e2f09de Fix outline caching in XML layout. 2011-01-26 19:28:10 +09:00
d29e83e5f6 Add XML layout engine (WIP). 2011-01-26 19:24:06 +09:00
0dd37a39b9 Add XML layout engine (WIP). 2011-01-26 19:17:32 +09:00
b22858f9cf Remove useless assertion. 2011-01-26 19:16:52 +09:00
4accb1e952 Doc fix. 2011-01-26 12:50:22 +09:00
5e4a6b2c8e Port modifier handling code from application into library. 2011-01-26 11:59:12 +09:00
79986e47b6 Remove unused variables. 2011-01-26 11:12:21 +09:00
45cd7958d0 Don't cache group/level in EekKey. 2011-01-26 07:57:44 +09:00
7bdc984933 Add new symbols to GTK-Doc sections.txt. 2011-01-25 18:43:07 +09:00
76f3ef75d5 Fix eek_keyboard_new arglist. 2011-01-25 18:42:29 +09:00
13e4d1cdb3 Add convenient function to get/set per-keyboard group/level. 2011-01-25 18:32:52 +09:00
70df392647 Avoid to use Clutter scaling feature. 2011-01-25 18:10:42 +09:00
ae857f5981 Fix typo in eek_clutter_renderer_new. 2011-01-25 18:09:02 +09:00
cb49214667 Update README. 2011-01-25 18:08:36 +09:00
48e64f1c32 Move eek_keyboard_new to eek-layout.c; add utility functions. 2011-01-25 16:17:34 +09:00
9b1a53510e Delay the initialization of EekClutter* until ClutterActor::realize. 2011-01-25 15:20:20 +09:00
c6aa173202 Add EekGtkKeyboard:keyboard property. 2011-01-25 14:41:57 +09:00
907fc3f872 Define EekLayout as a class instead of an interface. 2011-01-25 14:29:57 +09:00
406a59277f Remove duplicate files in $(libeek_public_headers) in Makefile.am. 2011-01-25 11:28:13 +09:00
f094466d64 Add license text. 2011-01-25 11:10:53 +09:00
af8274f305 Fix GTK-Doc comment. 2011-01-25 11:06:03 +09:00
420b8014f8 Revive Clutter support. 2011-01-25 10:40:25 +09:00
9e5fa977a5 Split eek_renderer_render_key to e_r_r_key_label and e_r_r_key_outline. 2011-01-25 10:38:56 +09:00
fe101ff0e8 Rename eek_renderer_set_preferred_size to e_r_s_allocation_size. 2011-01-23 17:29:10 +09:00
0ba067aa15 Fix memleak; fix eek_gtk_keyboard_new doc. 2011-01-23 16:59:05 +09:00
192cab67e9 Fix "keysym-index-changed" callback of EekGtkKeyboard. 2011-01-22 16:50:15 +09:00
fa08da847a Don't install eek-clutter*.pc if Clutter build is disabled. 2011-01-22 16:27:59 +09:00
81d40c829d Add doc. 2011-01-22 16:24:38 +09:00
6e978cae63 Move "blank background" code from EekGtkKeyboard to EekRenderer. 2011-01-22 16:13:53 +09:00
a0167c4cc2 Re-organize API.
EekGtkKeyboard is now a subclass of GtkWidget not EekKeyboard.  Widget
creation is done as follows:

layout = eek_xkl_layout_new (...);
keyboard = eek_keyboard_new (layout, 640, 480);
widget = eek_gtk_keyboard_new (keyboard);

Broken Clutter support is temporarily disabled.
2011-01-22 11:55:29 +09:00
cab893b4aa Remove unused EekContainer#find_element_by_position. 2011-01-22 11:42:56 +09:00
8399acda83 libeek: add EekKey#is_pressed. 2011-01-22 11:42:56 +09:00
12550f4bc3 Re-implement Cairo-based rendering. 2011-01-22 11:42:56 +09:00
2ec76cad54 Bump API version; ignore eek-marshallers.[ch]. 2011-01-22 11:42:52 +09:00
47602652e4 Fix coding-style. 2011-01-22 11:25:55 +09:00
158ddf2269 libeek: add new signal "keysym-index-changed" to EekKeyboard 2011-01-22 11:25:55 +09:00
71d5259f85 libeek: define new boxed type EekColor for colors 2011-01-22 11:25:51 +09:00
1ddf39b3da eekboard: replace GTK2_* with GTK_*. 2011-01-19 13:14:04 +09:00
8b9981970d Reorganize build infrastructure.
Generate glib marshallers for libeek, check for pangocairo instead of checking
pango and cairo individually, and link libeek against pango and cairo.
2011-01-19 12:37:06 +09:00
4accc5e2ac eekboard: don't use deprecated gtk_quit_add. 2011-01-13 16:05:54 +09:00
dc4e802bd1 libeek/gtk: add compatibility macro for gdk_cairo_create (>= 2.91.5) 2011-01-13 15:20:44 +09:00
7b368057e3 eekboard: set window opacity based on the gconf setting 2011-01-12 15:59:45 +09:00
2ea6fa9611 eekboard: support fullscreen mode 2011-01-12 15:59:16 +09:00
125fd4c65c libeek/gtk: fix scale and geometry calculation 2011-01-12 15:45:36 +09:00
cf4d1109d3 Update to 0.0.7. 2010-12-06 14:44:01 +09:00
c7c6d06907 eekboard: Reset modifiers just after normal key press. 2010-12-06 14:42:14 +09:00
384d43bb80 libeek: Fix gtk keyboard rendering. 2010-12-06 13:06:11 +09:00
29c55b6ca3 Suppress compiler warnings. 2010-12-06 12:12:52 +09:00
910b0be5a5 eekboard: listen xklavier status events. 2010-12-06 12:09:17 +09:00
706fa6310b Define AM_SILENT_RULES. 2010-12-06 11:33:32 +09:00
248699d771 eekboard: change the default behavior to "standalone" mode. 2010-12-06 11:19:47 +09:00
6343e37bc1 eekboard: reduce the number of allocs when parsing a config file. 2010-12-06 11:18:18 +09:00
f562e8c212 0.0.6 released. 2010-11-15 14:37:57 +09:00
8ff00226e2 Correct GTK API version in *.pc.in. 2010-11-15 14:35:03 +09:00
c72c75083c Fix typo. 2010-11-15 12:49:12 +09:00
862a54eac3 Fix build against libnotify >= 0.7.0. 2010-11-15 12:49:01 +09:00
12bc18e1ba Add compatibility code for GTK2. 2010-11-15 12:01:17 +09:00
f045bd0d50 Add --with-gtk configure option. 2010-11-15 11:46:12 +09:00
dfe06468ed Fix build against 2.91.5. 2010-11-12 15:12:56 +09:00
3fda8da1a5 libeek: forward decl structs to let g-ir-scanner inspect their fields. 2010-10-13 16:58:31 +09:00
d0a5715f8c libeek: Add setter for position/size of EekElement. 2010-10-13 16:21:12 +09:00
6b83bb8503 Clean up action groups on quit. 2010-10-13 15:04:41 +09:00
69f1dba96a Require clutter-gtk-1.0. 2010-09-08 10:13:33 +09:00
dcbdd7ff63 eekboard: fix AltGr handling. 2010-08-25 18:46:02 +09:00
9b28a011e7 Ignore generated files. 2010-08-23 14:50:00 +09:00
350598dc55 eekboard: handle AltGr 2010-08-20 18:39:06 +09:00
ae9df021c2 libeek: eek_keyboard_find_key_by_position(): consider overlapped sections. 2010-08-13 11:43:10 +09:00
d7cb78ecf5 libeek: suppress debug message if DEBUG is not set. 2010-08-13 10:44:08 +09:00
ef2e9acf1e Update TODO. 2010-08-13 10:43:17 +09:00
7f52069e41 libeek: terminate args of eek_xkb_layout_set_names_full() with NULL instead of -1. 2010-08-13 08:11:40 +09:00
9a5c0d9cdc libeek: more distcheck fixes. 2010-08-13 08:10:47 +09:00
154 changed files with 17401 additions and 7557 deletions

30
.gitignore vendored
View File

@ -30,13 +30,23 @@ libkeyactor*.tar.*
mkinstalldirs
m4/*.m4
gtk-doc.make
eek/eek-special-keysym-labels.h
eek/eek-unicode-keysym-labels.h
eek/eek-keyname-keysym-labels.h
eek/eek-special-keysym-entries.h
eek/eek-unicode-keysym-entries.h
eek/eek-xkeysym-keysym-entries.h
eek/eek-marshalers.[ch]
eek/*.pc
eek/*.gir
eek/*.typelib
eekboard/*.pc
eekboard/*.gir
eekboard/*.typelib
tests/eek-simple-test
tests/eek-xkb-test
src/eekboard
tests/eek-xml-test
src/eekboard-server
src/eekboard-client
src/eekboard-system-client
src/eekboard-xml
docs/reference/eek/*.stamp
docs/reference/eek/*.txt
!/docs/reference/eek/eek-sections.txt
@ -47,8 +57,18 @@ docs/reference/eek/eek.args
docs/reference/eek/eek.hierarchy
docs/reference/eek/eek.interfaces
docs/reference/eek/eek.prerequisites
docs/reference/eekboard/*.stamp
docs/reference/eekboard/*.txt
!/docs/reference/eekboard/eekboard-sections.txt
docs/reference/eekboard/xml
docs/reference/eekboard/html
docs/reference/eekboard/eekboard.signals
docs/reference/eekboard/eekboard.args
docs/reference/eekboard/eekboard.hierarchy
docs/reference/eekboard/eekboard.interfaces
docs/reference/eekboard/eekboard.prerequisites
po/*.gmo
po/Makefile.in.in
po/POTFILES
po/stamp-it
bindings/vala/*.vapi

View File

@ -1,5 +1,5 @@
# Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
# Copyright (C) 2010 Red Hat, Inc.
# 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
@ -17,6 +17,5 @@
# 02110-1301 USA
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = eek src tests bindings docs po
SUBDIRS = eek eekboard src tests bindings docs po data
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-introspection
EXTRA_DIST = eekboard-sample.conf

80
README
View File

@ -1,29 +1,75 @@
eekboard - a virtual keyboard for GNOME -*- outline -*-
eekboard - an easy to use virtual keyboard toolkit -*- outline -*-
eekboard is a virtual keyboard software package which ships with a
standalone virtual keyboard application ("eekboard"), and a library to
create keyboard-like UI ("libeek").
eekboard is a virtual keyboard software package, including a set of
tools to implement desktop virtual keyboards.
* Requirements
* How to build
* GLib2, GTK2, Cairo, Pango, Libxklavier...
* Clutter (optional)
* Clutter-Gtk (optional)
** Dependencies
* How to test
REQUIRED: GLib2, GTK, GConf2, PangoCairo, libxklavier
OPTIONAL: fakekey, CSPI, Clutter, Clutter-Gtk, Vala, gobject-introspection
If you build from git repo:
** Build from git repo
$ git clone git://github.com/ueno/eekboard.git
$ cd eekboard
$ ./autogen.sh --prefix=/usr --enable-gtk-doc
Otherwise start from here:
$ ./configure
$ make
$ sudo make install
$ eekboard
*NOTE* some version combination of Clutter & Clutter-Gtk does not
cooperate well. Try "EEKBOARD_DISABLE_CLUTTER=1 eekboard"
** Build from tarball
$ ./configure --prefix=/usr
$ make
$ sudo make install
* How to test
eekboard currently includes 4 tools to implement your own virtual
keyboard.
** eekboard-server
eekboard-server is a D-Bus server which is responsible for drawing
interactive on-screen keyboards. Since it has a D-Bus service
activation entry, you will not need to start it manually, but you can
do that with:
$ eekboard-server &
** eekboard-desktop-client
eekboard-desktop-client is a client of eekboard-server. It listens
desktop events (keyboard change, focus in/out, and keystroke) and
generates key events when some keys are pressed on the on-screen
keyboard. It can be started with:
$ eekboard-desktop-client
** eekboard-xml
eekboard-xml is a tool to manipulate XML keyboard description used by
eekboard-client tool and in the eekboard library.
To dump the current system keyboard layout into an XML file:
$ eekboard-xml --dump > keyboard.xml
You can display the dumped layout with:
$ eekboard-xml --load keyboard.xml
** eekboard-client
eekboard-client is a simple test client of eekboard-server. To upload
the keyboard description to the server, display it, and listen
key events.
$ eekboard-client --set-keyboard keyboard.xml --show-keyboard --listen
KeyPressed XXXXX
KeyReleased XXXXX
* Documentation
See file:docs/reference/eek/html/index.html

18
TODO
View File

@ -1,17 +1 @@
- packaging
-- debian
-- add more tests
- eekboard
-- a11y
-- display current configuration
-- notify user if there is no focused window
-- startup in the tray
-- rewrite in Vala
- libeek
-- Caribou layout engine (XML)
-- matchbox-keyboard layout engine (XML)
-- delay initialization of XKB and XKL layouts
-- add mechanism to change appearances (colors?) of UI widgets
depending on modifier states
See https://github.com/ueno/eekboard/wiki/TODO

View File

@ -19,6 +19,7 @@ which gnome-autogen.sh || {
}
ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I m4"
REQUIRED_AUTOMAKE_VERSION=1.8
REQUIRED_AUTOMAKE_VERSION=1.10
REQUIRED_AUTOCONF_VERSION=2.60
. gnome-autogen.sh

View File

@ -1,5 +1,5 @@
# Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
# Copyright (C) 2010 Red Hat, Inc.
# 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
@ -16,8 +16,12 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
if ENABLE_VALA
SUBDIRS = vala
else
SUBDIRS =
if ENABLE_PYTHON
SUBDIRS += python
endif
if ENABLE_VALA
SUBDIRS += vala
endif

View File

@ -0,0 +1,18 @@
# 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/>.
SUBDIRS = eekboard

View File

@ -0,0 +1,21 @@
# 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/>.
pkgpython_PYTHON = \
__init__.py \
eekboard.py \
context.py

View File

@ -0,0 +1,63 @@
# 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/>.
from gi.repository import Eek, EekXkl, Gio
from eekboard import Eekboard
from context import Context
Keyboard = Eek.Keyboard
Section = Eek.Section
Key = Eek.Key
Symbol = Eek.Symbol
Keysym = Eek.Keysym
MODIFIER_BEHAVIOR_NONE, \
MODIFIER_BEHAVIOR_LOCK, \
MODIFIER_BEHAVIOR_LATCH = \
(Eek.ModifierBehavior.NONE,
Eek.ModifierBehavior.LOCK,
Eek.ModifierBehavior.LATCH)
CSW = 640
CSH = 480
def XmlKeyboard(path, modifier_behavior=MODIFIER_BEHAVIOR_NONE):
_file = Gio.file_new_for_path(path)
layout = Eek.XmlLayout.new(_file.read())
keyboard = Eek.Keyboard.new(layout, CSW, CSH)
keyboard.set_modifier_behavior(modifier_behavior)
return keyboard
def XklKeyboard(modifier_behavior=MODIFIER_BEHAVIOR_NONE):
layout = EekXkl.Layout.new()
keyboard = Eek.Keyboard.new(layout, CSW, CSH)
keyboard.set_modifier_behavior(modifier_behavior)
return keyboard
__all__ = ['Eekboard',
'Context',
'Keyboard',
'Section',
'Key',
'Symbol',
'Keysym',
'MODIFIER_BEHAVIOR_NONE',
'MODIFIER_BEHAVIOR_LOCK',
'MODIFIER_BEHAVIOR_LATCH',
'XmlKeyboard',
'XklKeyboard']

View File

@ -0,0 +1,73 @@
# 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/>.
from gi.repository import Eekboard
import gobject
class Context(gobject.GObject):
__gtype_name__ = "PYEekboardContext"
__gsignals__ = {
'enabled': (
gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
()),
'disabled': (
gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
()),
'key-pressed': (
gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
(gobject.TYPE_UINT,)),
'key-released': (
gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
(gobject.TYPE_UINT,))
}
def __init__(self, giobject):
super(Context, self).__init__()
import sys
self.__giobject = giobject
self.__giobject.connect('enabled', lambda *args: self.emit('enabled'))
self.__giobject.connect('disabled', lambda *args: self.emit('disabled'))
self.__giobject.connect('key-pressed', lambda *args: self.emit('key-pressed', args[1]))
self.__giobject.connect('key-released', lambda *args: self.emit('key-released', args[1]))
def get_giobject(self):
return self.__giobject
def set_keyboard(self, keyboard):
self.__giobject.set_keyboard(keyboard, None)
def show_keyboard(self):
self.__giobject.show_keyboard(None)
def hide_keyboard(self):
self.__giobject.hide_keyboard(None)
def set_group(self, group):
self.__giobject.set_group(group, None)
def press_key(self, keycode):
self.__giobject.press_key(keycode, None)
def release_key(self, keycode):
self.__giobject.release_key(keycode, None)
def is_enabled(self):
return self.__giobject.is_enabled()

View File

@ -0,0 +1,42 @@
# 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/>.
from gi.repository import Gio
import gi.repository
import gobject
from context import Context
class Eekboard(gobject.GObject):
__gtype_name__ = "PYEekboardEekboard"
def __init__(self):
super(Eekboard, self).__init__()
self.__connection = Gio.bus_get_sync(Gio.BusType.SESSION, None)
self.__eekboard = gi.repository.Eekboard.Eekboard.new(self.__connection, None);
def create_context(self, client_name):
context = self.__eekboard.create_context(client_name, None)
return Context(context)
def push_context(self, context):
self.__eekboard.push_context(context.get_giobject(), None)
def pop_context(self):
self.__eekboard.pop_context(None)
def destroy_context(self, context):
self.__eekboard.destroy_context(context.get_giobject(), None)

View File

@ -1,5 +1,5 @@
# Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
# Copyright (C) 2010 Red Hat, Inc.
# 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
@ -31,20 +31,20 @@ eek-$(EEK_API_VERSION).vapi:
eek-clutter-$(EEK_API_VERSION).vapi: eek-$(EEK_API_VERSION).vapi
vapigen --vapidir=$(builddir) --library eek-clutter-$(EEK_API_VERSION) \
--pkg eek-0.1 --pkg clutter-1.0 \
--pkg eek-$(EEK_API_VERSION) --pkg clutter-1.0 \
eek-clutter-$(EEK_API_VERSION)/eek-clutter-$(EEK_API_VERSION).gi
eek-gtk-$(EEK_API_VERSION).vapi: eek-$(EEK_API_VERSION).vapi
vapigen --vapidir=$(builddir) --library eek-gtk-$(EEK_API_VERSION) \
--pkg eek-0.1 --pkg gtk+-2.0 \
--pkg eek-$(EEK_API_VERSION) --pkg gtk+-2.0 \
eek-gtk-$(EEK_API_VERSION)/eek-gtk-$(EEK_API_VERSION).gi
eek-xkb-$(EEK_API_VERSION).vapi: eek-$(EEK_API_VERSION).vapi
vapigen --vapidir=$(builddir) --library eek-xkb-$(EEK_API_VERSION) \
--pkg eek-0.1 \
--pkg eek-$(EEK_API_VERSION) \
eek-xkb-$(EEK_API_VERSION)/eek-xkb-$(EEK_API_VERSION).gi
eek-xkl-$(EEK_API_VERSION).vapi: eek-xkb-$(EEK_API_VERSION).vapi
vapigen --vapidir=$(builddir) --library eek-xkl-$(EEK_API_VERSION) \
--pkg eek-0.1 --pkg eek-xkb-0.1 \
--pkg eek-$(EEK_API_VERSION) --pkg eek-xkb-$(EEK_API_VERSION) \
eek-xkl-$(EEK_API_VERSION)/eek-xkl-$(EEK_API_VERSION).gi

View File

@ -1,5 +1,5 @@
# Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
# Copyright (C) 2010 Red Hat, Inc.
# 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
@ -16,38 +16,154 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
AC_INIT([eekboard], [0.0.5], [ueno@unixuser.org])
AC_CONFIG_SRCDIR([configure.ac])
AC_PREREQ(2.63)
AM_INIT_AUTOMAKE
AM_PROG_CC_C_O
dnl AC_CONFIG_SRCDIR([configure.ac])
AC_CONFIG_MACRO_DIR([m4])
AC_INIT([eekboard], [0.90.2], [ueno@unixuser.org])
dnl Init automake
AM_INIT_AUTOMAKE
AM_MAINTAINER_MODE([enable])
AC_GNU_SOURCE
dnl Support silent build
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
dnl Check for programs
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_CC_STDC
AC_PROG_INSTALL
AC_PROG_CXX
# define PACKAGE_VERSION_* variables
AM_DISABLE_STATIC
AC_ISC_POSIX
AC_HEADER_STDC
LT_INIT
IT_PROG_INTLTOOL([0.35.0])
PKG_CHECK_MODULES([GLIB2], [glib-2.0], ,
AC_MSG_CHECKING([which gtk+ version to compile against])
AC_ARG_WITH([gtk],
[AS_HELP_STRING([--with-gtk=2.0|3.0],[which gtk+ version to compile against (default: 2.0)])],
[case "$with_gtk" in
2.0|3.0) ;;
*) AC_MSG_ERROR([invalid gtk version specified]) ;;
esac],
[with_gtk=2.0])
AC_MSG_RESULT([$with_gtk])
case "$with_gtk" in
2.0) GTK_API_VERSION=2.0
GTK_REQUIRED=2.14.0
EEK_API_VERSION=0.90
EEK_API_MAJOR_VERSION=0
EEK_API_MINOR_VERSION=90
EEK_API_PC_VERSION=0.90
EEK_LIBRARY_SUFFIX="-$EEK_API_VERSION"
;;
3.0) GTK_API_VERSION=3.0
GTK_REQUIRED=2.91.0
EEK_API_VERSION=0.90
EEK_API_MAJOR_VERSION=0
EEK_API_MINOR_VERSION=90
EEK_API_PC_VERSION=0.90
EEK_LIBRARY_SUFFIX="-$EEK_API_VERSION"
;;
esac
AC_SUBST([GTK_API_VERSION])
AC_SUBST([EEK_API_VERSION])
AC_SUBST([EEK_API_MAJOR_VERSION])
AC_SUBST([EEK_API_MINOR_VERSION])
AC_SUBST([EEK_API_PC_VERSION])
AC_SUBST([EEK_LIBRARY_SUFFIX])
AC_SUBST([EEK_LIBRARY_SUFFIX_U],[AS_TR_SH([$EEK_LIBRARY_SUFFIX])])
AM_CONDITIONAL([HAVE_GTK_2],[test "$with_gtk" = "2.0"])
AM_CONDITIONAL([HAVE_GTK_3],[test "$with_gtk" = "3.0"])
AM_PATH_GLIB_2_0
PKG_CHECK_MODULES([GLIB2], [glib-2.0 >= 2.25.4], ,
[AC_MSG_ERROR([GLib2 not found])])
PKG_CHECK_MODULES([GOBJECT2], [gobject-2.0], ,
[AC_MSG_ERROR([GObject2 not found])])
PKG_CHECK_MODULES([CAIRO], [cairo], ,
[AC_MSG_ERROR([Cairo not found])])
PKG_CHECK_MODULES([PANGO], [pango], ,
[AC_MSG_ERROR([Pango not found])])
PKG_CHECK_MODULES([GTK2], [gtk+-2.0 gdk-2.0], ,
[AC_MSG_ERROR([GTK2 not found])])
PKG_CHECK_MODULES([GIO2], [gio-2.0], ,
[AC_MSG_ERROR([Gio2 not found])])
PKG_CHECK_MODULES([PANGOCAIRO], [pangocairo], ,
[AC_MSG_ERROR([PangoCairo not found])])
PKG_CHECK_MODULES([GTK], [
gtk+-$GTK_API_VERSION >= $GTK_REQUIRED
gdk-$GTK_API_VERSION >= $GTK_REQUIRED], ,
[AC_MSG_ERROR([GTK not found])])
PKG_CHECK_MODULES([GCONF2], [gconf-2.0], ,
[AC_MSG_ERROR([GConf not found])])
PKG_CHECK_MODULES([XKB], [x11], ,
[AC_MSG_ERROR([XKB support not found])])
PKG_CHECK_MODULES([LIBXKLAVIER], [libxklavier x11], ,
[AC_MSG_ERROR([Libxklavier not found])])
PKG_CHECK_MODULES([LIBFAKEKEY], [libfakekey], ,
[AC_MSG_ERROR([libfakekey not found])])
PKG_CHECK_MODULES([CSPI], [cspi-1.0], ,
[AC_MSG_ERROR([AT-SPI C not found])])
PKG_CHECK_MODULES([NOTIFY], [libnotify], ,
[AC_MSG_ERROR([libnotify not found])])
dnl use libfakekey to generate key events
AC_MSG_CHECKING([whether you enable fakekey])
AC_ARG_ENABLE(fakekey,
AS_HELP_STRING([--enable-fakekey=no/yes],
[Enable fakekey default=yes]),,
enable_fakekey=yes)
if test x$enable_fakekey = xyes; then
PKG_CHECK_MODULES([FAKEKEY], [libfakekey], ,
[AC_MSG_ERROR([fakekey not found])])
AC_DEFINE([HAVE_FAKEKEY], [1], [Define if fakekey is found])
fi
AM_CONDITIONAL(ENABLE_FAKEKEY, [test x$enable_fakekey = xyes])
AC_MSG_RESULT($enable_fakekey)
dnl use AT-SPI to capture focus/keystroke events
AC_MSG_CHECKING([whether you enable AT-SPI event handling])
AC_ARG_ENABLE(cspi,
AS_HELP_STRING([--enable-cspi=no/yes],
[Enable AT-SPI event handling default=yes]),,
enable_cspi=yes)
if test x$enable_cspi = xyes; then
PKG_CHECK_MODULES([CSPI], [cspi-1.0], ,
[AC_MSG_ERROR([AT-SPI C not found])])
AC_DEFINE([HAVE_CSPI], [1], [Define if CSPI is found])
fi
AC_MSG_RESULT($enable_cspi)
AM_CONDITIONAL(ENABLE_CSPI, [test x$enable_cspi = xyes])
dnl Python language binding
AC_MSG_CHECKING([whether you enable Python language support])
AC_ARG_ENABLE(python,
AS_HELP_STRING([--enable-python=no/yes],
[Enable Python language binding default=yes]),,
enable_python=yes)
AC_MSG_RESULT($enable_python)
AM_CONDITIONAL(ENABLE_PYTHON, [test x$enable_python = xyes])
if test x"$enable_python" = x"yes"; then
# check python
AM_PATH_PYTHON([2.5])
AC_PATH_PROG(PYTHON_CONFIG, python$PYTHON_VERSION-config)
if test x"$PYTHON_CONFIG" = x""; then
AC_PATH_PROG(PYTHON_CONFIG, python-config)
fi
if test x"$PYTHON_CONFIG" != x""; then
PYTHON_CFLAGS=`$PYTHON_CONFIG --includes`
PYTHON_LIBS=`$PYTHON_CONFIG --libs`
else
PYTHON_CFLAGS=`$PYTHON $srcdir/python-config.py --includes`
PYTHON_LIBS=`$PYTHON $srcdir/python-config.py --libs`
fi
PYTHON_INCLUDES="$PYTHON_CFLAGS"
AC_SUBST(PYTHON_CFLAGS)
AC_SUBST(PYTHON_INCLUDES)
AC_SUBST(PYTHON_LIBS)
else
enable_python="no (disabled, use --enable-python to enable)"
fi
dnl Vala langauge binding
AC_MSG_CHECKING([whether you enable Vala language support])
AC_ARG_ENABLE(vala,
AS_HELP_STRING([--enable-vala=no/yes],
@ -56,6 +172,7 @@ AC_ARG_ENABLE(vala,
AC_MSG_RESULT($enable_vala)
AM_CONDITIONAL(ENABLE_VALA, [test x$enable_vala = xyes])
dnl standalone application
AC_MSG_CHECKING([whether you enable eekboard])
AC_ARG_ENABLE(eekboard,
AS_HELP_STRING([--enable-eekboard=no/yes],
@ -64,32 +181,32 @@ AC_ARG_ENABLE(eekboard,
AC_MSG_RESULT($enable_eekboard)
AM_CONDITIONAL(ENABLE_EEKBOARD, [test x$enable_eekboard = xyes])
dnl Clutter
AC_MSG_CHECKING([whether you enable Clutter])
AC_ARG_ENABLE(clutter,
AS_HELP_STRING([--enable-clutter=no/yes],
[Enable Clutter user interface default=yes]),,
enable_clutter=yes)
enable_clutter=no)
AC_MSG_RESULT($enable_clutter)
if test x$enable_clutter = xyes; then
PKG_CHECK_MODULES([CLUTTER], [clutter-1.0], ,
[AC_MSG_ERROR([Clutter not found -- install it or add --disable-clutter])])
AC_DEFINE([HAVE_CLUTTER], [1], [Define if Clutter is found])
need_swap_event_workaround=no
PKG_CHECK_MODULES([CLUTTER_GTK], [clutter-gtk-0.90],,
have_clutter_gtk=0
need_swap_event_workaround=0
PKG_CHECK_MODULES([CLUTTER_GTK], [clutter-gtk-1.0], [have_clutter_gtk=1],
[PKG_CHECK_MODULES([CLUTTER_GTK], [clutter-gtk-0.10 clutter-x11-1.0],
[need_swap_event_workaround=yes])])
AC_DEFINE([HAVE_CLUTTER_GTK], [1], [Define if Clutter-Gtk is found])
AC_DEFINE([NEED_SWAP_EVENT_WORKAROUND], [1],
[have_clutter_gtk=1; need_swap_event_workaround=1])])
AC_DEFINE_UNQUOTED([HAVE_CLUTTER_GTK], $have_clutter_gtk,
[Define if Clutter-Gtk is found])
AC_DEFINE_UNQUOTED([NEED_SWAP_EVENT_WORKAROUND], $need_swap_event_workaround,
[Define if GLX_INTEL_swap_event work around is needed])
fi
AM_CONDITIONAL(HAVE_CLUTTER, [test x$enable_clutter = xyes])
AM_CONDITIONAL(ENABLE_CLUTTER, [test x$enable_clutter = xyes])
GTK_DOC_CHECK([1.14],[--flavour no-tmpl])
EEK_API_VERSION=0.1
AC_SUBST(EEK_API_VERSION)
dnl to re-generate eek/*-keysym-labels.txt
AC_CHECK_PROGS([PYTHON], [python])
@ -102,20 +219,43 @@ AM_GLIB_DEFINE_LOCALEDIR(EEKBOARD_LOCALEDIR)
GOBJECT_INTROSPECTION_CHECK([0.6.7])
AC_CONFIG_HEADERS([eek/config.h])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile
eek/Makefile
eekboard/Makefile
src/Makefile
tests/Makefile
bindings/Makefile
bindings/python/Makefile
bindings/python/eekboard/Makefile
bindings/vala/Makefile
docs/Makefile
docs/reference/Makefile
docs/reference/eek/Makefile
docs/reference/eekboard/Makefile
po/Makefile.in
data/Makefile
data/icons/Makefile
data/icons/16x16/Makefile
data/icons/22x22/Makefile
data/icons/24x24/Makefile
data/icons/32x32/Makefile
data/icons/48x48/Makefile
data/icons/scalable/Makefile
eek/eek-${EEK_API_VERSION}.pc
eek/eek-clutter-${EEK_API_VERSION}.pc
eek/eek-gtk-${EEK_API_VERSION}.pc
eek/eek-xkb-${EEK_API_VERSION}.pc
eek/eek-xkl-${EEK_API_VERSION}.pc])
eek/eek-xkl-${EEK_API_VERSION}.pc
eekboard/eekboard-${EEK_API_VERSION}.pc])
AC_OUTPUT
AC_MSG_RESULT([
Build options:
Version $VERSION
Install prefix $prefix
Build shared libs $enable_shared
Build static libs $enable_static
CFLAGS $CFLAGS
Build vala binding $enable_vala
Build document $enable_gtk_doc
])

1
data/Makefile.am Normal file
View File

@ -0,0 +1 @@
SUBDIRS = icons

View File

@ -0,0 +1,16 @@
size = 16x16
icondir = $(datadir)/icons/hicolor/$(size)/apps
dist_icon_DATA = eekboard.png
gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor
install-data-hook:
@-if test -z "$(DESTDIR)"; then \
echo "Updating Gtk icon cache."; \
$(gtk_update_icon_cache); \
else \
echo "*** Icon cache not updated. After install, run this:"; \
echo "*** $(gtk_update_icon_cache)"; \
fi

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

View File

@ -0,0 +1,16 @@
size = 22x22
icondir = $(datadir)/icons/hicolor/$(size)/apps
dist_icon_DATA = eekboard.png
gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor
install-data-hook:
@-if test -z "$(DESTDIR)"; then \
echo "Updating Gtk icon cache."; \
$(gtk_update_icon_cache); \
else \
echo "*** Icon cache not updated. After install, run this:"; \
echo "*** $(gtk_update_icon_cache)"; \
fi

Binary file not shown.

After

Width:  |  Height:  |  Size: 892 B

View File

@ -0,0 +1,16 @@
size = 24x24
icondir = $(datadir)/icons/hicolor/$(size)/apps
dist_icon_DATA = eekboard.png
gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor
install-data-hook:
@-if test -z "$(DESTDIR)"; then \
echo "Updating Gtk icon cache."; \
$(gtk_update_icon_cache); \
else \
echo "*** Icon cache not updated. After install, run this:"; \
echo "*** $(gtk_update_icon_cache)"; \
fi

Binary file not shown.

After

Width:  |  Height:  |  Size: 957 B

View File

@ -0,0 +1,16 @@
size = 32x32
icondir = $(datadir)/icons/hicolor/$(size)/apps
dist_icon_DATA = eekboard.png
gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor
install-data-hook:
@-if test -z "$(DESTDIR)"; then \
echo "Updating Gtk icon cache."; \
$(gtk_update_icon_cache); \
else \
echo "*** Icon cache not updated. After install, run this:"; \
echo "*** $(gtk_update_icon_cache)"; \
fi

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,16 @@
size = 48x48
icondir = $(datadir)/icons/hicolor/$(size)/apps
dist_icon_DATA = eekboard.png
gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor
install-data-hook:
@-if test -z "$(DESTDIR)"; then \
echo "Updating Gtk icon cache."; \
$(gtk_update_icon_cache); \
else \
echo "*** Icon cache not updated. After install, run this:"; \
echo "*** $(gtk_update_icon_cache)"; \
fi

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

1
data/icons/Makefile.am Normal file
View File

@ -0,0 +1 @@
SUBDIRS = 16x16 22x22 24x24 32x32 48x48 scalable

View File

@ -0,0 +1,14 @@
icondir = $(datadir)/icons/hicolor/scalable/apps
dist_icon_DATA = eekboard.svg
gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor
install-data-hook:
@-if test -z "$(DESTDIR)"; then \
echo "Updating Gtk icon cache."; \
$(gtk_update_icon_cache); \
else \
echo "*** Icon cache not updated. After install, run this:"; \
echo "*** $(gtk_update_icon_cache)"; \
fi

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 472 KiB

View File

@ -1,5 +1,5 @@
# Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
# Copyright (C) 2010 Red Hat, Inc.
# 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

View File

@ -1,5 +1,5 @@
# Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
# Copyright (C) 2010 Red Hat, Inc.
# 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
@ -16,4 +16,4 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
SUBDIRS = eek
SUBDIRS = eek eekboard

View File

@ -1,5 +1,5 @@
# Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
# Copyright (C) 2010 Red Hat, Inc.
# 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
@ -47,7 +47,7 @@ SCANGOBJ_OPTIONS=
# Extra options to supply to gtkdoc-scan.
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
SCAN_OPTIONS=
SCAN_OPTIONS=--rebuild-types
# Extra options to supply to gtkdoc-mkdb.
# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
@ -76,13 +76,15 @@ EXTRA_HFILES=
# Header files to ignore when scanning. Use base file name, no paths
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
IGNORE_HFILES= eek-private.h \
eek-drawing.h \
eek-clutter-key.h \
IGNORE_HFILES = \
config.h \
eek-renderer.h \
eek-clutter-renderer.h \
eek-clutter-section.h \
eek-clutter-key-actor.h \
eek-clutter-drawing-context.h \
config.h
eek-clutter-key.h
if !ENABLE_CLUTTER
IGNORE_HFILES += eek-clutter-keyboard.h eek-clutter.h
endif
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
@ -102,16 +104,19 @@ expand_content_files=eek-overview.xml
# signals and properties.
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS = $(GOBJECT2_CFLAGS)
GTKDOC_LIBS = $(top_srcdir)/eek/libeek.la \
$(top_srcdir)/eek/libeek-gtk.la \
$(top_srcdir)/eek/libeek-xkb.la \
$(top_srcdir)/eek/libeek-xkl.la \
$(GOBJECT2_LIBS) \
GTKDOC_CFLAGS = $(GIO2_CFLAGS)
GTKDOC_LIBS = $(top_builddir)/eek/libeek.la \
$(top_builddir)/eek/libeek-gtk.la \
$(top_builddir)/eek/libeek-xkb.la \
$(top_builddir)/eek/libeek-xkl.la \
$(GIO2_LIBS) \
$(GTK_LIBS) \
$(XKB_LIBS)
if HAVE_CLUTTER
GTKDOC_LIBS += $(top_srcdir)/eek/libeek-clutter.la $(CLUTTER_LIBS)
if ENABLE_CLUTTER
GTKDOC_LIBS += \
$(top_builddir)/eek/libeek-clutter.la \
$(CLUTTER_LIBS)
endif
# This includes the standard gtk-doc make rules, copied by gtkdocize.

View File

@ -8,15 +8,15 @@
<bookinfo>
<title>libeek Reference Manual</title>
<releaseinfo>
for libeek 0.0.5.
for libeek 0.90.0.
</releaseinfo>
<copyright>
<year>2010</year>
<year>2010-2011</year>
<holder>Daiki Ueno</holder>
</copyright>
<copyright>
<year>2010</year>
<year>2010-2011</year>
<holder>Red Hat, Inc.</holder>
</copyright>
@ -37,14 +37,16 @@
<title>API Manual</title>
<chapter>
<title>Base Classes, Interfaces, and Utilities</title>
<xi:include href="xml/eek-serializable.xml"/>
<xi:include href="xml/eek-element.xml"/>
<xi:include href="xml/eek-container.xml"/>
<xi:include href="xml/eek-keyboard.xml"/>
<xi:include href="xml/eek-section.xml"/>
<xi:include href="xml/eek-key.xml"/>
<xi:include href="xml/eek-symbol.xml"/>
<xi:include href="xml/eek-keysym.xml"/>
<xi:include href="xml/eek-layout.xml"/>
<xi:include href="xml/eek-types.xml"/>
<xi:include href="xml/eek-keysym.xml"/>
</chapter>
<chapter>
<title>Clutter Keyboard</title>
@ -62,6 +64,11 @@
<title>XKB Layout Engine</title>
<xi:include href="xml/eek-xkb-layout.xml"/>
</chapter>
<chapter>
<title>XML Layout Engine</title>
<xi:include href="xml/eek-xml-layout.xml"/>
<xi:include href="xml/eek-xml.xml"/>
</chapter>
<chapter id="object-tree">
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml"/>

View File

@ -25,36 +25,32 @@
#ClutterActor:</para>
<informalexample>
<programlisting>
EekKeyboard *keyboard;
EekLayout *layout;
EekKeyboard *keyboard;
ClutterActor *actor;
/* Create a keyboard layout using libxklavier configuration. */
/* Create a layout engine based on libxklavier configuration. */
layout = eek_xkl_layout_new ();
/* Create a keyboard implemented as ClutterActor. */
keyboard = eek_clutter_keyboard_new ();
/* Create a keyboard from the given layout. */
keyboard = eek_keyboard_new (layout, initial_width, initial_height);
/* Apply the layout to the keyboard. */
eek_keyboard_set_layout (keyboard, layout);
/* Create a ClutterActor. */
actor = eek_clutter_keyboard_new (eekboard->keyboard);
clutter_group_add (CLUTTER_GROUP(stage),
eek_clutter_keyboard_get_actor (EEK_CLUTTER_KEYBOARD(keyboard)));
/* Add the actor to a stage. */
clutter_group_add (CLUTTER_GROUP(stage), actor);
</programlisting>
</informalexample>
<para>The most interesting feature of libeek is that developer can
choose arbitrary combination of UI toolkits and layout engine
supported by libeek. For example, to create a keyboard-like
#GtkWidget instead of #ClutterActor, all you need is to replace
eek_clutter_keyboard_new() with eek_gtk_keyboard_new() and
eek_clutter_keyboard_get_actor() with
eek_gtk_keyboard_get_widget(). Similarly, if you want to use XKB
configuration directly (without libxklavier), you will only need to
replace eek_xkl_layout_new () with eek_xkb_layout_new().</para>
<para>libeek currently supports GTK+ and Clutter as UI toolkits.
To create a keyboard-like #GtkWidget instead of #ClutterActor,
replace eek_clutter_keyboard_new() with eek_gtk_keyboard_new().
Similarly, if you want to use XKB configuration directly (without
libxklavier), you will only need to replace eek_xkl_layout_new ()
with eek_xkb_layout_new().</para>
<para>To achieve portability across different UI toolkits,
there is a seperate represention of keyboard elements apart from
the actual UI widgets. For example, a keyboard is represented as a tree of
<para>In the above example, a keyboard is represented as a tree of
#EekElement -- #EekKeyboard contains one or more #EekSection's and
#EekSection contains one or more #EekKey's. Each element may emit
events when user pushes the corresponding UI widget.</para>

View File

@ -4,12 +4,23 @@
EekKeyboardClass
EekKeyboardPrivate
EekKeyboard
eek_keyboard_set_keysym_index
eek_keyboard_get_keysym_index
eek_keyboard_new
eek_keyboard_get_layout
eek_keyboard_get_size
eek_keyboard_set_size
eek_keyboard_set_symbol_index
eek_keyboard_get_symbol_index
eek_keyboard_set_group
eek_keyboard_set_level
eek_keyboard_get_group
eek_keyboard_get_level
eek_keyboard_set_modifier_behavior
eek_keyboard_get_modifier_behavior
eek_keyboard_get_modifiers
eek_keyboard_create_section
eek_keyboard_set_layout
eek_keyboard_realize
eek_keyboard_find_key_by_keycode
eek_keyboard_add_outline
eek_keyboard_get_outline
<SUBSECTION Standard>
EEK_KEYBOARD
EEK_IS_KEYBOARD
@ -23,16 +34,16 @@ EEK_KEYBOARD_GET_CLASS
<SECTION>
<FILE>eek-layout</FILE>
<TITLE>EekLayout</TITLE>
EekLayoutIface
EekLayoutClass
EekLayout
eek_layout_apply
eek_layout_get_group
<SUBSECTION Standard>
EEK_LAYOUT
EEK_IS_LAYOUT
EEK_TYPE_LAYOUT
eek_layout_get_type
EEK_LAYOUT_GET_IFACE
EEK_LAYOUT_CLASS
EEK_IS_LAYOUT_CLASS
EEK_LAYOUT_GET_CLASS
</SECTION>
<SECTION>
@ -42,7 +53,6 @@ EekGtkKeyboard
EekGtkKeyboardClass
EekGtkKeyboardPrivate
eek_gtk_keyboard_new
eek_gtk_keyboard_get_widget
<SUBSECTION Standard>
EEK_GTK_KEYBOARD
EEK_IS_GTK_KEYBOARD
@ -86,7 +96,7 @@ EekCompareFunc
EekContainer
eek_container_foreach_child
eek_container_find
eek_container_find_by_position
eek_container_add_child
<SUBSECTION Standard>
EEK_CONTAINER
EEK_IS_CONTAINER
@ -104,7 +114,6 @@ EekClutterKeyboard
EekClutterKeyboardClass
EekClutterKeyboardPrivate
eek_clutter_keyboard_new
eek_clutter_keyboard_get_actor
<SUBSECTION Standard>
EEK_CLUTTER_KEYBOARD
EEK_IS_CLUTTER_KEYBOARD
@ -115,6 +124,33 @@ EEK_IS_CLUTTER_KEYBOARD_CLASS
EEK_CLUTTER_KEYBOARD_GET_CLASS
</SECTION>
<SECTION>
<FILE>eek-symbol</FILE>
<TITLE>EekSymbol</TITLE>
EekSymbolCategory
EekSymbolClass
EekSymbolPrivate
EekSymbol
eek_symbol_new
eek_symbol_set_name
eek_symbol_get_name
eek_symbol_set_label
eek_symbol_get_label
eek_symbol_set_category
eek_symbol_get_category
eek_symbol_get_modifier_mask
eek_symbol_set_modifier_mask
eek_symbol_is_modifier
<SUBSECTION Standard>
EEK_SYMBOL
EEK_IS_SYMBOL
EEK_TYPE_SYMBOL
eek_symbol_get_type
EEK_SYMBOL_CLASS
EEK_IS_SYMBOL_CLASS
EEK_SYMBOL_GET_CLASS
</SECTION>
<SECTION>
<FILE>eek-xkl-layout</FILE>
<TITLE>EekXklLayout</TITLE>
@ -128,12 +164,12 @@ eek_xkl_layout_set_model
eek_xkl_layout_set_layouts
eek_xkl_layout_set_variants
eek_xkl_layout_set_options
eek_xkl_layout_enable_option
eek_xkl_layout_disable_option
eek_xkl_layout_get_model
eek_xkl_layout_get_layouts
eek_xkl_layout_get_variants
eek_xkl_layout_get_options
eek_xkl_layout_disable_option
eek_xkl_layout_enable_option
eek_xkl_layout_get_option
<SUBSECTION Standard>
EEK_XKL_LAYOUT
@ -154,6 +190,7 @@ EekXkbLayoutPrivate
eek_xkb_layout_new
eek_xkb_layout_set_names
eek_xkb_layout_set_names_full
eek_xkb_layout_set_names_full_valist
eek_xkb_layout_set_keycodes
eek_xkb_layout_set_geometry
eek_xkb_layout_set_symbols
@ -178,15 +215,16 @@ EekKeyPrivate
EekKey
eek_key_set_keycode
eek_key_get_keycode
eek_key_set_keysyms
eek_key_get_keysyms
eek_key_get_keysym
eek_key_set_symbol_matrix
eek_key_get_symbol_matrix
eek_key_get_symbol
eek_key_get_symbol_with_fallback
eek_key_get_symbol_at_index
eek_key_set_index
eek_key_get_index
eek_key_set_outline
eek_key_get_outline
eek_key_set_keysym_index
eek_key_get_keysym_index
eek_key_set_oref
eek_key_get_oref
eek_key_is_pressed
<SUBSECTION Standard>
EEK_KEY
EEK_IS_KEY
@ -197,6 +235,21 @@ EEK_IS_KEY_CLASS
EEK_KEY_GET_CLASS
</SECTION>
<SECTION>
<FILE>eek-serializable</FILE>
<TITLE>EekSerializable</TITLE>
EekSerializable
EekSerializableIface
eek_serializable_serialize
eek_serializable_deserialize
<SUBSECTION Standard>
EEK_SERIALIZABLE
EEK_IS_SERIALIZABLE
EEK_TYPE_SERIALIZABLE
eek_serializable_get_type
EEK_SERIALIZABLE_GET_IFACE
</SECTION>
<SECTION>
<FILE>eek-element</FILE>
<TITLE>EekElement</TITLE>
@ -209,6 +262,8 @@ eek_element_set_name
eek_element_get_name
eek_element_set_bounds
eek_element_get_bounds
eek_element_set_position
eek_element_set_size
eek_element_get_absolute_position
<SUBSECTION Standard>
EEK_ELEMENT
@ -221,28 +276,79 @@ EEK_ELEMENT_GET_CLASS
</SECTION>
<SECTION>
<FILE>eek-types</FILE>
EekOrientation
EekKeysymMatrix
EEK_TYPE_KEYSYM_MATRIX
eek_keysym_matrix_get_type
EekPoint
EEK_TYPE_POINT
eek_point_get_type
EekBounds
EEK_TYPE_BOUNDS
eek_bounds_get_type
eek_bounds_long_side
EekOutline
EEK_TYPE_OUTLINE
eek_outline_get_type
<FILE>eek-xml-layout</FILE>
<TITLE>EekXmlLayout</TITLE>
EekXmlLayout
EekXmlLayoutClass
EekXmlLayoutPrivate
eek_xml_layout_new
eek_xml_layout_set_source
eek_xml_layout_get_source
<SUBSECTION Standard>
EEK_XML_LAYOUT
EEK_IS_XML_LAYOUT
EEK_TYPE_XML_LAYOUT
eek_xml_layout_get_type
EEK_XML_LAYOUT_CLASS
EEK_IS_XML_LAYOUT_CLASS
EEK_XML_LAYOUT_GET_CLASS
</SECTION>
<SECTION>
<FILE>eek-keysym</FILE>
<TITLE>EekKeysym</TITLE>
EEK_KEYSYM
EekKeysymClass
EekKeysymPrivate
EekKeysym
eek_keysym_new
eek_keysym_get_xkeysym
eek_keysym_new_from_name
<SUBSECTION Standard>
EEK_INVALID_KEYSYM
EEK_INVALID_KEYCODE
EekKeysymCategory
eek_keysym_to_string
eek_keysym_get_category
EEK_IS_KEYSYM
EEK_TYPE_KEYSYM
eek_keysym_get_type
EEK_KEYSYM_CLASS
EEK_IS_KEYSYM_CLASS
EEK_KEYSYM_GET_CLASS
</SECTION>
<SECTION>
<FILE>eek-xml</FILE>
EEK_XML_SCHEMA_VERSION
eek_keyboard_output
</SECTION>
<SECTION>
<FILE>eek-types</FILE>
I_
EEK_TYPE_SYMBOL_MATRIX
EEK_TYPE_POINT
EEK_TYPE_BOUNDS
EEK_TYPE_OUTLINE
EEK_TYPE_COLOR
EekOrientation
EekModifierBehavior
EekModifierType
EEK_INVALID_KEYCODE
EekSymbolMatrix
EekPoint
EekBounds
EekOutline
EekColor
eek_symbol_matrix_get_type
eek_symbol_matrix_new
eek_symbol_matrix_copy
eek_symbol_matrix_free
eek_point_get_type
eek_point_rotate
eek_bounds_get_type
eek_bounds_long_side
eek_outline_get_type
eek_outline_copy
eek_outline_free
eek_color_get_type
eek_color_new
</SECTION>

View File

@ -0,0 +1,120 @@
# 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
## Process this file with automake to produce Makefile.in
# We require automake 1.6 at least.
AUTOMAKE_OPTIONS = 1.6
# This is a blank Makefile.am for using gtk-doc.
# Copy this to your project's API docs directory and modify the variables to
# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
# of using the various options.
# The name of the module, e.g. 'glib'.
DOC_MODULE=eekboard
# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
#DOC_MODULE_VERSION=2
# The top-level SGML file. You can change this if you want to.
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
# The directory containing the source code. Relative to $(srcdir).
# gtk-doc will search all .c & .h files beneath here for inline comments
# documenting the functions and macros.
# e.g. DOC_SOURCE_DIR=../../../gtk
DOC_SOURCE_DIR=../../../eekboard
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
SCANGOBJ_OPTIONS=
# Extra options to supply to gtkdoc-scan.
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
SCAN_OPTIONS=
# Extra options to supply to gtkdoc-mkdb.
# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
MKDB_OPTIONS=--sgml-mode --output-format=xml
# Extra options to supply to gtkdoc-mktmpl
# e.g. MKTMPL_OPTIONS=--only-section-tmpl
MKTMPL_OPTIONS=
# Extra options to supply to gtkdoc-mkhtml
MKHTML_OPTIONS=
# Extra options to supply to gtkdoc-fixref. Not normally needed.
# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
FIXXREF_OPTIONS=
# Used for dependencies. The docs will be rebuilt if any of these change.
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
HFILE_GLOB=$(top_srcdir)/eekboard/*.h
CFILE_GLOB=$(top_srcdir)/eekboard/*.c
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
EXTRA_HFILES=
# Header files to ignore when scanning. Use base file name, no paths
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
IGNORE_HFILES=config.h eekboard.h
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
HTML_IMAGES=
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
# content_files=eekboard-overview.xml
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
# These files must be listed here *and* in content_files
# e.g. expand_content_files=running.sgml
# expand_content_files=eekboard-overview.xml
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
# signals and properties.
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS = $(GIO2_CFLAGS)
GTKDOC_LIBS = $(top_builddir)/eekboard/libeekboard.la $(GIO2_LIBS)
# This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make
# Other files to distribute
# e.g. EXTRA_DIST += version.xml.in
# EXTRA_DIST +=
# Files not to distribute
# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
#DISTCLEANFILES +=
# Comment this out if you want your docs-status tested during 'make check'
if ENABLE_GTK_DOC
#TESTS_ENVIRONMENT = cd $(srcsrc) &&
#TESTS = $(GTKDOC_CHECK)
endif
-include $(top_srcdir)/gtk-doc.mk

View File

@ -0,0 +1,51 @@
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
]>
<book id="index">
<bookinfo>
<title>eekboard Reference Manual</title>
<releaseinfo>
for eekboard 0.90.0.
</releaseinfo>
<copyright>
<year>2011</year>
<holder>Daiki Ueno</holder>
</copyright>
<copyright>
<year>2011</year>
<holder>Red Hat, Inc.</holder>
</copyright>
<legalnotice>
<para>
Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation License,
Version 1.3 or any later version published by the Free Software
Foundation; with no Invariant Sections, no Front-Cover Texts and
no Back-Cover Texts. A copy of the license is included in the
section entitled "GNU Free Documentation License".
</para>
</legalnotice>
</bookinfo>
<part id="apireference">
<title>API Manual</title>
<chapter>
<title>D-Bus client interface to eekboard-server</title>
<xi:include href="xml/eekboard-eekboard.xml"/>
<xi:include href="xml/eekboard-context.xml"/>
</chapter>
<chapter id="object-tree">
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml"/>
</chapter>
<index id="api-index-full">
<title>API Index</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
</index>
</part>
</book>

View File

@ -0,0 +1,47 @@
<SECTION>
<FILE>eekboard-eekboard</FILE>
<TITLE>EekboardEekboard</TITLE>
EekboardEekboard
EekboardEekboardClass
EekboardEekboardPrivate
eekboard_eekboard_new
eekboard_eekboard_create_context
eekboard_eekboard_push_context
eekboard_eekboard_pop_context
eekboard_eekboard_destroy_context
<SUBSECTION Standard>
EEKBOARD_EEKBOARD
EEKBOARD_IS_EEKBOARD
EEKBOARD_TYPE_EEKBOARD
eekboard_eekboard_get_type
EEKBOARD_EEKBOARD_CLASS
EEKBOARD_IS_EEKBOARD_CLASS
EEKBOARD_EEKBOARD_GET_CLASS
</SECTION>
<SECTION>
<FILE>eekboard-context</FILE>
<TITLE>EekboardContext</TITLE>
EekboardContext
EekboardContextClass
EekboardContextPrivate
eekboard_context_new
eekboard_context_set_keyboard
eekboard_context_show_keyboard
eekboard_context_hide_keyboard
eekboard_context_set_group
eekboard_context_press_key
eekboard_context_release_key
eekboard_context_is_keyboard_visible
eekboard_context_set_enabled
eekboard_context_is_enabled
<SUBSECTION Standard>
EEKBOARD_CONTEXT
EEKBOARD_IS_CONTEXT
EEKBOARD_TYPE_CONTEXT
eekboard_context_get_type
EEKBOARD_CONTEXT_CLASS
EEKBOARD_IS_CONTEXT_CLASS
EEKBOARD_CONTEXT_GET_CLASS
</SECTION>

View File

@ -0,0 +1,2 @@
eekboard_context_get_type
eekboard_eekboard_get_type

View File

@ -1,5 +1,5 @@
# Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
# Copyright (C) 2010 Red Hat, Inc.
# 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
@ -16,190 +16,236 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
lib_LTLIBRARIES = \
libeek.la \
libeek-gtk.la \
libeek-xkb.la \
lib_LTLIBRARIES = \
libeek.la \
libeek-gtk.la \
libeek-xkb.la \
libeek-xkl.la
if HAVE_CLUTTER
if ENABLE_CLUTTER
lib_LTLIBRARIES += libeek-clutter.la
endif
libeek_la_SOURCES = \
$(srcdir)/eek-layout.c \
$(srcdir)/eek-layout.h \
$(srcdir)/eek-element.c \
$(srcdir)/eek-element.h \
$(srcdir)/eek-container.c \
$(srcdir)/eek-container.h \
$(srcdir)/eek-keyboard.c \
$(srcdir)/eek-keyboard.h \
$(srcdir)/eek-section.c \
$(srcdir)/eek-section.h \
$(srcdir)/eek-key.c \
$(srcdir)/eek-key.h \
$(srcdir)/eek-types.h \
$(srcdir)/eek-types.c \
$(srcdir)/eek-keysym.h \
$(srcdir)/eek-keysym.c \
$(srcdir)/eek-special-keysym-labels.h \
$(srcdir)/eek-unicode-keysym-labels.h \
$(srcdir)/eek-keyname-keysym-labels.h
libeek_la_CFLAGS = $(GOBJECT2_CFLAGS)
libeek_la_LIBADD = $(GOBJECT2_LIBS) -lm
libeek_public_headers = \
$(srcdir)/eek-layout.h \
$(srcdir)/eek-element.h \
$(srcdir)/eek-container.h \
$(srcdir)/eek-keyboard.h \
$(srcdir)/eek-section.h \
$(srcdir)/eek-key.h \
$(srcdir)/eek-symbol.h \
$(srcdir)/eek-keysym.h \
$(srcdir)/eek-types.h \
$(srcdir)/eek-xml.h \
$(srcdir)/eek-xml-layout.h \
$(srcdir)/eek-serializable.h \
$(srcdir)/eek.h
if HAVE_CLUTTER
libeek_clutter_la_SOURCES = \
$(srcdir)/eek-clutter-keyboard.c \
$(srcdir)/eek-clutter-keyboard.h \
$(srcdir)/eek-clutter-section.c \
$(srcdir)/eek-clutter-section.h \
$(srcdir)/eek-clutter-key.c \
$(srcdir)/eek-clutter-key.h \
$(srcdir)/eek-clutter-key-actor.c \
$(srcdir)/eek-clutter-key-actor.h \
$(srcdir)/eek-clutter-drawing-context.c \
$(srcdir)/eek-clutter-drawing-context.h \
$(srcdir)/eek-drawing.h \
$(srcdir)/eek-drawing.c \
libeek_private_headers = \
$(srcdir)/eek-renderer.h \
$(srcdir)/eek-special-keysym-entries.h \
$(srcdir)/eek-unicode-keysym-entries.h \
$(srcdir)/eek-xkeysym-keysym-entries.h \
$(srcdir)/eek-marshalers.h
libeek_sources = \
$(srcdir)/eek-layout.c \
$(srcdir)/eek-element.c \
$(srcdir)/eek-container.c \
$(srcdir)/eek-keyboard.c \
$(srcdir)/eek-section.c \
$(srcdir)/eek-key.c \
$(srcdir)/eek-symbol.c \
$(srcdir)/eek-keysym.c \
$(srcdir)/eek-types.c \
$(srcdir)/eek-serializable.c \
$(srcdir)/eek-xml.c \
$(srcdir)/eek-xml-layout.c \
$(srcdir)/eek-renderer.c \
$(srcdir)/eek-keyboard-drawing.c
libeek_keysym_sources = \
$(srcdir)/eek-special-keysym-entries.h \
$(srcdir)/eek-unicode-keysym-entries.h \
$(srcdir)/eek-xkeysym-keysym-entries.h
libeek_enumtypes_sources = \
$(srcdir)/eek-enumtypes.c \
$(srcdir)/eek-enumtypes.h
libeek_marshalers_sources = \
$(srcdir)/eek-marshalers.c \
$(srcdir)/eek-marshalers.h
BUILT_SOURCES = \
$(libeek_keysym_sources) \
$(libeek_marshalers_sources)
libeek_la_SOURCES = \
$(libeek_sources) \
$(srcdir)/eek-marshalers.c
libeek_la_CFLAGS = $(GIO2_CFLAGS) $(PANGOCAIRO_CFLAGS)
libeek_la_LIBADD = $(GIO2_LIBS) $(PANGOCAIRO_LIBS) -lm
if ENABLE_CLUTTER
libeek_clutter_public_headers = \
$(srcdir)/eek-clutter-keyboard.h \
$(srcdir)/eek-clutter.h
libeek_clutter_la_CFLAGS = $(CLUTTER_CFLAGS) $(CAIRO_LIBS) $(PANGO_LIBS)
libeek_clutter_la_LIBADD = libeek.la $(CLUTTER_LIBS) $(CAIRO_LIBS) $(PANGO_LIBS)
libeek_clutter_private_headers = \
$(srcdir)/eek-clutter-section.h \
$(srcdir)/eek-clutter-key.h \
$(srcdir)/eek-clutter-renderer.h
libeek_clutter_sources = \
$(srcdir)/eek-clutter-keyboard.c \
$(srcdir)/eek-clutter-section.c \
$(srcdir)/eek-clutter-key.c \
$(srcdir)/eek-clutter-renderer.c
libeek_clutter_la_SOURCES = $(libeek_clutter_sources)
libeek_clutter_la_CFLAGS = $(CLUTTER_CFLAGS)
libeek_clutter_la_LIBADD = libeek.la $(CLUTTER_LIBS)
endif
libeek_gtk_la_SOURCES = \
$(srcdir)/eek-gtk-keyboard.c \
$(srcdir)/eek-gtk-keyboard.h \
$(srcdir)/eek-drawing.h \
$(srcdir)/eek-drawing.c \
libeek_gtk_public_headers = \
$(srcdir)/eek-gtk-keyboard.h \
$(srcdir)/eek-gtk.h
libeek_gtk_sources = \
$(srcdir)/eek-gtk-keyboard.c
libeek_gtk_la_CFLAGS = $(GTK2_CFLAGS) $(CAIRO_LIBS) $(PANGO_LIBS)
libeek_gtk_la_LIBADD = libeek.la $(GTK2_LIBS) $(CAIRO_LIBS) $(PANGO_LIBS)
libeek_gtk_la_SOURCES = $(libeek_gtk_sources)
libeek_gtk_la_CFLAGS = $(GTK_CFLAGS)
libeek_gtk_la_LIBADD = libeek.la $(GTK_LIBS)
libeek_xkb_la_SOURCES = \
$(srcdir)/eek-xkb-layout.h \
libeek_xkb_public_headers = \
$(srcdir)/eek-xkb-layout.h \
$(srcdir)/eek-xkb.h
libeek_xkb_sources = \
$(srcdir)/eek-xkb-layout.c
libeek_xkb_la_CFLAGS = $(GTK2_CFLAGS) $(XKB_CFLAGS)
libeek_xkb_la_LIBADD = libeek.la $(GTK2_LIBS) $(XKB_LIBS)
libeek_xkb_la_SOURCES = $(libeek_xkb_sources)
libeek_xkb_la_CFLAGS = $(XKB_CFLAGS) $(GTK_CFLAGS)
libeek_xkb_la_LIBADD = libeek.la $(XKB_LIBS) $(GTK_LIBS)
libeek_xkl_la_SOURCES = \
$(srcdir)/eek-xkl-layout.h \
libeek_xkl_public_headers = \
$(srcdir)/eek-xkl-layout.h \
$(srcdir)/eek-xkl.h
libeek_xkl_sources = \
$(srcdir)/eek-xkl-layout.c
libeek_xkl_la_CFLAGS = $(GTK2_CFLAGS) $(LIBXKLAVIER_CFLAGS)
libeek_xkl_la_LIBADD = libeek-xkb.la $(GTK2_LIBS) $(LIBXKLAVIER_LIBS)
libeek_xkl_la_SOURCES = $(libeek_xkl_sources)
libeek_xkl_la_CFLAGS = $(LIBXKLAVIER_CFLAGS) $(GTK_CFLAGS)
libeek_xkl_la_LIBADD = libeek-xkb.la $(LIBXKLAVIER_LIBS) $(GTK_LIBS)
eekdir = $(includedir)/eek-$(EEK_API_VERSION)/eek
eek_HEADERS = \
$(top_srcdir)/eek/eek-element.h \
$(top_srcdir)/eek/eek-container.h \
$(top_srcdir)/eek/eek-keyboard.h \
$(top_srcdir)/eek/eek-section.h \
$(top_srcdir)/eek/eek-key.h \
$(top_srcdir)/eek/eek-layout.h \
$(top_srcdir)/eek/eek-keysym.h \
$(top_srcdir)/eek/eek-types.h \
$(top_srcdir)/eek/eek-gtk-keyboard.h \
$(top_srcdir)/eek/eek-xkb-layout.h \
$(top_srcdir)/eek/eek-xkl-layout.h \
$(top_srcdir)/eek/eek.h \
$(top_srcdir)/eek/eek-gtk.h \
$(top_srcdir)/eek/eek-xkb.h \
$(top_srcdir)/eek/eek-xkl.h
eek_HEADERS = \
$(libeek_public_headers) \
$(libeek_clutter_public_headers) \
$(libeek_gtk_public_headers) \
$(libeek_xkb_public_headers) \
$(libeek_xkl_public_headers)
if HAVE_CLUTTER
eek_HEADERS += \
$(top_srcdir)/eek/eek-clutter-keyboard.h \
$(top_srcdir)/eek/eek-clutter-section.h \
$(top_srcdir)/eek/eek-clutter-key.h \
$(top_srcdir)/eek/eek-clutter-drawing-context.h \
$(top_srcdir)/eek/eek-clutter.h
endif
noinst_HEADERS = \
$(libeek_private_headers) \
$(libeek_clutter_private_headers) \
$(libeek_gtk_private_headers) \
$(libeek_xkb_private_headers) \
$(libeek_xkl_private_headers)
eek-keysym.c: eek-special-keysym-labels.h eek-unicode-keysym-labels.h eek-keyname-keysym-labels.h
eek-special-keysym-entries.h: special-keysym-entries.txt
$(PYTHON) ./gen-keysym-entries.py special_keysym_entries < $< > $@
eek-unicode-keysym-entries.h: unicode-keysym-entries.txt
$(PYTHON) ./gen-keysym-entries.py unicode_keysym_entries < $< > $@
eek-xkeysym-keysym-entries.h: xkeysym-keysym-entries.txt
$(PYTHON) ./gen-keysym-entries.py xkeysym_keysym_entries < $< > $@
eek-special-keysym-labels.h: special-keysym-labels.txt
$(PYTHON) ./gen-keysym-labels.py special_keysym_labels < $< > $@
eek-unicode-keysym-labels.h: unicode-keysym-labels.txt
$(PYTHON) ./gen-keysym-labels.py unicode_keysym_labels < $< > $@
eek-keyname-keysym-labels.h: keyname-keysym-labels.txt
$(PYTHON) ./gen-keysym-labels.py keyname_keysym_labels < $< > $@
# gen marshal
eek-marshalers.h: eek-marshalers.list
$(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=_eek_marshal $(srcdir)/eek-marshalers.list --header --internal > $@.tmp && \
mv $@.tmp $@
eek-marshalers.c: eek-marshalers.list eek-marshalers.h
$(AM_V_GEN) (echo "#include \"eek-marshalers.h\""; \
$(GLIB_GENMARSHAL) --prefix=_eek_marshal $(srcdir)/eek-marshalers.list --body --internal) > $@.tmp && \
mv $@.tmp $@
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = \
eek-$(EEK_API_VERSION).pc \
eek-clutter-$(EEK_API_VERSION).pc \
eek-gtk-$(EEK_API_VERSION).pc \
eek-xkb-$(EEK_API_VERSION).pc \
pkgconfig_DATA = \
eek-$(EEK_API_VERSION).pc \
eek-gtk-$(EEK_API_VERSION).pc \
eek-xkb-$(EEK_API_VERSION).pc \
eek-xkl-$(EEK_API_VERSION).pc
DISTCLEANFILES = \
eek-special-keysym-labels.h \
eek-unicode-keysym-labels.h \
eek-keyname-keysym-labels.h \
$(pkgconfig_DATA)
EXTRA_DIST = \
gen-keysym-labels.py \
special-keysym-labels.txt \
unicode-keysym-labels.txt \
keyname-keysym-labels.txt
if ENABLE_CLUTTER
pkgconfig_DATA += eek-clutter-$(EEK_API_VERSION).pc
endif
CLEANFILES =
DISTCLEANFILES = \
$(BUILT_SOURCES) \
$(pkgconfig_DATA)
EXTRA_DIST = \
gen-keysym-entries.py \
special-keysym-entries.txt \
unicode-keysym-entries.txt \
xkeysym-keysym-entries.txt \
eek-marshalers.list
-include $(INTROSPECTION_MAKEFILE)
INTROSPECTION_GIRS =
INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir)
INTROSPECTION_SCANNER_ARGS = --add-include-path=$(builddir)
INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
if HAVE_INTROSPECTION
Eek-0.1.gir: libeek.la
Eek_0_1_gir_SCANNERFLAGS = --strip-prefix=Eek --pkg=glib-2.0
Eek_0_1_gir_INCLUDES = GLib-2.0 GObject-2.0
Eek_0_1_gir_CFLAGS = $(libeek_la_CFLAGS)
Eek_0_1_gir_LIBS = libeek.la
Eek_0_1_gir_FILES = $(libeek_la_SOURCES)
Eek@EEK_LIBRARY_SUFFIX@.gir: libeek.la
Eek@EEK_LIBRARY_SUFFIX_U@_gir_SCANNERFLAGS = --strip-prefix=Eek --pkg=glib-2.0
Eek@EEK_LIBRARY_SUFFIX_U@_gir_INCLUDES = GLib-2.0 GObject-2.0 Gio-2.0
Eek@EEK_LIBRARY_SUFFIX_U@_gir_CFLAGS = $(libeek_la_CFLAGS)
Eek@EEK_LIBRARY_SUFFIX_U@_gir_LIBS = libeek.la
Eek@EEK_LIBRARY_SUFFIX_U@_gir_FILES = $(libeek_sources) $(libeek_public_headers)
EekGtk-0.1.gir: libeek-gtk.la Eek-0.1.gir
EekGtk_0_1_gir_INCLUDES = GObject-2.0 Gtk-2.0 Eek-0.1
EekGtk_0_1_gir_CFLAGS = $(libeek_gtk_la_CFLAGS)
EekGtk_0_1_gir_LIBS = libeek-gtk.la
EekGtk_0_1_gir_FILES = $(libeek_gtk_la_SOURCES)
EekGtk@EEK_LIBRARY_SUFFIX@.gir: libeek-gtk.la Eek@EEK_LIBRARY_SUFFIX@.gir
EekGtk@EEK_LIBRARY_SUFFIX_U@_gir_INCLUDES = GObject-2.0 Gtk-@GTK_API_VERSION@ Eek@EEK_LIBRARY_SUFFIX@
EekGtk@EEK_LIBRARY_SUFFIX_U@_gir_CFLAGS = $(libeek_gtk_la_CFLAGS)
EekGtk@EEK_LIBRARY_SUFFIX_U@_gir_LIBS = libeek-gtk.la
EekGtk@EEK_LIBRARY_SUFFIX_U@_gir_FILES = $(libeek_gtk_sources) $(libeek_gtk_public_headers)
if HAVE_CLUTTER
EekClutter-0.1.gir: libeek-clutter.la Eek-0.1.gir
EekClutter_0_1_gir_INCLUDES = GObject-2.0 Clutter-1.0 Eek-0.1
EekClutter_0_1_gir_CFLAGS = $(libeek_clutter_la_CFLAGS)
EekClutter_0_1_gir_LIBS = libeek-clutter.la
EekClutter_0_1_gir_FILES = $(libeek_clutter_la_SOURCES)
if ENABLE_CLUTTER
EekClutter@EEK_LIBRARY_SUFFIX@.gir: libeek-clutter.la Eek@EEK_LIBRARY_SUFFIX@.gir
EekClutter@EEK_LIBRARY_SUFFIX_U@_gir_INCLUDES = GObject-2.0 Clutter-1.0 Eek@EEK_LIBRARY_SUFFIX@
EekClutter@EEK_LIBRARY_SUFFIX_U@_gir_CFLAGS = $(libeek_clutter_la_CFLAGS)
EekClutter@EEK_LIBRARY_SUFFIX_U@_gir_LIBS = libeek-clutter.la
EekClutter@EEK_LIBRARY_SUFFIX_U@_gir_FILES = $(libeek_clutter_sources) $(libeek_clutter_public_headers)
endif
EekXkb-0.1.gir: libeek-xkb.la Eek-0.1.gir
EekXkb_0_1_gir_INCLUDES = GObject-2.0 Eek-0.1
EekXkb_0_1_gir_CFLAGS = $(libeek_xkb_la_CFLAGS)
EekXkb_0_1_gir_LIBS = libeek-xkb.la
EekXkb_0_1_gir_FILES = $(libeek_xkb_la_SOURCES)
EekXkb@EEK_LIBRARY_SUFFIX@.gir: libeek-xkb.la Eek@EEK_LIBRARY_SUFFIX@.gir
EekXkb@EEK_LIBRARY_SUFFIX_U@_gir_INCLUDES = GObject-2.0 Eek@EEK_LIBRARY_SUFFIX@
EekXkb@EEK_LIBRARY_SUFFIX_U@_gir_CFLAGS = $(libeek_xkb_la_CFLAGS)
EekXkb@EEK_LIBRARY_SUFFIX_U@_gir_LIBS = libeek-xkb.la
EekXkb@EEK_LIBRARY_SUFFIX_U@_gir_FILES = $(libeek_xkb_sources) $(libeek_xkb_public_headers)
EekXkl-0.1.gir: libeek-xkl.la EekXkb-0.1.gir
EekXkl_0_1_gir_INCLUDES = GObject-2.0 EekXkb-0.1
EekXkl_0_1_gir_CFLAGS = $(libeek_xkl_la_CFLAGS)
EekXkl_0_1_gir_LIBS = libeek-xkl.la
EekXkl_0_1_gir_FILES = $(libeek_xkl_la_SOURCES)
EekXkl@EEK_LIBRARY_SUFFIX@.gir: libeek-xkl.la EekXkb@EEK_LIBRARY_SUFFIX@.gir
EekXkl@EEK_LIBRARY_SUFFIX_U@_gir_INCLUDES = GObject-2.0 EekXkb@EEK_LIBRARY_SUFFIX@
EekXkl@EEK_LIBRARY_SUFFIX_U@_gir_CFLAGS = $(libeek_xkl_la_CFLAGS)
EekXkl@EEK_LIBRARY_SUFFIX_U@_gir_LIBS = libeek-xkl.la
EekXkl@EEK_LIBRARY_SUFFIX_U@_gir_FILES = $(libeek_xkl_sources) $(libeek_xkl_public_headers)
INTROSPECTION_GIRS += \
Eek-0.1.gir \
EekGtk-0.1.gir \
EekXkb-0.1.gir \
EekXkl-0.1.gir
INTROSPECTION_GIRS += \
Eek@EEK_LIBRARY_SUFFIX@.gir \
EekGtk@EEK_LIBRARY_SUFFIX@.gir \
EekXkb@EEK_LIBRARY_SUFFIX@.gir \
EekXkl@EEK_LIBRARY_SUFFIX@.gir
if HAVE_CLUTTER
INTROSPECTION_GIRS += \
EekClutter-0.1.gir
if ENABLE_CLUTTER
INTROSPECTION_GIRS += \
EekClutter@EEK_LIBRARY_SUFFIX@.gir
endif
girdir = $(datadir)/gir-1.0

View File

@ -1,5 +1,5 @@
# Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
# Copyright (C) 2010 Red Hat, Inc.
# 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

View File

@ -1,5 +1,5 @@
# Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
# Copyright (C) 2010 Red Hat, Inc.
# 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

View File

@ -1,138 +0,0 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 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>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-clutter-drawing-context.h"
G_DEFINE_TYPE (EekClutterDrawingContext, eek_clutter_drawing_context,
G_TYPE_INITIALLY_UNOWNED);
#define EEK_CLUTTER_DRAWING_CONTEXT_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CLUTTER_DRAWING_CONTEXT, EekClutterDrawingContextPrivate))
struct _EekClutterDrawingContextPrivate
{
/* outline pointer -> ClutterTexture */
GHashTable *outline_textures;
/* keysym category -> PangoFontDescription * */
PangoFontDescription *category_fonts[EEK_KEYSYM_CATEGORY_LAST];
};
static void
eek_clutter_drawing_context_dispose (GObject *object)
{
EekClutterDrawingContextPrivate *priv =
EEK_CLUTTER_DRAWING_CONTEXT_GET_PRIVATE(object);
if (priv->outline_textures) {
g_hash_table_unref (priv->outline_textures);
priv->outline_textures = NULL;
}
}
static void
eek_clutter_drawing_context_finalize (GObject *object)
{
EekClutterDrawingContextPrivate *priv =
EEK_CLUTTER_DRAWING_CONTEXT_GET_PRIVATE(object);
gint i;
for (i = 0; i < EEK_KEYSYM_CATEGORY_LAST; i++)
pango_font_description_free (priv->category_fonts[i]);
}
static void
eek_clutter_drawing_context_class_init (EekClutterDrawingContextClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (gobject_class,
sizeof (EekClutterDrawingContextPrivate));
gobject_class->finalize = eek_clutter_drawing_context_finalize;
gobject_class->dispose = eek_clutter_drawing_context_dispose;
}
static void
eek_clutter_drawing_context_init (EekClutterDrawingContext *self)
{
EekClutterDrawingContextPrivate *priv;
priv = self->priv = EEK_CLUTTER_DRAWING_CONTEXT_GET_PRIVATE(self);
priv->outline_textures = g_hash_table_new (g_direct_hash, g_direct_equal);
memset (priv->category_fonts, 0, sizeof *priv->category_fonts);
}
void
eek_clutter_drawing_context_set_outline_texture
(EekClutterDrawingContext *context,
EekOutline *outline,
ClutterActor *texture)
{
EekClutterDrawingContextPrivate *priv =
EEK_CLUTTER_DRAWING_CONTEXT_GET_PRIVATE(context);
g_return_if_fail (priv);
g_hash_table_insert (context->priv->outline_textures, outline, texture);
}
ClutterActor *
eek_clutter_drawing_context_get_outline_texture
(EekClutterDrawingContext *context,
EekOutline *outline)
{
EekClutterDrawingContextPrivate *priv =
EEK_CLUTTER_DRAWING_CONTEXT_GET_PRIVATE(context);
g_return_val_if_fail (priv, NULL);
return g_hash_table_lookup (context->priv->outline_textures, outline);
}
void
eek_clutter_drawing_context_set_category_font
(EekClutterDrawingContext *context,
EekKeysymCategory category,
PangoFontDescription *font)
{
EekClutterDrawingContextPrivate *priv =
EEK_CLUTTER_DRAWING_CONTEXT_GET_PRIVATE(context);
g_return_if_fail (priv);
priv->category_fonts[category] = pango_font_description_copy (font);
}
PangoFontDescription *
eek_clutter_drawing_context_get_category_font
(EekClutterDrawingContext *context,
EekKeysymCategory category)
{
EekClutterDrawingContextPrivate *priv =
EEK_CLUTTER_DRAWING_CONTEXT_GET_PRIVATE(context);
g_return_val_if_fail (priv, NULL);
return priv->category_fonts[category];
}
EekClutterDrawingContext *
eek_clutter_drawing_context_new (void)
{
return g_object_new (EEK_TYPE_CLUTTER_DRAWING_CONTEXT, NULL);
}

View File

@ -1,82 +0,0 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 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_CLUTTER_DRAWING_CONTEXT_H
#define EEK_CLUTTER_DRAWING_CONTEXT_H 1
#include <clutter/clutter.h>
#include <pango/pango.h>
#include "eek-keysym.h"
#include "eek-types.h"
G_BEGIN_DECLS
#define EEK_TYPE_CLUTTER_DRAWING_CONTEXT (eek_clutter_drawing_context_get_type())
#define EEK_CLUTTER_DRAWING_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_CLUTTER_DRAWING_CONTEXT, EekClutterDrawingContext))
#define EEK_CLUTTER_DRAWING_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_CLUTTER_DRAWING_CONTEXT, EekClutterDrawingContextClass))
#define EEK_IS_CLUTTER_DRAWING_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_CLUTTER_DRAWING_CONTEXT))
#define EEK_IS_CLUTTER_DRAWING_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_CLUTTER_DRAWING_CONTEXT))
#define EEK_CLUTTER_DRAWING_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_CLUTTER_DRAWING_CONTEXT, EekClutterDrawingContextClass))
typedef struct _EekClutterDrawingContext EekClutterDrawingContext;
typedef struct _EekClutterDrawingContextClass EekClutterDrawingContextClass;
typedef struct _EekClutterDrawingContextPrivate EekClutterDrawingContextPrivate;
struct _EekClutterDrawingContext
{
/*< private >*/
GInitiallyUnowned parent;
/*< private >*/
EekClutterDrawingContextPrivate *priv;
};
struct _EekClutterDrawingContextClass
{
/*< private >*/
GInitiallyUnownedClass parent_class;
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_clutter_drawing_context_get_type
(void) G_GNUC_CONST;
EekClutterDrawingContext *eek_clutter_drawing_context_new
(void);
void eek_clutter_drawing_context_set_outline_texture
(EekClutterDrawingContext *context,
EekOutline *outline,
ClutterActor *texture);
ClutterActor *eek_clutter_drawing_context_get_outline_texture
(EekClutterDrawingContext *context,
EekOutline *outline);
void eek_clutter_drawing_context_set_category_font
(EekClutterDrawingContext *context,
EekKeysymCategory category,
PangoFontDescription *fonts);
PangoFontDescription *eek_clutter_drawing_context_get_category_font
(EekClutterDrawingContext *context,
EekKeysymCategory category);
G_END_DECLS
#endif /* EEK_CLUTTER_DRAWING_CONTEXT_H */

View File

@ -1,373 +0,0 @@
/*
* Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 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 <cogl/cogl.h>
#include <cogl/cogl-pango.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-clutter-key-actor.h"
#include "eek-keysym.h"
#include "eek-drawing.h"
#include "eek-section.h"
#include "eek-keyboard.h"
#define noKBDRAW_DEBUG
enum {
PRESSED,
RELEASED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (EekClutterKeyActor, eek_clutter_key_actor,
CLUTTER_TYPE_GROUP);
#define EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CLUTTER_KEY_ACTOR, EekClutterKeyActorPrivate))
struct _EekClutterKeyActorPrivate
{
EekClutterDrawingContext *context;
EekKey *key;
ClutterActor *texture;
gboolean is_pressed;
};
static ClutterActor *get_texture (EekClutterKeyActor *actor);
static void draw_key_on_layout (EekClutterKeyActor *actor,
PangoLayout *layout);
static void key_enlarge (ClutterActor *actor);
static void key_shrink (ClutterActor *actor);
static void
eek_clutter_key_actor_real_paint (ClutterActor *self)
{
EekClutterKeyActorPrivate *priv = EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE (self);
PangoLayout *layout;
PangoRectangle logical_rect = { 0, };
CoglColor color;
ClutterGeometry geom;
EekBounds bounds;
eek_element_get_bounds (EEK_ELEMENT(priv->key), &bounds);
clutter_actor_set_anchor_point_from_gravity (self,
CLUTTER_GRAVITY_CENTER);
clutter_actor_set_position (self,
bounds.x + bounds.width / 2,
bounds.y + bounds.height / 2);
if (!priv->texture) {
priv->texture = get_texture (EEK_CLUTTER_KEY_ACTOR(self));
clutter_actor_set_position (priv->texture, 0, 0);
clutter_container_add_actor (CLUTTER_CONTAINER(self), priv->texture);
}
CLUTTER_ACTOR_CLASS (eek_clutter_key_actor_parent_class)->
paint (self);
/* Draw the label on the key. */
layout = clutter_actor_create_pango_layout (self, NULL);
draw_key_on_layout (EEK_CLUTTER_KEY_ACTOR(self), layout);
pango_layout_get_extents (layout, NULL, &logical_rect);
/* FIXME: Color should be configurable through a property. */
cogl_color_set_from_4ub (&color, 0x80, 0x00, 0x00, 0xff);
clutter_actor_get_allocation_geometry (self, &geom);
cogl_pango_render_layout
(layout,
(geom.width - logical_rect.width / PANGO_SCALE) / 2,
(geom.height - logical_rect.height / PANGO_SCALE) / 2,
&color,
0);
g_object_unref (layout);
}
static void
eek_clutter_key_actor_real_pressed (EekClutterKeyActor *self)
{
ClutterActor *actor, *section;
actor = CLUTTER_ACTOR(self);
/* Make sure the enlarged key show up on the keys which belong
to other sections. */
section = clutter_actor_get_parent (actor);
clutter_actor_raise_top (section);
clutter_actor_raise_top (actor);
key_enlarge (actor);
}
static void
eek_clutter_key_actor_real_released (EekClutterKeyActor *self)
{
ClutterActor *actor, *section;
actor = CLUTTER_ACTOR(self);
/* Make sure the enlarged key show up on the keys which belong
to other sections. */
section = clutter_actor_get_parent (actor);
clutter_actor_raise_top (section);
clutter_actor_raise_top (actor);
key_shrink (actor);
}
static void
eek_clutter_key_actor_dispose (GObject *object)
{
EekClutterKeyActorPrivate *priv = EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE(object);
if (priv->context) {
g_object_unref (priv->context);
priv->context = NULL;
}
if (priv->key) {
g_object_unref (priv->key);
priv->key = NULL;
}
G_OBJECT_CLASS (eek_clutter_key_actor_parent_class)->dispose (object);
}
static void
eek_clutter_key_actor_class_init (EekClutterKeyActorClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
g_type_class_add_private (gobject_class,
sizeof (EekClutterKeyActorPrivate));
actor_class->paint = eek_clutter_key_actor_real_paint;
gobject_class->dispose = eek_clutter_key_actor_dispose;
/* signals */
klass->pressed = eek_clutter_key_actor_real_pressed;
klass->released = eek_clutter_key_actor_real_released;
signals[PRESSED] =
g_signal_new ("pressed",
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(EekClutterKeyActorClass, pressed),
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[RELEASED] =
g_signal_new ("released",
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(EekClutterKeyActorClass, released),
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
on_button_press_event (ClutterActor *actor,
ClutterEvent *event,
gpointer user_data)
{
EekClutterKeyActorPrivate *priv =
EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE(actor);
if (!priv->is_pressed) {
priv->is_pressed = TRUE;
/* priv->key will send back PRESSED event of actor. */
g_signal_emit_by_name (priv->key, "pressed");
}
}
static void
on_button_release_event (ClutterActor *actor,
ClutterEvent *event,
gpointer user_data)
{
EekClutterKeyActorPrivate *priv =
EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE(actor);
if (priv->is_pressed) {
priv->is_pressed = FALSE;
/* priv->key will send back RELEASED event of actor. */
g_signal_emit_by_name (priv->key, "released");
}
}
static gboolean
on_leave_event (ClutterActor *actor,
ClutterEvent *event,
gpointer user_data)
{
EekClutterKeyActorPrivate *priv =
EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE(actor);
if (priv->is_pressed) {
priv->is_pressed = FALSE;
/* priv->key will send back RELEASED event of actor. */
g_signal_emit_by_name (priv->key, "released");
}
return FALSE;
}
static void
eek_clutter_key_actor_init (EekClutterKeyActor *self)
{
EekClutterKeyActorPrivate *priv;
priv = self->priv = EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE(self);
priv->key = NULL;
priv->texture = NULL;
clutter_actor_set_reactive (CLUTTER_ACTOR(self), TRUE);
g_signal_connect (self, "button-press-event",
G_CALLBACK (on_button_press_event), NULL);
g_signal_connect (self, "button-release-event",
G_CALLBACK (on_button_release_event), NULL);
g_signal_connect (self, "leave-event",
G_CALLBACK (on_leave_event), NULL);
}
ClutterActor *
eek_clutter_key_actor_new (EekClutterDrawingContext *context, EekKey *key)
{
EekClutterKeyActor *actor;
actor = g_object_new (EEK_TYPE_CLUTTER_KEY_ACTOR, NULL);
actor->priv->context = context;
g_object_ref_sink (actor->priv->context);
actor->priv->key = key;
g_object_ref_sink (actor->priv->key);
return CLUTTER_ACTOR(actor);
}
#if 0
static void
on_key_animate_complete (ClutterAnimation *animation,
gpointer user_data)
{
ClutterActor *actor = (ClutterActor*)user_data;
/* reset after effect */
clutter_actor_set_opacity (actor, 0xff);
clutter_actor_set_scale (actor, 1.0, 1.0);
}
#endif
static void
key_enlarge (ClutterActor *actor)
{
clutter_actor_set_scale (actor, 1.0, 1.0);
clutter_actor_animate (actor, CLUTTER_EASE_IN_SINE, 150,
"scale-x", 1.5,
"scale-y", 1.5,
NULL);
}
static void
key_shrink (ClutterActor *actor)
{
clutter_actor_set_scale (actor, 1.5, 1.5);
clutter_actor_animate (actor, CLUTTER_EASE_OUT_SINE, 150,
"scale-x", 1.0,
"scale-y", 1.0,
NULL);
}
static ClutterActor *
create_texture_for_key (EekKey *key)
{
ClutterActor *texture;
cairo_t *cr;
EekOutline *outline;
EekBounds bounds;
outline = eek_key_get_outline (EEK_KEY(key));
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
texture = clutter_cairo_texture_new (bounds.width, bounds.height);
cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE(texture));
eek_draw_outline (cr, outline);
cairo_destroy (cr);
return texture;
}
static ClutterActor *
get_texture (EekClutterKeyActor *actor)
{
ClutterActor *texture;
EekOutline *outline;
outline = eek_key_get_outline (actor->priv->key);
texture =
eek_clutter_drawing_context_get_outline_texture (actor->priv->context,
outline);
if (texture == NULL) {
texture = create_texture_for_key (actor->priv->key);
eek_clutter_drawing_context_set_outline_texture (actor->priv->context,
outline,
texture);
} else
texture = clutter_clone_new (texture);
return texture;
}
static void
draw_key_on_layout (EekClutterKeyActor *self,
PangoLayout *layout)
{
EekClutterKeyActorPrivate *priv = EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE (self);
guint keysym;
const gchar *label, *empty_label = "";
EekKeysymCategory category;
EekBounds bounds;
PangoFontDescription *font;
keysym = eek_key_get_keysym (priv->key);
if (keysym == EEK_INVALID_KEYSYM)
return;
category = eek_keysym_get_category (keysym);
if (category == EEK_KEYSYM_CATEGORY_UNKNOWN)
return;
font = eek_clutter_drawing_context_get_category_font (priv->context,
category);
pango_layout_set_font_description (layout, font);
eek_element_get_bounds (EEK_ELEMENT(priv->key), &bounds);
pango_layout_set_width (layout, PANGO_SCALE * bounds.width);
pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
label = eek_keysym_to_string (keysym);
if (!label)
label = empty_label;
eek_draw_text_on_layout (layout, label);
if (label != empty_label)
g_free ((gpointer)label);
}

View File

@ -1,68 +0,0 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 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_CLUTTER_KEY_ACTOR_H
#define EEK_CLUTTER_KEY_ACTOR_H 1
#include <clutter/clutter.h>
#include "eek-clutter-drawing-context.h"
#include "eek-key.h"
G_BEGIN_DECLS
#define EEK_TYPE_CLUTTER_KEY_ACTOR (eek_clutter_key_actor_get_type())
#define EEK_CLUTTER_KEY_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_CLUTTER_KEY_ACTOR, EekClutterKeyActor))
#define EEK_CLUTTER_KEY_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_CLUTTER_KEY_ACTOR, EekClutterKeyActorClass))
#define EEK_IS_CLUTTER_KEY_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_CLUTTER_KEY_ACTOR))
#define EEK_IS_CLUTTER_KEY_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_CLUTTER_KEY_ACTOR))
#define EEK_CLUTTER_KEY_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_CLUTTER_KEY_ACTOR, EekClutterKeyActorClass))
typedef struct _EekClutterKeyActor EekClutterKeyActor;
typedef struct _EekClutterKeyActorClass EekClutterKeyActorClass;
typedef struct _EekClutterKeyActorPrivate EekClutterKeyActorPrivate;
struct _EekClutterKeyActor
{
/*< private >*/
ClutterGroup parent;
/*< private >*/
EekClutterKeyActorPrivate *priv;
};
struct _EekClutterKeyActorClass
{
/*< private >*/
ClutterGroupClass parent_class;
/* signals */
void (* pressed) (EekClutterKeyActor *self);
void (* released) (EekClutterKeyActor *self);
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_clutter_key_actor_get_type
(void) G_GNUC_CONST;
ClutterActor *eek_clutter_key_actor_new (EekClutterDrawingContext *context,
EekKey *key);
G_END_DECLS
#endif /* EEK_CLUTTER_KEY_ACTOR_H */

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -23,98 +23,269 @@
#endif /* HAVE_CONFIG_H */
#include "eek-clutter-key.h"
#include "eek-clutter-key-actor.h"
G_DEFINE_TYPE (EekClutterKey, eek_clutter_key, EEK_TYPE_KEY);
enum {
PROP_0,
PROP_KEY,
PROP_RENDERER,
PROP_LAST
};
G_DEFINE_TYPE (EekClutterKey, eek_clutter_key, CLUTTER_TYPE_ACTOR);
#define EEK_CLUTTER_KEY_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CLUTTER_KEY, EekClutterKeyPrivate))
struct _EekClutterKeyPrivate
{
EekClutterDrawingContext *context;
ClutterActor *actor;
EekKey *key;
EekClutterRenderer *renderer;
gulong pressed_handler;
gulong released_handler;
};
static void
eek_clutter_key_real_set_name (EekElement *self,
const gchar *name)
on_pressed (EekKey *key, gpointer user_data)
{
EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(self);
ClutterActor *actor = user_data, *parent;
EEK_ELEMENT_CLASS (eek_clutter_key_parent_class)->
set_name (self, name);
parent = clutter_actor_get_parent (actor);
clutter_actor_raise_top (parent);
clutter_actor_raise_top (actor);
clutter_actor_set_scale_with_gravity (actor,
1.0,
1.0,
CLUTTER_GRAVITY_CENTER);
if (priv->actor)
clutter_actor_set_name (CLUTTER_ACTOR(priv->actor), name);
clutter_actor_animate (actor, CLUTTER_EASE_IN_SINE, 150,
"scale-x", 1.5,
"scale-y", 1.5,
NULL);
}
static void
eek_clutter_key_real_set_bounds (EekElement *self,
EekBounds *bounds)
on_released (EekKey *key, gpointer user_data)
{
ClutterActor *actor = user_data, *parent;
parent = clutter_actor_get_parent (actor);
clutter_actor_raise_top (parent);
clutter_actor_raise_top (actor);
clutter_actor_set_scale_with_gravity (actor,
1.5,
1.5,
CLUTTER_GRAVITY_CENTER);
clutter_actor_animate (actor, CLUTTER_EASE_OUT_SINE, 150,
"scale-x", 1.0,
"scale-y", 1.0,
NULL);
}
static void
set_position (ClutterActor *self)
{
EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(self);
EekBounds bounds;
gdouble scale;
eek_element_get_bounds (EEK_ELEMENT(priv->key), &bounds);
scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer));
clutter_actor_set_position (self, bounds.x * scale, bounds.y * scale);
}
static void
eek_clutter_key_real_realize (ClutterActor *self)
{
EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(self);
EEK_ELEMENT_CLASS (eek_clutter_key_parent_class)->
set_bounds (self, bounds);
set_position (self);
clutter_actor_set_reactive (self, TRUE);
if (priv->actor) {
clutter_actor_set_position (priv->actor, bounds->x, bounds->y);
clutter_actor_set_size (priv->actor, bounds->width, bounds->height);
priv->pressed_handler =
g_signal_connect (priv->key, "pressed",
G_CALLBACK(on_pressed), self);
priv->released_handler =
g_signal_connect (priv->key, "released",
G_CALLBACK(on_released), self);
}
static void
eek_clutter_key_real_paint (ClutterActor *self)
{
EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(self);
set_position (self);
eek_clutter_renderer_render_key (priv->renderer, self, priv->key);
}
static void
eek_clutter_key_real_get_preferred_width (ClutterActor *self,
gfloat for_height,
gfloat *min_width_p,
gfloat *natural_width_p)
{
EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(self);
EekBounds bounds;
gdouble scale;
scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer));
eek_element_get_bounds (EEK_ELEMENT(priv->key), &bounds);
*min_width_p = 0.0f;
*natural_width_p = bounds.width * scale;
}
static void
eek_clutter_key_real_get_preferred_height (ClutterActor *self,
gfloat for_width,
gfloat *min_height_p,
gfloat *natural_height_p)
{
EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(self);
EekBounds bounds;
gdouble scale;
scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer));
eek_element_get_bounds (EEK_ELEMENT(priv->key), &bounds);
*min_height_p = 0.0f;
*natural_height_p = bounds.height * scale;
}
static void
eek_clutter_key_real_allocate (ClutterActor *self,
const ClutterActorBox *box,
ClutterAllocationFlags flags)
{
CLUTTER_ACTOR_CLASS (eek_clutter_key_parent_class)->
allocate (self, box, flags);
}
static gboolean
eek_clutter_key_real_button_press_event (ClutterActor *self,
ClutterButtonEvent *event)
{
EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(self);
g_signal_emit_by_name (priv->key, "pressed");
return TRUE;
}
static gboolean
eek_clutter_key_real_button_release_event (ClutterActor *self,
ClutterButtonEvent *event)
{
EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(self);
g_signal_emit_by_name (priv->key, "released");
return TRUE;
}
static gboolean
eek_clutter_key_real_leave_event (ClutterActor *self,
ClutterCrossingEvent *event)
{
EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(self);
if (eek_key_is_pressed (priv->key))
g_signal_emit_by_name (priv->key, "released");
return TRUE;
}
static void
eek_clutter_key_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(object);
switch (prop_id) {
case PROP_KEY:
priv->key = g_value_get_object (value);
g_object_ref (priv->key);
break;
case PROP_RENDERER:
priv->renderer = g_value_get_object (value);
g_object_ref (priv->renderer);
break;
default:
g_object_set_property (object,
g_param_spec_get_name (pspec),
value);
break;
}
}
static void
eek_clutter_key_real_pressed (EekKey *key)
{
EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(key);
if (priv->actor)
g_signal_emit_by_name (priv->actor, "pressed");
}
static void
eek_clutter_key_real_released (EekKey *key)
{
EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(key);
if (priv->actor)
g_signal_emit_by_name (priv->actor, "released");
}
static void
eek_clutter_key_dispose (GObject *object)
{
EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(object);
if (priv->context) {
g_object_unref (priv->context);
priv->context = NULL;
if (priv->renderer) {
g_object_unref (priv->renderer);
priv->renderer = NULL;
}
if (priv->actor) {
g_object_unref (priv->actor);
priv->actor = NULL;
if (priv->key) {
if (g_signal_handler_is_connected (priv->key, priv->pressed_handler))
g_signal_handler_disconnect (priv->key, priv->pressed_handler);
if (g_signal_handler_is_connected (priv->key, priv->released_handler))
g_signal_handler_disconnect (priv->key, priv->released_handler);
g_object_unref (priv->key);
priv->key = NULL;
}
G_OBJECT_CLASS (eek_clutter_key_parent_class)->dispose (object);
}
static void
eek_clutter_key_class_init (EekClutterKeyClass *klass)
{
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
EekElementClass *element_class = EEK_ELEMENT_CLASS (klass);
EekKeyClass *key_class = EEK_KEY_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class,
sizeof (EekClutterKeyPrivate));
element_class->set_name = eek_clutter_key_real_set_name;
element_class->set_bounds = eek_clutter_key_real_set_bounds;
gobject_class->dispose = eek_clutter_key_dispose;
actor_class->realize = eek_clutter_key_real_realize;
actor_class->paint = eek_clutter_key_real_paint;
actor_class->get_preferred_width =
eek_clutter_key_real_get_preferred_width;
actor_class->get_preferred_height =
eek_clutter_key_real_get_preferred_height;
actor_class->allocate = eek_clutter_key_real_allocate;
/* signals */
key_class->pressed = eek_clutter_key_real_pressed;
key_class->released = eek_clutter_key_real_released;
actor_class->button_press_event =
eek_clutter_key_real_button_press_event;
actor_class->button_release_event =
eek_clutter_key_real_button_release_event;
actor_class->leave_event =
eek_clutter_key_real_leave_event;
gobject_class->set_property = eek_clutter_key_set_property;
gobject_class->dispose = eek_clutter_key_dispose;
pspec = g_param_spec_object ("key",
"Key",
"Key",
EEK_TYPE_KEY,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
g_object_class_install_property (gobject_class,
PROP_KEY,
pspec);
pspec = g_param_spec_object ("renderer",
"Renderer",
"Renderer",
EEK_TYPE_RENDERER,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
g_object_class_install_property (gobject_class,
PROP_RENDERER,
pspec);
}
static void
@ -122,33 +293,15 @@ eek_clutter_key_init (EekClutterKey *self)
{
EekClutterKeyPrivate *priv;
priv = self->priv = EEK_CLUTTER_KEY_GET_PRIVATE (self);
priv->actor = NULL;
priv->key = NULL;
priv->renderer = NULL;
}
ClutterActor *
eek_clutter_key_get_actor (EekClutterKey *key)
eek_clutter_key_new (EekKey *key, EekClutterRenderer *renderer)
{
EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(key);
if (!priv->actor) {
g_return_val_if_fail (priv->context, NULL);
priv->actor = eek_clutter_key_actor_new (priv->context, EEK_KEY(key));
g_object_ref_sink (priv->actor);
}
return priv->actor;
}
EekKey *
eek_clutter_key_new (EekClutterDrawingContext *context, gint column, gint row)
{
EekClutterKey *key;
g_return_val_if_fail (context, NULL);
key = g_object_new (EEK_TYPE_CLUTTER_KEY,
"column", column,
"row", row,
NULL);
key->priv->context = context;
g_object_ref_sink (key->priv->context);
return EEK_KEY(key);
return g_object_new (EEK_TYPE_CLUTTER_KEY,
"key", key,
"renderer", renderer,
NULL);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -21,8 +21,8 @@
#define EEK_CLUTTER_KEY_H 1
#include <clutter/clutter.h>
#include "eek-clutter-drawing-context.h"
#include "eek-key.h"
#include "eek-clutter-renderer.h"
G_BEGIN_DECLS
#define EEK_TYPE_CLUTTER_KEY (eek_clutter_key_get_type())
@ -39,7 +39,7 @@ typedef struct _EekClutterKeyPrivate EekClutterKeyPrivate;
struct _EekClutterKey
{
/*< private >*/
EekKey parent;
ClutterActor parent;
/*< private >*/
EekClutterKeyPrivate *priv;
@ -48,18 +48,16 @@ struct _EekClutterKey
struct _EekClutterKeyClass
{
/*< private >*/
EekKeyClass parent_class;
ClutterActorClass parent_class;
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_clutter_key_get_type (void) G_GNUC_CONST;
EekKey * eek_clutter_key_new (EekClutterDrawingContext *context,
gint column,
gint row);
ClutterActor *eek_clutter_key_get_actor (EekClutterKey *key);
GType eek_clutter_key_get_type (void) G_GNUC_CONST;
ClutterActor *eek_clutter_key_new (EekKey *key,
EekClutterRenderer *renderer);
G_END_DECLS
#endif /* EEK_CLUTTER_KEY_H */

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -20,107 +20,161 @@
/**
* SECTION:eek-clutter-keyboard
* @short_description: #EekKeyboard that can be converted into a #ClutterActor
* @short_description: a #ClutterActor displaying #EekKeyboard
*/
#include <string.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-clutter-keyboard.h"
#include "eek-clutter-drawing-context.h"
#include "eek-clutter-section.h"
#include "eek-clutter-renderer.h"
#include "eek-keyboard.h"
#include "eek-drawing.h"
G_DEFINE_TYPE (EekClutterKeyboard, eek_clutter_keyboard, EEK_TYPE_KEYBOARD);
enum {
PROP_0,
PROP_KEYBOARD,
PROP_LAST
};
G_DEFINE_TYPE (EekClutterKeyboard, eek_clutter_keyboard, CLUTTER_TYPE_GROUP);
#define EEK_CLUTTER_KEYBOARD_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CLUTTER_KEYBOARD, EekClutterKeyboardPrivate))
struct _EekClutterKeyboardPrivate
{
EekClutterDrawingContext *context;
ClutterActor *actor;
guint key_press_event_handler;
guint key_release_event_handler;
EekKeyboard *keyboard;
EekClutterRenderer *renderer;
};
static void
eek_clutter_keyboard_real_set_name (EekElement *self,
const gchar *name)
{
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
EEK_ELEMENT_CLASS (eek_clutter_keyboard_parent_class)->
set_name (self, name);
if (priv->actor)
clutter_actor_set_name (priv->actor, name);
}
static void
eek_clutter_keyboard_real_set_bounds (EekElement *self,
EekBounds *bounds)
{
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
EEK_ELEMENT_CLASS (eek_clutter_keyboard_parent_class)->
set_bounds (self, bounds);
if (priv->actor) {
clutter_actor_set_position (priv->actor, bounds->x, bounds->y);
clutter_actor_set_size (priv->actor, bounds->width, bounds->height);
}
}
static void
key_pressed_event (EekSection *section,
EekKey *key,
EekKeyboard *keyboard)
{
g_signal_emit_by_name (keyboard, "key-pressed", key);
}
static void
key_released_event (EekSection *section,
EekKey *key,
EekKeyboard *keyboard)
{
g_signal_emit_by_name (keyboard, "key-released", key);
}
static EekSection *
eek_clutter_keyboard_real_create_section (EekKeyboard *self)
{
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
EekSection *section;
struct _CreateSectionCallbackData {
ClutterActor *actor;
EekClutterRenderer *renderer;
};
typedef struct _CreateSectionCallbackData CreateSectionCallbackData;
if (!priv->context) {
priv->context = eek_clutter_drawing_context_new ();
g_object_ref_sink (G_OBJECT(priv->context));
static void
create_section (EekElement *element, gpointer user_data)
{
CreateSectionCallbackData *data = user_data;
ClutterActor *section;
section = eek_clutter_section_new (EEK_SECTION(element), data->renderer);
clutter_container_add_actor (CLUTTER_CONTAINER(data->actor), section);
}
static void
eek_clutter_keyboard_real_realize (ClutterActor *self)
{
EekClutterKeyboardPrivate *priv;
CreateSectionCallbackData data;
EekBounds bounds;
gdouble scale;
priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer));
clutter_actor_set_position (CLUTTER_ACTOR(self),
bounds.x * scale,
bounds.y * scale);
data.actor = CLUTTER_ACTOR(self);
data.renderer = priv->renderer;
eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
create_section,
&data);
}
static void
eek_clutter_keyboard_real_get_preferred_width (ClutterActor *self,
float for_height,
float *min_width_p,
float *natural_width_p)
{
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
gdouble width;
eek_renderer_get_size (EEK_RENDERER(priv->renderer), &width, NULL);
*min_width_p = 0.0f;
*natural_width_p = width;
}
static void
eek_clutter_keyboard_real_get_preferred_height (ClutterActor *self,
float for_width,
float *min_height_p,
float *natural_height_p)
{
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
gdouble height;
eek_renderer_get_size (EEK_RENDERER(priv->renderer), NULL, &height);
*min_height_p = 0.0f;
*natural_height_p = height;
}
static void
eek_clutter_keyboard_real_allocate (ClutterActor *self,
const ClutterActorBox *box,
ClutterAllocationFlags flags)
{
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
g_assert (priv->renderer);
eek_renderer_set_allocation_size (EEK_RENDERER(priv->renderer),
box->x2 - box->x1,
box->y2 - box->y1);
CLUTTER_ACTOR_CLASS (eek_clutter_keyboard_parent_class)->
allocate (self, box, flags);
}
static void
create_renderer (EekClutterKeyboard *self)
{
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
PangoContext *pcontext;
PangoFontDescription *font;
EekBounds bounds;
pcontext = clutter_actor_get_pango_context (CLUTTER_ACTOR(self));
font = pango_font_description_from_string ("Sans 48px");
pango_context_set_font_description (pcontext, font);
pango_font_description_free (font);
priv->renderer = eek_clutter_renderer_new (priv->keyboard, pcontext);
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
eek_renderer_set_allocation_size (EEK_RENDERER(priv->renderer),
bounds.width,
bounds.height);
}
static void
eek_clutter_keyboard_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(object);
switch (prop_id) {
case PROP_KEYBOARD:
priv->keyboard = g_value_get_object (value);
g_object_ref (priv->keyboard);
create_renderer (EEK_CLUTTER_KEYBOARD(object));
break;
default:
g_object_set_property (object,
g_param_spec_get_name (pspec),
value);
break;
}
section = eek_clutter_section_new (priv->context);
g_return_val_if_fail (section, NULL);
g_signal_connect (section, "key-pressed",
G_CALLBACK(key_pressed_event), self);
g_signal_connect (section, "key-released",
G_CALLBACK(key_released_event), self);
EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self),
EEK_ELEMENT(section));
actor = eek_clutter_keyboard_get_actor (EEK_CLUTTER_KEYBOARD(self));
clutter_container_add_actor
(CLUTTER_CONTAINER(actor),
eek_clutter_section_get_actor (EEK_CLUTTER_SECTION(section)));
return section;
}
static void
@ -128,40 +182,48 @@ eek_clutter_keyboard_dispose (GObject *object)
{
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(object);
if (priv->context) {
g_object_unref (G_OBJECT(priv->context));
priv->context = NULL;
if (priv->renderer) {
g_object_unref (G_OBJECT(priv->renderer));
priv->renderer = NULL;
}
if (priv->actor) {
ClutterActor *stage;
stage = clutter_actor_get_stage (priv->actor);
if (stage) {
g_signal_handler_disconnect (stage,
priv->key_press_event_handler);
g_signal_handler_disconnect (stage,
priv->key_release_event_handler);
}
g_object_unref (priv->actor);
priv->actor = NULL;
if (priv->keyboard) {
g_object_unref (priv->keyboard);
priv->keyboard = NULL;
}
G_OBJECT_CLASS (eek_clutter_keyboard_parent_class)->dispose (object);
}
static void
eek_clutter_keyboard_class_init (EekClutterKeyboardClass *klass)
{
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
EekElementClass *element_class = EEK_ELEMENT_CLASS (klass);
EekKeyboardClass *keyboard_class = EEK_KEYBOARD_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class,
sizeof (EekClutterKeyboardPrivate));
keyboard_class->create_section = eek_clutter_keyboard_real_create_section;
element_class->set_name = eek_clutter_keyboard_real_set_name;
element_class->set_bounds = eek_clutter_keyboard_real_set_bounds;
actor_class->realize =
eek_clutter_keyboard_real_realize;
actor_class->get_preferred_width =
eek_clutter_keyboard_real_get_preferred_width;
actor_class->get_preferred_height =
eek_clutter_keyboard_real_get_preferred_height;
actor_class->allocate = eek_clutter_keyboard_real_allocate;
gobject_class->set_property = eek_clutter_keyboard_set_property;
gobject_class->dispose = eek_clutter_keyboard_dispose;
pspec = g_param_spec_object ("keyboard",
"Keyboard",
"Keyboard",
EEK_TYPE_KEYBOARD,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
g_object_class_install_property (gobject_class,
PROP_KEYBOARD,
pspec);
}
static void
@ -170,147 +232,19 @@ eek_clutter_keyboard_init (EekClutterKeyboard *self)
EekClutterKeyboardPrivate *priv;
priv = self->priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
priv->actor = NULL;
priv->keyboard = NULL;
priv->renderer = NULL;
}
/**
* eek_clutter_keyboard_new:
* @keyboard: an #EekKeyboard
*
* Create a new #EekClutterKeyboard.
* Create a new #ClutterActor displaying @keyboard.
* Returns: a #ClutterActor
*/
EekKeyboard*
eek_clutter_keyboard_new (void)
{
return g_object_new (EEK_TYPE_CLUTTER_KEYBOARD, NULL);
}
static gboolean
on_clutter_key_press_event (ClutterActor *actor,
ClutterEvent *event,
gpointer user_data)
{
guint keycode;
EekKey *key;
keycode = clutter_event_get_key_code (event);
key = eek_keyboard_find_key_by_keycode (user_data, keycode);
if (key) {
g_signal_emit_by_name (key, "pressed", NULL);
return TRUE;
}
return FALSE;
}
static gboolean
on_clutter_key_release_event (ClutterActor *actor,
ClutterEvent *event,
gpointer user_data)
{
guint keycode;
EekKey *key;
keycode = clutter_event_get_key_code (event);
key = eek_keyboard_find_key_by_keycode (user_data, keycode);
if (key) {
g_signal_emit_by_name (key, "released", NULL);
return TRUE;
}
return FALSE;
}
static void
on_clutter_stage_resize (GObject *object,
GParamSpec *param_spec,
gpointer user_data)
{
ClutterActor *stage = CLUTTER_ACTOR(object);
EekClutterKeyboard *keyboard = user_data;
GValue value = {0};
gfloat width, height, scale;
EekBounds bounds;
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
g_object_get (G_OBJECT(stage), "width", &width, NULL);
g_object_get (G_OBJECT(stage), "height", &height, NULL);
g_value_init (&value, G_TYPE_DOUBLE);
scale = width > height ? width / bounds.width : height / bounds.height;
g_value_set_double (&value, scale);
g_object_set_property (G_OBJECT (stage),
"scale-x",
&value);
g_value_set_double (&value, scale);
g_object_set_property (G_OBJECT (stage),
"scale-y",
&value);
}
static void
on_clutter_realize (ClutterActor *actor,
gpointer user_data)
{
EekClutterKeyboard *keyboard = user_data;
EekClutterKeyboardPrivate *priv =
EEK_CLUTTER_KEYBOARD_GET_PRIVATE(keyboard);
ClutterActor *stage;
stage = clutter_actor_get_stage (priv->actor);
priv->key_press_event_handler =
g_signal_connect (stage, "key-press-event",
G_CALLBACK (on_clutter_key_press_event), keyboard);
priv->key_release_event_handler =
g_signal_connect (stage, "key-release-event",
G_CALLBACK (on_clutter_key_release_event), keyboard);
g_signal_connect (stage, "notify::width",
G_CALLBACK (on_clutter_stage_resize), keyboard);
g_signal_connect (stage, "notify::height",
G_CALLBACK (on_clutter_stage_resize), keyboard);
}
static void
update_category_fonts (EekClutterKeyboard *keyboard)
{
EekClutterKeyboardPrivate *priv =
EEK_CLUTTER_KEYBOARD_GET_PRIVATE(keyboard);
PangoContext *context;
PangoLayout *layout;
PangoFontDescription *fonts[EEK_KEYSYM_CATEGORY_LAST], *base_font;
gint i;
context = clutter_actor_get_pango_context (priv->actor);
layout = pango_layout_new (context);
base_font = pango_font_description_from_string ("Sans");
pango_layout_set_font_description (layout, base_font);
pango_font_description_free (base_font);
eek_get_fonts (EEK_KEYBOARD(keyboard),
layout,
(PangoFontDescription **)&fonts);
for (i = 0; i < EEK_KEYSYM_CATEGORY_LAST; i++) {
eek_clutter_drawing_context_set_category_font (priv->context,
i,
fonts[i]);
pango_font_description_free (fonts[i]);
}
g_object_unref (G_OBJECT(layout));
}
ClutterActor *
eek_clutter_keyboard_get_actor (EekClutterKeyboard *keyboard)
eek_clutter_keyboard_new (EekKeyboard *keyboard)
{
EekClutterKeyboardPrivate *priv =
EEK_CLUTTER_KEYBOARD_GET_PRIVATE(keyboard);
if (!priv->actor) {
priv->actor = clutter_group_new ();
g_object_ref_sink (priv->actor);
g_signal_connect (priv->actor, "realize",
G_CALLBACK (on_clutter_realize), keyboard);
g_return_val_if_fail (priv->actor, NULL);
eek_keyboard_realize (EEK_KEYBOARD(keyboard));
update_category_fonts (keyboard);
}
return priv->actor;
return g_object_new (EEK_TYPE_CLUTTER_KEYBOARD, "keyboard", keyboard, NULL);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -20,7 +20,7 @@
#ifndef EEK_CLUTTER_KEYBOARD_H
#define EEK_CLUTTER_KEYBOARD_H 1
#include "eek-clutter-section.h"
#include <clutter/clutter.h>
#include "eek-keyboard.h"
G_BEGIN_DECLS
@ -38,7 +38,7 @@ typedef struct _EekClutterKeyboardPrivate EekClutterKeyboardPrivate;
struct _EekClutterKeyboard
{
/*< private >*/
EekKeyboard parent;
ClutterGroup parent;
EekClutterKeyboardPrivate *priv;
};
@ -46,7 +46,7 @@ struct _EekClutterKeyboard
struct _EekClutterKeyboardClass
{
/*< private >*/
EekKeyboardClass parent_class;
ClutterGroupClass parent_class;
/*< private >*/
/* padding */
@ -54,8 +54,7 @@ struct _EekClutterKeyboardClass
};
GType eek_clutter_keyboard_get_type (void) G_GNUC_CONST;
EekKeyboard *eek_clutter_keyboard_new (void);
ClutterActor *eek_clutter_keyboard_get_actor (EekClutterKeyboard *keyboard);
ClutterActor *eek_clutter_keyboard_new (EekKeyboard *keyboard);
G_END_DECLS
#endif /* EEK_CLUTTER_KEYBOARD_H */

213
eek/eek-clutter-renderer.c Normal file
View File

@ -0,0 +1,213 @@
/*
* 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
*/
#include <string.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <cogl/cogl.h>
#include <cogl/cogl-pango.h>
#include <clutter/clutter.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-clutter-renderer.h"
#include "eek-key.h"
G_DEFINE_TYPE (EekClutterRenderer, eek_clutter_renderer, EEK_TYPE_RENDERER);
#define EEK_CLUTTER_RENDERER_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CLUTTER_RENDERER, EekClutterRendererPrivate))
struct _EekClutterRendererPrivate
{
GHashTable *outline_texture_cache;
};
/* This routine is copied from librsvg:
Copyright © 2005 Dom Lachowicz <cinamod@hotmail.com>
Copyright © 2005 Caleb Moore <c.moore@student.unsw.edu.au>
Copyright © 2005 Red Hat, Inc.
*/
static void
cairo_pixels_to_pixbuf (guint8 *pixels,
int rowstride,
int height)
{
int row;
/* un-premultiply data */
for (row = 0; row < height; row++) {
guint8 *row_data = (pixels + (row * rowstride));
int i;
for (i = 0; i < rowstride; i += 4) {
guint8 *b = &row_data[i];
guint32 pixel;
guint8 alpha;
memcpy (&pixel, b, sizeof (guint32));
alpha = (pixel & 0xff000000) >> 24;
if (alpha == 0) {
b[0] = b[1] = b[2] = b[3] = 0;
} else {
b[0] = (((pixel & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
b[1] = (((pixel & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha;
b[2] = (((pixel & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha;
b[3] = alpha;
}
}
}
}
static void
eek_clutter_renderer_class_init (EekClutterRendererClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (gobject_class,
sizeof (EekClutterRendererPrivate));
}
static void
eek_clutter_renderer_init (EekClutterRenderer *self)
{
EekClutterRendererPrivate *priv;
priv = self->priv = EEK_CLUTTER_RENDERER_GET_PRIVATE(self);
priv->outline_texture_cache =
g_hash_table_new_full (g_direct_hash,
g_direct_equal,
NULL,
cogl_handle_unref);
}
void
eek_clutter_renderer_render_key (EekClutterRenderer *renderer,
ClutterActor *actor,
EekKey *key)
{
EekClutterRendererPrivate *priv;
EekOutline *outline;
CoglHandle *outline_texture;
PangoLayout *layout;
PangoRectangle extents = { 0, };
CoglColor color = { 0x00, 0x00, 0x00, 0xFF };
ClutterGeometry geom;
gulong oref;
EekKeyboard *keyboard;
g_assert (EEK_IS_CLUTTER_RENDERER(renderer));
g_assert (CLUTTER_IS_ACTOR(actor));
g_assert (EEK_IS_KEY(key));
oref = eek_key_get_oref (key);
g_object_get (renderer, "keyboard", &keyboard, NULL);
outline = eek_keyboard_get_outline (keyboard, oref);
g_object_unref (keyboard);
priv = EEK_CLUTTER_RENDERER_GET_PRIVATE(renderer);
outline_texture = g_hash_table_lookup (priv->outline_texture_cache,
outline);
if (!outline_texture) {
gint rowstride;
guint8 *data;
cairo_surface_t *surface;
cairo_t *cr;
EekBounds bounds;
gdouble scale;
GdkPixbuf *pixbuf;
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
scale = eek_renderer_get_scale (EEK_RENDERER(renderer));
rowstride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32,
bounds.width * scale);
data = g_malloc0 (rowstride * bounds.height);
surface = cairo_image_surface_create_for_data (data,
CAIRO_FORMAT_ARGB32,
bounds.width * scale,
bounds.height * scale,
rowstride);
cr = cairo_create (surface);
eek_renderer_render_key_outline (EEK_RENDERER(renderer),
cr,
key,
1.0,
FALSE);
cairo_destroy (cr);
cairo_surface_destroy (surface);
cairo_pixels_to_pixbuf (data, rowstride, bounds.height * scale);
pixbuf = gdk_pixbuf_new_from_data (data,
GDK_COLORSPACE_RGB,
TRUE,
8,
bounds.width * scale,
bounds.height * scale,
rowstride,
(GdkPixbufDestroyNotify) g_free,
data);
outline_texture =
cogl_texture_new_from_data (gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf),
COGL_TEXTURE_NONE,
gdk_pixbuf_get_has_alpha (pixbuf)
? COGL_PIXEL_FORMAT_RGBA_8888
: COGL_PIXEL_FORMAT_RGB_888,
COGL_PIXEL_FORMAT_ANY,
gdk_pixbuf_get_rowstride (pixbuf),
gdk_pixbuf_get_pixels (pixbuf));
g_object_unref (pixbuf);
g_hash_table_insert (priv->outline_texture_cache,
outline,
outline_texture);
}
clutter_actor_get_allocation_geometry (actor, &geom);
cogl_set_source_texture (outline_texture);
cogl_rectangle (0.0f, 0.0f, geom.width, geom.height);
layout = eek_renderer_create_pango_layout (EEK_RENDERER(renderer));
eek_renderer_render_key_label (EEK_RENDERER(renderer), layout, key);
pango_layout_get_extents (layout, NULL, &extents);
cogl_pango_render_layout (layout,
(geom.width - extents.width / PANGO_SCALE) / 2,
(geom.height - extents.height / PANGO_SCALE) / 2,
&color,
0);
g_object_unref (layout);
}
EekClutterRenderer *
eek_clutter_renderer_new (EekKeyboard *keyboard,
PangoContext *pcontext)
{
EekClutterRenderer *renderer;
renderer = g_object_new (EEK_TYPE_CLUTTER_RENDERER,
"keyboard", keyboard,
"pango-context", pcontext,
NULL);
return renderer;
}

View File

@ -0,0 +1,64 @@
/*
* 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_CLUTTER_RENDERER_H
#define EEK_CLUTTER_RENDERER_H 1
#include "eek-renderer.h"
G_BEGIN_DECLS
#define EEK_TYPE_CLUTTER_RENDERER (eek_clutter_renderer_get_type())
#define EEK_CLUTTER_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_CLUTTER_RENDERER, EekClutterRenderer))
#define EEK_CLUTTER_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_CLUTTER_RENDERER, EekClutterRendererClass))
#define EEK_IS_CLUTTER_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_CLUTTER_RENDERER))
#define EEK_IS_CLUTTER_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_CLUTTER_RENDERER))
#define EEK_CLUTTER_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_CLUTTER_RENDERER, EekClutterRendererClass))
typedef struct _EekClutterRenderer EekClutterRenderer;
typedef struct _EekClutterRendererClass EekClutterRendererClass;
typedef struct _EekClutterRendererPrivate EekClutterRendererPrivate;
struct _EekClutterRenderer {
EekRenderer parent;
EekClutterRendererPrivate *priv;
};
struct _EekClutterRendererClass
{
EekRendererClass parent_class;
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_clutter_renderer_get_type
(void) G_GNUC_CONST;
EekClutterRenderer *eek_clutter_renderer_new (EekKeyboard *keyboard,
PangoContext *pcontext);
void eek_clutter_renderer_render_key
(EekClutterRenderer *renderer,
ClutterActor *actor,
EekKey *key);
G_END_DECLS
#endif /* EEK_CLUTTER_RENDERER_H */

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -23,106 +23,135 @@
#endif /* HAVE_CONFIG_H */
#include "eek-clutter-section.h"
#include "eek-clutter-key.h"
G_DEFINE_TYPE (EekClutterSection, eek_clutter_section, EEK_TYPE_SECTION);
enum {
PROP_0,
PROP_SECTION,
PROP_RENDERER,
PROP_LAST
};
G_DEFINE_TYPE (EekClutterSection, eek_clutter_section, CLUTTER_TYPE_GROUP);
#define EEK_CLUTTER_SECTION_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CLUTTER_SECTION, EekClutterSectionPrivate))
struct _EekClutterSectionPrivate
{
EekClutterDrawingContext *context;
ClutterActor *actor;
EekSection *section;
EekClutterRenderer *renderer;
};
static void
eek_clutter_section_real_set_name (EekElement *self,
const gchar *name)
{
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(self);
EEK_ELEMENT_CLASS (eek_clutter_section_parent_class)->
set_name (self, name);
if (priv->actor)
clutter_actor_set_name (priv->actor, name);
}
static void
eek_clutter_section_real_set_bounds (EekElement *self,
EekBounds *bounds)
{
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(self);
EEK_ELEMENT_CLASS (eek_clutter_section_parent_class)->
set_bounds (self, bounds);
if (priv->actor) {
clutter_actor_set_position (priv->actor, bounds->x, bounds->y);
clutter_actor_set_size (priv->actor, bounds->width, bounds->height);
}
}
static void
eek_clutter_section_real_set_angle (EekSection *self,
gint angle)
{
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(self);
EEK_SECTION_CLASS (eek_clutter_section_parent_class)->
set_angle (self, angle);
g_return_if_fail (priv->actor);
clutter_actor_set_rotation (priv->actor,
CLUTTER_Z_AXIS,
eek_section_get_angle (self),
0, 0, 0);
}
static void
pressed_event (EekKey *key, gpointer user_data)
{
g_signal_emit_by_name (user_data, "key-pressed", key);
}
static void
released_event (EekKey *key, gpointer user_data)
{
g_signal_emit_by_name (user_data, "key-released", key);
}
static EekKey *
eek_clutter_section_real_create_key (EekSection *self,
gint column,
gint row)
{
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(self);
EekKey *key;
gint num_columns, num_rows;
EekOrientation orientation;
struct _CreateKeyCallbackData {
ClutterActor *actor;
EekClutterRenderer *renderer;
};
typedef struct _CreateKeyCallbackData CreateKeyCallbackData;
num_rows = eek_section_get_n_rows (self);
g_return_val_if_fail (0 <= row && row < num_rows, NULL);
eek_section_get_row (self, row, &num_columns, &orientation);
g_return_val_if_fail (column < num_columns, NULL);
static void
create_key (EekElement *element, gpointer user_data)
{
CreateKeyCallbackData *data = user_data;
ClutterActor *key;
key = eek_clutter_key_new (priv->context, column, row);
g_return_val_if_fail (key, NULL);
g_signal_connect (key, "pressed", G_CALLBACK(pressed_event), self);
g_signal_connect (key, "released", G_CALLBACK(released_event), self);
key = eek_clutter_key_new (EEK_KEY(element), data->renderer);
clutter_container_add_actor (CLUTTER_CONTAINER(data->actor), key);
}
EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self),
EEK_ELEMENT(key));
static void
set_position (ClutterActor *self)
{
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(self);
EekBounds bounds;
gdouble scale;
actor = eek_clutter_section_get_actor (EEK_CLUTTER_SECTION(self));
clutter_container_add_actor
(CLUTTER_CONTAINER(actor),
eek_clutter_key_get_actor (EEK_CLUTTER_KEY(key)));
eek_element_get_bounds (EEK_ELEMENT(priv->section), &bounds);
scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer));
clutter_actor_set_position (self, bounds.x * scale, bounds.y * scale);
}
return key;
static void
eek_clutter_section_real_realize (ClutterActor *self)
{
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(self);
CreateKeyCallbackData data;
clutter_actor_set_rotation (self,
CLUTTER_Z_AXIS,
eek_section_get_angle (priv->section),
0.0f, 0.0f, 0.0f);
set_position (self);
data.actor = self;
data.renderer = priv->renderer;
eek_container_foreach_child (EEK_CONTAINER(priv->section),
create_key,
&data);
}
static void
eek_clutter_section_real_paint (ClutterActor *self)
{
set_position (self);
CLUTTER_ACTOR_CLASS (eek_clutter_section_parent_class)->
paint (self);
}
static void
eek_clutter_section_real_get_preferred_width (ClutterActor *self,
float for_height,
float *min_width_p,
float *natural_width_p)
{
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(self);
EekBounds bounds;
gdouble scale;
scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer));
eek_element_get_bounds (EEK_ELEMENT(priv->section), &bounds);
*min_width_p = 0.0f;
*natural_width_p = bounds.width * scale;
}
static void
eek_clutter_section_real_get_preferred_height (ClutterActor *self,
float for_width,
float *min_height_p,
float *natural_height_p)
{
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(self);
EekBounds bounds;
gdouble scale;
scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer));
eek_element_get_bounds (EEK_ELEMENT(priv->section), &bounds);
*min_height_p = 0.0f;
*natural_height_p = bounds.height * scale;
}
static void
eek_clutter_section_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(object);
switch (prop_id) {
case PROP_SECTION:
priv->section = g_value_get_object (value);
g_object_ref (priv->section);
break;
case PROP_RENDERER:
priv->renderer = g_value_get_object (value);
g_object_ref (priv->renderer);
break;
default:
g_object_set_property (object,
g_param_spec_get_name (pspec),
value);
break;
}
}
static void
@ -130,31 +159,57 @@ eek_clutter_section_dispose (GObject *object)
{
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(object);
if (priv->context) {
g_object_unref (priv->context);
priv->context = NULL;
if (priv->renderer) {
g_object_unref (priv->renderer);
priv->renderer = NULL;
}
if (priv->actor) {
g_object_unref (priv->actor);
priv->actor = NULL;
if (priv->section) {
g_object_unref (priv->section);
priv->section = NULL;
}
G_OBJECT_CLASS (eek_clutter_section_parent_class)->dispose (object);
}
static void
eek_clutter_section_class_init (EekClutterSectionClass *klass)
{
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
EekElementClass *element_class = EEK_ELEMENT_CLASS (klass);
EekSectionClass *section_class = EEK_SECTION_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class, sizeof (EekClutterSectionPrivate));
section_class->set_angle = eek_clutter_section_real_set_angle;
section_class->create_key = eek_clutter_section_real_create_key;
element_class->set_name = eek_clutter_section_real_set_name;
element_class->set_bounds = eek_clutter_section_real_set_bounds;
actor_class->realize =
eek_clutter_section_real_realize;
actor_class->paint =
eek_clutter_section_real_paint;
actor_class->get_preferred_width =
eek_clutter_section_real_get_preferred_width;
actor_class->get_preferred_height =
eek_clutter_section_real_get_preferred_height;
gobject_class->set_property = eek_clutter_section_set_property;
gobject_class->dispose = eek_clutter_section_dispose;
pspec = g_param_spec_object ("section",
"Section",
"Section",
EEK_TYPE_SECTION,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
g_object_class_install_property (gobject_class,
PROP_SECTION,
pspec);
pspec = g_param_spec_object ("renderer",
"Renderer",
"Renderer",
EEK_TYPE_RENDERER,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
g_object_class_install_property (gobject_class,
PROP_RENDERER,
pspec);
}
static void
@ -162,29 +217,16 @@ eek_clutter_section_init (EekClutterSection *self)
{
EekClutterSectionPrivate *priv;
priv = self->priv = EEK_CLUTTER_SECTION_GET_PRIVATE (self);
priv->actor = NULL;
priv->section = NULL;
priv->renderer = NULL;
}
ClutterActor *
eek_clutter_section_get_actor (EekClutterSection *section)
eek_clutter_section_new (EekSection *section,
EekClutterRenderer *renderer)
{
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(section);
if (!priv->actor) {
priv->actor = clutter_group_new ();
g_object_ref_sink (priv->actor);
}
return priv->actor;
}
EekSection *
eek_clutter_section_new (EekClutterDrawingContext *context)
{
EekClutterSection *section;
g_return_val_if_fail (context, NULL);
section = g_object_new (EEK_TYPE_CLUTTER_SECTION, NULL);
section->priv->context = context;
g_object_ref_sink (G_OBJECT(section->priv->context));
return EEK_SECTION(section);
return g_object_new (EEK_TYPE_CLUTTER_SECTION,
"section", section,
"renderer", renderer,
NULL);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -20,9 +20,9 @@
#ifndef EEK_CLUTTER_SECTION_H
#define EEK_CLUTTER_SECTION_H 1
#include "eek-clutter-drawing-context.h"
#include "eek-clutter-key.h"
#include <clutter/clutter.h>
#include "eek-section.h"
#include "eek-clutter-renderer.h"
G_BEGIN_DECLS
#define EEK_TYPE_CLUTTER_SECTION (eek_clutter_section_get_type())
@ -39,7 +39,7 @@ typedef struct _EekClutterSectionPrivate EekClutterSectionPrivate;
struct _EekClutterSection
{
/*< private >*/
EekSection parent;
ClutterGroup parent;
EekClutterSectionPrivate *priv;
};
@ -47,16 +47,16 @@ struct _EekClutterSection
struct _EekClutterSectionClass
{
/*< private >*/
EekSectionClass parent_class;
ClutterGroupClass parent_class;
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_clutter_section_get_type (void) G_GNUC_CONST;
EekSection * eek_clutter_section_new (EekClutterDrawingContext *context);
ClutterActor *eek_clutter_section_get_actor (EekClutterSection *section);
GType eek_clutter_section_get_type (void) G_GNUC_CONST;
ClutterActor *eek_clutter_section_new (EekSection *section,
EekClutterRenderer *renderer);
G_END_DECLS
#endif /* EEK_CLUTTER_SECTION_H */

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -31,6 +31,7 @@
#endif /* HAVE_CONFIG_H */
#include "eek-container.h"
#include "eek-serializable.h"
enum {
CHILD_ADDED,
@ -40,7 +41,11 @@ enum {
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_ABSTRACT_TYPE (EekContainer, eek_container, EEK_TYPE_ELEMENT);
static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (EekContainer, eek_container, EEK_TYPE_ELEMENT,
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init));
#define EEK_CONTAINER_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CONTAINER, EekContainerPrivate))
@ -51,6 +56,60 @@ struct _EekContainerPrivate
GSList *children;
};
static EekSerializableIface *eek_container_parent_serializable_iface;
static void
eek_container_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekContainerPrivate *priv = EEK_CONTAINER_GET_PRIVATE(self);
GSList *head;
GVariantBuilder array;
eek_container_parent_serializable_iface->serialize (self, builder);
g_variant_builder_init (&array, G_VARIANT_TYPE("av"));
for (head = priv->children; head; head = g_slist_next (head)) {
GVariant *variant =
eek_serializable_serialize (EEK_SERIALIZABLE(head->data));
g_variant_builder_add (&array, "v", variant);
}
g_variant_builder_add (builder, "v", g_variant_builder_end (&array));
}
static gsize
eek_container_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
GVariant *array, *child;
GVariantIter iter;
index = eek_container_parent_serializable_iface->deserialize (self,
variant,
index);
g_variant_get_child (variant, index++, "v", &array);
g_variant_iter_init (&iter, array);
while (g_variant_iter_next (&iter, "v", &child)) {
EekSerializable *serializable = eek_serializable_deserialize (child);
eek_container_add_child (EEK_CONTAINER(self),
EEK_ELEMENT(serializable));
}
return index;
}
static void
eek_serializable_iface_init (EekSerializableIface *iface)
{
eek_container_parent_serializable_iface =
g_type_interface_peek_parent (iface);
iface->serialize = eek_container_real_serialize;
iface->deserialize = eek_container_real_deserialize;
}
static void
eek_container_real_add_child (EekContainer *self,
EekElement *child)
@ -58,10 +117,11 @@ eek_container_real_add_child (EekContainer *self,
EekContainerPrivate *priv = EEK_CONTAINER_GET_PRIVATE(self);
g_return_if_fail (EEK_IS_ELEMENT(child));
g_object_ref_sink (child);
g_object_ref (child);
priv->children = g_slist_prepend (priv->children, child);
eek_element_set_parent (child, EEK_ELEMENT(self));
g_signal_emit_by_name (self, "child-added", child);
}
static void
@ -77,6 +137,7 @@ eek_container_real_remove_child (EekContainer *self,
g_object_unref (child);
priv->children = g_slist_remove_link (priv->children, head);
eek_element_set_parent (child, NULL);
g_signal_emit_by_name (self, "child-removed", child);
}
static void
@ -111,24 +172,14 @@ eek_container_dispose (GObject *object)
EekContainerPrivate *priv = EEK_CONTAINER_GET_PRIVATE(object);
GSList *head;
for (head = priv->children; head; head = g_slist_next (head)) {
if (head->data) {
g_object_unref (head->data);
head->data = NULL;
}
for (head = priv->children; head; head = priv->children) {
g_object_unref (head->data);
priv->children = g_slist_next (head);
g_slist_free1 (head);
}
G_OBJECT_CLASS(eek_container_parent_class)->dispose (object);
}
static void
eek_container_finalize (GObject *object)
{
EekContainerPrivate *priv = EEK_CONTAINER_GET_PRIVATE(object);
g_slist_free (priv->children);
G_OBJECT_CLASS(eek_container_parent_class)->finalize (object);
}
static void
eek_container_class_init (EekContainerClass *klass)
{
@ -142,7 +193,10 @@ eek_container_class_init (EekContainerClass *klass)
klass->foreach_child = eek_container_real_foreach_child;
klass->find = eek_container_real_find;
gobject_class->finalize = eek_container_finalize;
/* signals */
klass->child_added = NULL;
klass->child_removed = NULL;
gobject_class->dispose = eek_container_dispose;
/**
@ -154,7 +208,7 @@ eek_container_class_init (EekContainerClass *klass)
* added to @container.
*/
signals[CHILD_ADDED] =
g_signal_new ("child-added",
g_signal_new (I_("child-added"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(EekContainerClass, child_added),
@ -172,7 +226,7 @@ eek_container_class_init (EekContainerClass *klass)
* removed from @container.
*/
signals[CHILD_REMOVED] =
g_signal_new ("child-removed",
g_signal_new (I_("child-removed"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(EekContainerClass, child_removed),
@ -231,33 +285,10 @@ eek_container_find (EekContainer *container,
user_data);
}
static gint
compare_element_by_position (EekElement *element, gpointer user_data)
void
eek_container_add_child (EekContainer *container, EekElement *element)
{
EekBounds bounds;
EekPoint *point = user_data;
eek_element_get_bounds (element, &bounds);
if (bounds.x <= point->x && bounds.y <= point->y &&
point->x <= (bounds.x + bounds.width) &&
point->y <= (bounds.y + bounds.height))
return 0;
return -1;
}
EekElement *
eek_container_find_by_position (EekContainer *container,
gdouble x,
gdouble y)
{
EekBounds bounds;
EekPoint point;
g_return_val_if_fail (EEK_IS_CONTAINER(container), NULL);
eek_element_get_bounds (EEK_ELEMENT(container), &bounds);
point.x = x - bounds.x;
point.y = y - bounds.y;
return eek_container_find (container,
compare_element_by_position,
&point);
g_return_if_fail (EEK_IS_CONTAINER(container));
g_return_if_fail (EEK_IS_ELEMENT(element));
return EEK_CONTAINER_GET_CLASS(container)->add_child (container, element);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -57,42 +57,40 @@ struct _EekContainerClass
/*< private >*/
EekElementClass parent_class;
void (* add_child) (EekContainer *self,
EekElement *element);
void (* add_child) (EekContainer *self,
EekElement *element);
void (* remove_child) (EekContainer *self,
EekElement *element);
void (* remove_child) (EekContainer *self,
EekElement *element);
/*< public >*/
void (* foreach_child) (EekContainer *self,
EekCallback callback,
gpointer user_data);
EekElement *(* find) (EekContainer *self,
EekCompareFunc func,
gpointer user_data);
void (* foreach_child) (EekContainer *self,
EekCallback callback,
gpointer user_data);
EekElement *(* find) (EekContainer *self,
EekCompareFunc func,
gpointer data);
/* signals */
void (* child_added) (EekContainer *self,
EekElement *element);
void (* child_removed) (EekContainer *self,
EekElement *element);
void (* child_added) (EekContainer *self,
EekElement *element);
void (* child_removed) (EekContainer *self,
EekElement *element);
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_container_get_type (void) G_GNUC_CONST;
GType eek_container_get_type (void) G_GNUC_CONST;
void eek_container_foreach_child (EekContainer *container,
EekCallback callback,
gpointer user_data);
EekElement *eek_container_find (EekContainer *container,
EekCompareFunc func,
gpointer user_data);
EekElement *eek_container_find_by_position (EekContainer *container,
gdouble x,
gdouble y);
void eek_container_foreach_child (EekContainer *container,
EekCallback callback,
gpointer user_data);
EekElement *eek_container_find (EekContainer *container,
EekCompareFunc func,
gpointer user_data);
void eek_container_add_child (EekContainer *container,
EekElement *element);
G_END_DECLS
#endif /* EEK_CONTAINER_H */

View File

@ -1,466 +0,0 @@
/*
* Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 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 <math.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-keyboard.h"
#include "eek-key.h"
#include "eek-drawing.h"
#include "eek-keysym.h"
void
eek_draw_text_on_layout (PangoLayout *layout,
const gchar *text)
{
/* pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); */
pango_layout_set_text (layout, text, -1);
}
struct _GetFontSizeCallbackData
{
PangoLayout *layout;
EekKeysymCategory category;
gint minimum_font_size;
gint font_size;
};
typedef struct _GetFontSizeCallbackData GetFontSizeCallbackData;
static gint
get_font_size (const gchar *text,
EekBounds *bounds,
PangoLayout *layout)
{
gdouble scale_x, scale_y;
const PangoFontDescription *base_font_desc;
PangoFontDescription *font_desc;
PangoRectangle logical_rect = { 0, };
gint font_size;
layout = pango_layout_copy (layout);
base_font_desc = pango_layout_get_font_description (layout);
font_desc = pango_font_description_copy (base_font_desc);
font_size = eek_bounds_long_side (bounds) * PANGO_SCALE;
pango_font_description_set_size (font_desc, font_size);
pango_layout_set_font_description (layout, font_desc);
pango_font_description_free (font_desc);
eek_draw_text_on_layout (layout, text);
pango_layout_get_extents (layout, NULL, &logical_rect);
scale_x = scale_y = 1.0;
if (logical_rect.width > bounds->width * PANGO_SCALE)
scale_x = bounds->width * PANGO_SCALE / logical_rect.width;
if (logical_rect.height > bounds->height * PANGO_SCALE)
scale_y = bounds->height * PANGO_SCALE / logical_rect.height;
g_object_unref (layout);
return font_size * (scale_x < scale_y ? scale_x : scale_y);
}
static void
egf_key_callback (EekElement *element,
gpointer user_data)
{
EekKey *key = EEK_KEY(element);
GetFontSizeCallbackData *data = user_data;
gdouble font_size;
guint keysym;
EekBounds bounds;
gchar *label;
keysym = eek_key_get_keysym (key);
if (keysym == EEK_INVALID_KEYSYM ||
eek_keysym_get_category (keysym) != data->category)
return;
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
label = eek_keysym_to_string (keysym);
if (!label)
return;
font_size = get_font_size (label, &bounds, data->layout);
if (font_size < data->font_size && font_size >= data->minimum_font_size)
data->font_size = font_size;
g_free (label);
}
static void
egf_section_callback (EekElement *element,
gpointer user_data)
{
eek_container_foreach_child (EEK_CONTAINER(element),
egf_key_callback,
user_data);
}
static PangoFontDescription *
get_font_for_category (EekKeyboard *keyboard,
EekKeysymCategory category,
PangoLayout *layout,
gdouble minimum_font_size,
gdouble maximum_font_size)
{
GetFontSizeCallbackData data;
PangoFontDescription *font_desc;
const PangoFontDescription *base_font_desc;
data.layout = layout;
data.category = category;
data.minimum_font_size = minimum_font_size;
data.font_size = maximum_font_size;
eek_container_foreach_child (EEK_CONTAINER(keyboard),
egf_section_callback,
&data);
base_font_desc = pango_layout_get_font_description (layout);
font_desc = pango_font_description_copy (base_font_desc);
pango_font_description_set_size (font_desc, data.font_size);
return font_desc;
}
void
eek_get_fonts (EekKeyboard *keyboard,
PangoLayout *layout,
PangoFontDescription **fonts)
{
EekBounds bounds;
PangoFontDescription *font_desc;
gint font_size;
/* font for EEK_KEYSYM_CATEGORY_LETTER */
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
font_desc = get_font_for_category (keyboard,
EEK_KEYSYM_CATEGORY_LETTER,
layout,
0,
eek_bounds_long_side (&bounds) *
PANGO_SCALE);
font_size = pango_font_description_get_size (font_desc);
fonts[EEK_KEYSYM_CATEGORY_LETTER] = font_desc;
/* font for EEK_KEYSYM_CATEGORY_FUNCTION */
font_desc = get_font_for_category (keyboard,
EEK_KEYSYM_CATEGORY_FUNCTION,
layout,
font_size * 0.3,
font_size);
fonts[EEK_KEYSYM_CATEGORY_FUNCTION] = font_desc;
/* font for EEK_KEYSYM_CATEGORY_KEYNAME */
font_desc = get_font_for_category (keyboard,
EEK_KEYSYM_CATEGORY_KEYNAME,
layout,
font_size * 0.3,
font_size);
fonts[EEK_KEYSYM_CATEGORY_KEYNAME] = font_desc;
}
void
eek_draw_outline (cairo_t *cr, EekOutline *outline)
{
cairo_pattern_t *pat;
cairo_set_line_width (cr, 1);
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, 256.0);
cairo_pattern_add_color_stop_rgba (pat, 1, 0.5, 0.5, 0.5, 1);
cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 1);
cairo_set_source (cr, pat);
eek_draw_rounded_polygon (cr,
TRUE,
outline->corner_radius,
outline->points,
outline->num_points);
cairo_pattern_destroy (pat);
cairo_set_source_rgba (cr, 0.3, 0.3, 0.3, 0.5);
eek_draw_rounded_polygon (cr,
FALSE,
outline->corner_radius,
outline->points,
outline->num_points);
}
void
eek_draw_key_label (cairo_t *cr,
EekKey *key,
PangoFontDescription **fonts)
{
guint keysym;
EekKeysymCategory category;
gchar *label;
PangoLayout *layout;
PangoRectangle logical_rect = { 0, };
EekBounds bounds;
keysym = eek_key_get_keysym (key);
if (keysym == EEK_INVALID_KEYSYM)
return;
category = eek_keysym_get_category (keysym);
if (category == EEK_KEYSYM_CATEGORY_UNKNOWN)
return;
label = eek_keysym_to_string (keysym);
if (!label)
return;
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
layout = pango_cairo_create_layout (cr);
pango_layout_set_font_description (layout, fonts[category]);
pango_layout_set_width (layout, PANGO_SCALE * bounds.width);
pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
pango_layout_set_text (layout, label, -1);
pango_layout_get_extents (layout, NULL, &logical_rect);
cairo_rel_move_to (cr,
(bounds.width - logical_rect.width / PANGO_SCALE) / 2,
(bounds.height - logical_rect.height / PANGO_SCALE) / 2);
pango_cairo_show_layout (cr, layout);
g_free (label);
g_object_unref (layout);
}
/*
* The functions below are borrowed from
* libgnomekbd/gkbd-keyboard-drawing.c.
* Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
*
* length(), point_line_distance(), normal_form(), inverse(), multiply(),
* intersect(), rounded_corner(), draw_rounded_polygon()
*/
static gdouble
length (gdouble x, gdouble y)
{
return sqrt (x * x + y * y);
}
static gdouble
point_line_distance (gdouble ax, gdouble ay, gdouble nx, gdouble ny)
{
return ax * nx + ay * ny;
}
static void
normal_form (gdouble ax, gdouble ay,
gdouble bx, gdouble by,
gdouble * nx, gdouble * ny, gdouble * d)
{
gdouble l;
*nx = by - ay;
*ny = ax - bx;
l = length (*nx, *ny);
*nx /= l;
*ny /= l;
*d = point_line_distance (ax, ay, *nx, *ny);
}
static void
inverse (gdouble a, gdouble b, gdouble c, gdouble d,
gdouble * e, gdouble * f, gdouble * g, gdouble * h)
{
gdouble det;
det = a * d - b * c;
*e = d / det;
*f = -b / det;
*g = -c / det;
*h = a / det;
}
static void
multiply (gdouble a, gdouble b, gdouble c, gdouble d,
gdouble e, gdouble f, gdouble * x, gdouble * y)
{
*x = a * e + b * f;
*y = c * e + d * f;
}
static void
intersect (gdouble n1x, gdouble n1y, gdouble d1,
gdouble n2x, gdouble n2y, gdouble d2, gdouble * x, gdouble * y)
{
gdouble e, f, g, h;
inverse (n1x, n1y, n2x, n2y, &e, &f, &g, &h);
multiply (e, f, g, h, d1, d2, x, y);
}
/* draw an angle from the current point to b and then to c,
* with a rounded corner of the given radius.
*/
static void
rounded_corner (cairo_t * cr,
gdouble bx, gdouble by,
gdouble cx, gdouble cy, gdouble radius)
{
gdouble ax, ay;
gdouble n1x, n1y, d1;
gdouble n2x, n2y, d2;
gdouble pd1, pd2;
gdouble ix, iy;
gdouble dist1, dist2;
gdouble nx, ny, d;
gdouble a1x, a1y, c1x, c1y;
gdouble phi1, phi2;
cairo_get_current_point (cr, &ax, &ay);
#ifdef KBDRAW_DEBUG
printf (" current point: (%f, %f), radius %f:\n", ax, ay,
radius);
#endif
/* make sure radius is not too large */
dist1 = length (bx - ax, by - ay);
dist2 = length (cx - bx, cy - by);
radius = MIN (radius, MIN (dist1, dist2));
/* construct normal forms of the lines */
normal_form (ax, ay, bx, by, &n1x, &n1y, &d1);
normal_form (bx, by, cx, cy, &n2x, &n2y, &d2);
/* find which side of the line a,b the point c is on */
if (point_line_distance (cx, cy, n1x, n1y) < d1)
pd1 = d1 - radius;
else
pd1 = d1 + radius;
/* find which side of the line b,c the point a is on */
if (point_line_distance (ax, ay, n2x, n2y) < d2)
pd2 = d2 - radius;
else
pd2 = d2 + radius;
/* intersect the parallels to find the center of the arc */
intersect (n1x, n1y, pd1, n2x, n2y, pd2, &ix, &iy);
nx = (bx - ax) / dist1;
ny = (by - ay) / dist1;
d = point_line_distance (ix, iy, nx, ny);
/* a1 is the point on the line a-b where the arc starts */
intersect (n1x, n1y, d1, nx, ny, d, &a1x, &a1y);
nx = (cx - bx) / dist2;
ny = (cy - by) / dist2;
d = point_line_distance (ix, iy, nx, ny);
/* c1 is the point on the line b-c where the arc ends */
intersect (n2x, n2y, d2, nx, ny, d, &c1x, &c1y);
/* determine the first angle */
if (a1x - ix == 0)
phi1 = (a1y - iy > 0) ? M_PI_2 : 3 * M_PI_2;
else if (a1x - ix > 0)
phi1 = atan ((a1y - iy) / (a1x - ix));
else
phi1 = M_PI + atan ((a1y - iy) / (a1x - ix));
/* determine the second angle */
if (c1x - ix == 0)
phi2 = (c1y - iy > 0) ? M_PI_2 : 3 * M_PI_2;
else if (c1x - ix > 0)
phi2 = atan ((c1y - iy) / (c1x - ix));
else
phi2 = M_PI + atan ((c1y - iy) / (c1x - ix));
/* compute the difference between phi2 and phi1 mod 2pi */
d = phi2 - phi1;
while (d < 0)
d += 2 * M_PI;
while (d > 2 * M_PI)
d -= 2 * M_PI;
#ifdef KBDRAW_DEBUG
printf (" line 1 to: (%f, %f):\n", a1x, a1y);
#endif
if (!(isnan (a1x) || isnan (a1y)))
cairo_line_to (cr, a1x, a1y);
/* pick the short arc from phi1 to phi2 */
if (d < M_PI)
cairo_arc (cr, ix, iy, radius, phi1, phi2);
else
cairo_arc_negative (cr, ix, iy, radius, phi1, phi2);
#ifdef KBDRAW_DEBUG
printf (" line 2 to: (%f, %f):\n", cx, cy);
#endif
cairo_line_to (cr, cx, cy);
}
void
eek_draw_rounded_polygon (cairo_t *cr,
gboolean filled,
gdouble radius,
EekPoint *points,
gint num_points)
{
gint i, j;
cairo_move_to (cr,
(gdouble) (points[num_points - 1].x +
points[0].x) / 2,
(gdouble) (points[num_points - 1].y +
points[0].y) / 2);
#ifdef KBDRAW_DEBUG
printf (" rounded polygon of radius %f:\n", radius);
#endif
for (i = 0; i < num_points; i++) {
j = (i + 1) % num_points;
rounded_corner (cr, (gdouble) points[i].x,
(gdouble) points[i].y,
(gdouble) (points[i].x + points[j].x) / 2,
(gdouble) (points[i].y + points[j].y) / 2,
radius);
#ifdef KBDRAW_DEBUG
printf (" corner (%d, %d) -> (%d, %d):\n",
points[i].x, points[i].y, points[j].x,
points[j].y);
#endif
};
cairo_close_path (cr);
if (filled)
cairo_fill (cr);
else
cairo_stroke (cr);
}

View File

@ -1,32 +0,0 @@
#ifndef EEK_DRAWING_H
#define EEK_DRAWING_H 1
#include <pango/pangocairo.h>
#include "eek-keyboard.h"
#include "eek-keysym.h"
#include "eek-types.h"
G_BEGIN_DECLS
void eek_draw_text_on_layout (PangoLayout *layout,
const gchar *text);
void eek_get_fonts (EekKeyboard *keyboard,
PangoLayout *layout,
PangoFontDescription **fonts);
void eek_draw_outline (cairo_t *cr,
EekOutline *outline);
void eek_draw_key_label (cairo_t *cr,
EekKey *key,
PangoFontDescription **fonts);
void eek_draw_rounded_polygon (cairo_t *cr,
gboolean filled,
gdouble radius,
EekPoint *points,
gint num_points);
G_END_DECLS
#endif /* EEK_DRAWING_H */

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -34,6 +34,7 @@
#include "eek-element.h"
#include "eek-container.h"
#include "eek-serializable.h"
enum {
PROP_0,
@ -42,7 +43,11 @@ enum {
PROP_LAST
};
G_DEFINE_ABSTRACT_TYPE (EekElement, eek_element, G_TYPE_INITIALLY_UNOWNED);
static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (EekElement, eek_element, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init));
#define EEK_ELEMENT_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_ELEMENT, EekElementPrivate))
@ -55,6 +60,61 @@ struct _EekElementPrivate
EekElement *parent;
};
static GVariant *
_g_variant_new_bounds (EekBounds *bounds)
{
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("ad"));
g_variant_builder_add (&builder, "d", bounds->x);
g_variant_builder_add (&builder, "d", bounds->y);
g_variant_builder_add (&builder, "d", bounds->width);
g_variant_builder_add (&builder, "d", bounds->height);
return g_variant_builder_end (&builder);
}
static void
_g_variant_get_bounds (GVariant *variant, EekBounds *bounds)
{
g_variant_get_child (variant, 0, "d", &bounds->x);
g_variant_get_child (variant, 1, "d", &bounds->y);
g_variant_get_child (variant, 2, "d", &bounds->width);
g_variant_get_child (variant, 3, "d", &bounds->height);
}
static void
eek_element_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekElementPrivate *priv = EEK_ELEMENT_GET_PRIVATE(self);
g_variant_builder_add (builder, "s", priv->name == NULL ? "" : priv->name);
g_variant_builder_add (builder, "v", _g_variant_new_bounds (&priv->bounds));
}
static gsize
eek_element_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekElementPrivate *priv = EEK_ELEMENT_GET_PRIVATE(self);
GVariant *bounds;
g_variant_get_child (variant, index++, "s", &priv->name);
g_variant_get_child (variant, index++, "v", &bounds);
_g_variant_get_bounds (bounds, &priv->bounds);
return index;
}
static void
eek_serializable_iface_init (EekSerializableIface *iface)
{
iface->serialize = eek_element_real_serialize;
iface->deserialize = eek_element_real_deserialize;
}
static void
eek_element_real_set_parent (EekElement *self,
EekElement *parent)
@ -68,7 +128,7 @@ eek_element_real_set_parent (EekElement *self,
priv->parent = NULL;
} else {
g_return_if_fail (!priv->parent);
g_object_ref_sink (self);
g_object_ref (self);
priv->parent = parent;
}
}
@ -128,6 +188,7 @@ eek_element_finalize (GObject *object)
EekElementPrivate *priv = EEK_ELEMENT_GET_PRIVATE(object);
g_free (priv->name);
G_OBJECT_CLASS (eek_element_parent_class)->finalize (object);
}
static void
@ -136,7 +197,6 @@ eek_element_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec)
{
g_return_if_fail (EEK_IS_ELEMENT(object));
switch (prop_id) {
case PROP_NAME:
eek_element_set_name (EEK_ELEMENT(object),
@ -160,7 +220,6 @@ eek_element_get_property (GObject *object,
{
EekBounds bounds;
g_return_if_fail (EEK_IS_ELEMENT(object));
switch (prop_id) {
case PROP_NAME:
g_value_set_string (value, eek_element_get_name (EEK_ELEMENT(object)));
@ -351,3 +410,45 @@ eek_element_get_absolute_position (EekElement *element,
*x = ax;
*y = ay;
}
/**
* eek_element_set_position:
* @element: an #EekElement
* @x: X coordinate of top left corner
* @y: Y coordinate of top left corner
*
* Set the relative position of @element.
*/
void
eek_element_set_position (EekElement *element,
gdouble x,
gdouble y)
{
EekBounds bounds;
eek_element_get_bounds (element, &bounds);
bounds.x = x;
bounds.y = y;
eek_element_set_bounds (element, &bounds);
}
/**
* eek_element_set_size:
* @element: an #EekElement
* @width: width of @element
* @height: height of @element
*
* Set the size of @element.
*/
void
eek_element_set_size (EekElement *element,
gdouble width,
gdouble height)
{
EekBounds bounds;
eek_element_get_bounds (element, &bounds);
bounds.width = width;
bounds.height = height;
eek_element_set_bounds (element, &bounds);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -37,7 +37,7 @@ typedef struct _EekElementPrivate EekElementPrivate;
struct _EekElement
{
/*< private >*/
GInitiallyUnowned parent;
GObject parent;
EekElementPrivate *priv;
};
@ -45,7 +45,7 @@ struct _EekElement
struct _EekElementClass
{
/*< private >*/
GInitiallyUnownedClass parent_class;
GObjectClass parent_class;
void (* set_parent) (EekElement *self,
EekElement *parent);
EekElement *(* get_parent) (EekElement *self);
@ -81,6 +81,13 @@ void eek_element_set_bounds (EekElement *element,
void eek_element_get_bounds (EekElement *element,
EekBounds *bounds);
void eek_element_set_position (EekElement *element,
gdouble x,
gdouble y);
void eek_element_set_size (EekElement *element,
gdouble width,
gdouble height);
void eek_element_get_absolute_position (EekElement *element,
gdouble *x,
gdouble *y);

View File

@ -1,5 +1,5 @@
# Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
# Copyright (C) 2010 Red Hat, Inc.
# 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
@ -25,6 +25,6 @@ Name: libeek-gtk
Description: A Library to Create Keyboard-like UI (GTK Support)
URL: http://ueno.github.com/eekboard/
Version: @VERSION@
Requires: eek-@EEK_API_VERSION@ gtk+-2.0
Requires: eek-@EEK_API_VERSION@ gtk+-@GTK_API_VERSION@
Libs: -L${libdir} -leek-gtk
Cflags: -I${includedir}/eek-@EEK_API_VERSION@

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -20,80 +20,219 @@
/**
* SECTION:eek-gtk-keyboard
* @short_description: #EekKeyboard that can be converted into a #GtkWidget
* @short_description: a #GtkWidget displaying #EekKeyboard
*/
#include <string.h>
#include <math.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-gtk-keyboard.h"
#include "eek-drawing.h"
#include "eek-renderer.h"
#include "eek-keyboard.h"
#include "eek-section.h"
#include "eek-key.h"
#include "eek-keysym.h"
#include "eek-symbol.h"
G_DEFINE_TYPE (EekGtkKeyboard, eek_gtk_keyboard, EEK_TYPE_KEYBOARD);
enum {
PROP_0,
PROP_KEYBOARD,
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))
#define SCALE 1.5
/* 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
{
GtkWidget *widget;
/* pixmap of entire keyboard (for expose event) */
GdkPixmap *pixmap;
/* mapping from outline pointer to pixmap */
GHashTable *outline_textures;
/* mapping from outline pointer to large pixmap */
GHashTable *large_outline_textures;
PangoFontDescription *fonts[EEK_KEYSYM_CATEGORY_LAST];
gdouble scale;
EekKey *key;
EekRenderer *renderer;
EekKeyboard *keyboard;
EekKey *dragged_key;
gulong key_pressed_handler;
gulong key_released_handler;
gulong symbol_index_changed_handler;
};
static void prepare_keyboard_pixmap (EekGtkKeyboard *keyboard);
static EekColor * color_from_gdk_color (GdkColor *gdk_color);
static void on_key_pressed (EekKeyboard *keyboard,
EekKey *key,
gpointer user_data);
static void on_key_released (EekKeyboard *keyboard,
EekKey *key,
gpointer user_data);
static void on_symbol_index_changed (EekKeyboard *keyboard,
gint group,
gint level,
gpointer user_data);
static void render_pressed_key (GtkWidget *widget,
EekKey *key);
static void
eek_gtk_keyboard_real_set_keysym_index (EekKeyboard *self,
gint group,
gint level)
eek_gtk_keyboard_real_realize (GtkWidget *self)
{
gint g, l;
gtk_widget_set_double_buffered (self, FALSE);
gtk_widget_set_events (self,
GDK_EXPOSURE_MASK |
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK);
eek_keyboard_get_keysym_index (self, &g, &l);
EEK_KEYBOARD_CLASS(eek_gtk_keyboard_parent_class)->
set_keysym_index (self, group, level);
if (g != group || l != level) {
EekGtkKeyboard *keyboard = EEK_GTK_KEYBOARD(self);
EekGtkKeyboardPrivate *priv =
EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)->realize (self);
}
static gboolean
eek_gtk_keyboard_real_draw (GtkWidget *self,
cairo_t *cr)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
GtkAllocation allocation;
gtk_widget_get_allocation (self, &allocation);
if (!priv->renderer) {
GtkStyle *style;
GtkStateType state;
GtkAllocation allocation;
PangoContext *pcontext;
if (!priv->widget || !gtk_widget_get_realized (priv->widget))
return;
pcontext = gtk_widget_get_pango_context (self);
priv->renderer = eek_renderer_new (priv->keyboard, pcontext);
prepare_keyboard_pixmap (keyboard);
state = gtk_widget_get_state (GTK_WIDGET (priv->widget));
gtk_widget_get_allocation (GTK_WIDGET (priv->widget), &allocation);
gdk_draw_drawable (gtk_widget_get_window (priv->widget),
gtk_widget_get_style (priv->widget)->fg_gc[state],
priv->pixmap,
0, 0,
0, 0,
allocation.width, allocation.height);
eek_renderer_set_allocation_size (priv->renderer,
allocation.width,
allocation.height);
style = gtk_widget_get_style (self);
state = gtk_widget_get_state (self);
eek_renderer_set_foreground
(priv->renderer,
color_from_gdk_color (&style->fg[state]));
eek_renderer_set_background
(priv->renderer,
color_from_gdk_color (&style->bg[state]));
}
eek_renderer_render_keyboard (priv->renderer, cr);
/* redraw dragged key */
if (priv->dragged_key)
render_pressed_key (self, priv->dragged_key);
return FALSE;
}
#if !GTK_CHECK_VERSION (2, 91, 2)
static gboolean
eek_gtk_keyboard_real_expose_event (GtkWidget *self,
GdkEventExpose *event)
{
gboolean retval;
cairo_t *cr;
cr = gdk_cairo_create (GDK_DRAWABLE (gtk_widget_get_window (self)));
retval = eek_gtk_keyboard_real_draw (self, cr);
cairo_destroy (cr);
return retval;
}
#endif /* !GTK_CHECK_VERSION (2, 91, 2) */
static void
eek_gtk_keyboard_real_size_allocate (GtkWidget *self,
GtkAllocation *allocation)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
if (priv->renderer)
eek_renderer_set_allocation_size (priv->renderer,
allocation->width,
allocation->height);
GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)->
size_allocate (self, allocation);
}
static gboolean
eek_gtk_keyboard_real_button_press_event (GtkWidget *self,
GdkEventButton *event)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
EekKey *key;
key = eek_renderer_find_key_by_position (priv->renderer,
(gdouble)event->x,
(gdouble)event->y);
if (priv->dragged_key && priv->dragged_key != key)
g_signal_emit_by_name (priv->dragged_key, "released", priv->keyboard);
if (key && !eek_key_is_pressed (key)) {
priv->dragged_key = key;
g_signal_emit_by_name (key, "pressed", priv->keyboard);
}
return TRUE;
}
static gboolean
eek_gtk_keyboard_real_button_release_event (GtkWidget *self,
GdkEventButton *event)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
if (priv->dragged_key) {
g_signal_emit_by_name (priv->dragged_key, "released", priv->keyboard);
priv->dragged_key = NULL;
}
return TRUE;
}
static void
eek_gtk_keyboard_set_keyboard (EekGtkKeyboard *self,
EekKeyboard *keyboard)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
priv->keyboard = g_object_ref (keyboard);
priv->key_pressed_handler =
g_signal_connect (priv->keyboard, "key-pressed",
G_CALLBACK(on_key_pressed), self);
priv->key_released_handler =
g_signal_connect (priv->keyboard, "key-released",
G_CALLBACK(on_key_released), self);
priv->symbol_index_changed_handler =
g_signal_connect (priv->keyboard, "symbol-index-changed",
G_CALLBACK(on_symbol_index_changed), self);
}
static void
eek_gtk_keyboard_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EekKeyboard *keyboard;
switch (prop_id) {
case PROP_KEYBOARD:
keyboard = g_value_get_object (value);
eek_gtk_keyboard_set_keyboard (EEK_GTK_KEYBOARD(object), keyboard);
break;
default:
g_object_set_property (object,
g_param_spec_get_name (pspec),
value);
break;
}
}
@ -102,39 +241,65 @@ eek_gtk_keyboard_dispose (GObject *object)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(object);
if (priv->widget) {
g_object_unref (priv->widget);
priv->widget = NULL;
if (priv->renderer) {
g_object_unref (priv->renderer);
priv->renderer = NULL;
}
if (priv->keyboard) {
if (g_signal_handler_is_connected (priv->keyboard,
priv->key_pressed_handler))
g_signal_handler_disconnect (priv->keyboard,
priv->key_pressed_handler);
if (g_signal_handler_is_connected (priv->keyboard,
priv->key_released_handler))
g_signal_handler_disconnect (priv->keyboard,
priv->key_released_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);
g_object_unref (priv->keyboard);
priv->keyboard = NULL;
}
G_OBJECT_CLASS (eek_gtk_keyboard_parent_class)->dispose (object);
}
static void
eek_gtk_keyboard_finalize (GObject *object)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(object);
gint i;
g_hash_table_unref (priv->outline_textures);
g_hash_table_unref (priv->large_outline_textures);
for (i = 0; i < EEK_KEYSYM_CATEGORY_LAST; i++)
pango_font_description_free (priv->fonts[i]);
G_OBJECT_CLASS (eek_gtk_keyboard_parent_class)->finalize (object);
}
static void
eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass)
{
EekKeyboardClass *keyboard_class = EEK_KEYBOARD_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class,
sizeof (EekGtkKeyboardPrivate));
keyboard_class->set_keysym_index = eek_gtk_keyboard_real_set_keysym_index;
widget_class->realize = eek_gtk_keyboard_real_realize;
#if GTK_CHECK_VERSION (2, 91, 2)
widget_class->draw = eek_gtk_keyboard_real_draw;
#else /* GTK_CHECK_VERSION (2, 91, 2) */
widget_class->expose_event = eek_gtk_keyboard_real_expose_event;
#endif /* !GTK_CHECK_VERSION (2, 91, 2) */
widget_class->size_allocate = eek_gtk_keyboard_real_size_allocate;
widget_class->button_press_event =
eek_gtk_keyboard_real_button_press_event;
widget_class->button_release_event =
eek_gtk_keyboard_real_button_release_event;
gobject_class->set_property = eek_gtk_keyboard_set_property;
gobject_class->dispose = eek_gtk_keyboard_dispose;
gobject_class->finalize = eek_gtk_keyboard_finalize;
pspec = g_param_spec_object ("keyboard",
"Keyboard",
"Keyboard",
EEK_TYPE_KEYBOARD,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
g_object_class_install_property (gobject_class,
PROP_KEYBOARD,
pspec);
}
static void
@ -143,429 +308,117 @@ eek_gtk_keyboard_init (EekGtkKeyboard *self)
EekGtkKeyboardPrivate *priv;
priv = self->priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
priv->widget = NULL;
priv->pixmap = NULL;
priv->outline_textures =
g_hash_table_new_full (g_direct_hash,
g_direct_equal,
NULL,
g_object_unref);
priv->large_outline_textures =
g_hash_table_new_full (g_direct_hash,
g_direct_equal,
NULL,
g_object_unref);
memset (priv->fonts, 0, sizeof priv->fonts);
priv->scale = 1.0;
priv->key = NULL;
priv->renderer = NULL;
priv->keyboard = NULL;
priv->dragged_key = NULL;
}
/**
* eek_gtk_keyboard_new:
* @keyboard: an #EekKeyboard
*
* Create a new #EekGtkKeyboard.
* Create a new #GtkWidget displaying @keyboard.
* Returns: a #GtkWidget
*/
EekKeyboard*
eek_gtk_keyboard_new (void)
{
return g_object_new (EEK_TYPE_GTK_KEYBOARD, NULL);
}
struct _DrawingContext
{
EekGtkKeyboard *keyboard;
cairo_t *cr;
GdkColor *fg, *bg;
};
typedef struct _DrawingContext DrawingContext;
static void on_key_pressed (EekKey *key, gpointer user_data);
static void on_key_released (EekKey *key, gpointer user_data);
static void
prepare_keyboard_pixmap_key_callback (EekElement *element,
gpointer user_data)
{
DrawingContext *context = user_data;
EekGtkKeyboardPrivate *priv =
EEK_GTK_KEYBOARD_GET_PRIVATE(context->keyboard);
EekKey *key = EEK_KEY(element);
EekBounds bounds;
EekOutline *outline;
GdkPixmap *texture;
eek_element_get_bounds (element, &bounds);
g_signal_connect (key, "pressed", G_CALLBACK(on_key_pressed),
context->keyboard);
g_signal_connect (key, "released", G_CALLBACK(on_key_released),
context->keyboard);
outline = eek_key_get_outline (key);
texture = g_hash_table_lookup (priv->outline_textures, outline);
if (!texture) {
cairo_t *cr;
texture =
gdk_pixmap_new (gtk_widget_get_window (GTK_WIDGET (priv->widget)),
bounds.width, bounds.height, -1);
cr = gdk_cairo_create (GDK_DRAWABLE (texture));
gdk_cairo_set_source_color (cr, context->bg);
cairo_rectangle (cr, 0, 0, bounds.width, bounds.height);
gdk_cairo_set_source_color (cr, context->fg);
eek_draw_outline (cr, outline);
cairo_destroy (cr);
g_hash_table_insert (priv->outline_textures, outline, texture);
}
cairo_save (context->cr);
cairo_translate (context->cr, bounds.x, bounds.y);
gdk_cairo_set_source_pixmap (context->cr, texture, 0, 0);
cairo_rectangle (context->cr, 0, 0, bounds.width, bounds.height);
cairo_fill (context->cr);
cairo_move_to (context->cr, 0, 0);
gdk_cairo_set_source_color (context->cr, context->fg);
eek_draw_key_label (context->cr, key, priv->fonts);
cairo_restore (context->cr);
}
static void
prepare_keyboard_pixmap_section_callback (EekElement *element,
gpointer user_data)
{
DrawingContext *context = user_data;
EekBounds bounds;
gint angle;
eek_element_get_bounds (element, &bounds);
angle = eek_section_get_angle (EEK_SECTION(element));
cairo_save (context->cr);
cairo_translate (context->cr,
bounds.x,
bounds.y);
cairo_rotate (context->cr, angle * M_PI / 180);
eek_container_foreach_child (EEK_CONTAINER(element),
prepare_keyboard_pixmap_key_callback,
context);
cairo_restore (context->cr);
}
static void
drawing_context_init (DrawingContext *context, EekGtkKeyboard *keyboard)
{
EekGtkKeyboardPrivate *priv = keyboard->priv;
GtkStateType state;
state = gtk_widget_get_state (GTK_WIDGET (priv->widget));
context->keyboard = keyboard;
context->fg = &gtk_widget_get_style (GTK_WIDGET (priv->widget))->fg[state];
context->bg = &gtk_widget_get_style (GTK_WIDGET (priv->widget))->bg[state];
}
static void
prepare_keyboard_pixmap (EekGtkKeyboard *keyboard)
{
EekGtkKeyboardPrivate *priv = keyboard->priv;
GtkAllocation allocation;
GtkStateType state;
DrawingContext context;
gtk_widget_get_allocation (GTK_WIDGET (priv->widget), &allocation);
priv->pixmap =
gdk_pixmap_new (gtk_widget_get_window (GTK_WIDGET (priv->widget)),
allocation.width, allocation.height, -1);
/* blank background */
state = gtk_widget_get_state (GTK_WIDGET (priv->widget));
gdk_draw_rectangle
(priv->pixmap,
gtk_widget_get_style (GTK_WIDGET(priv->widget))->base_gc[state],
TRUE,
0, 0, allocation.width, allocation.height);
/* draw sections on the canvas */
drawing_context_init (&context, keyboard);
context.cr = gdk_cairo_create (GDK_DRAWABLE (priv->pixmap));
cairo_scale (context.cr, priv->scale, priv->scale);
eek_container_foreach_child (EEK_CONTAINER(keyboard),
prepare_keyboard_pixmap_section_callback,
&context);
cairo_destroy (context.cr);
}
static gboolean
on_expose_event (GtkWidget *widget,
GdkEventExpose *event,
gpointer user_data)
{
EekGtkKeyboard *keyboard = user_data;
EekGtkKeyboardPrivate *priv =
EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
GtkStateType state = gtk_widget_get_state (widget);
if (!priv->pixmap) {
/* compute font sizes which fit in each key shape */
PangoFontDescription *base_font;
PangoContext *context;
PangoLayout *layout;
context = gtk_widget_get_pango_context (priv->widget);
layout = pango_layout_new (context);
base_font = gtk_widget_get_style (priv->widget)->font_desc;
pango_layout_set_font_description (layout, base_font);
eek_get_fonts (EEK_KEYBOARD(keyboard), layout, priv->fonts);
g_object_unref (layout);
prepare_keyboard_pixmap (keyboard);
}
g_return_val_if_fail (priv->pixmap, FALSE);
gdk_draw_drawable (gtk_widget_get_window (widget),
gtk_widget_get_style (widget)->fg_gc[state],
priv->pixmap,
event->area.x, event->area.y,
event->area.x, event->area.y,
event->area.width, event->area.height);
return TRUE;
}
static void
key_enlarge (EekGtkKeyboard *keyboard, EekKey *key)
{
EekGtkKeyboardPrivate *priv =
EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
EekBounds bounds;
EekOutline *outline;
gdouble ax, ay;
GdkPixmap *pixmap, *texture;
DrawingContext context;
GtkStateType state;
cairo_t *cr;
drawing_context_init (&context, keyboard);
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
eek_element_get_absolute_position (EEK_ELEMENT(key), &ax, &ay);
outline = eek_key_get_outline (key);
texture = g_hash_table_lookup (priv->large_outline_textures, outline);
if (!texture) {
texture =
gdk_pixmap_new (gtk_widget_get_window (GTK_WIDGET (priv->widget)),
bounds.width * SCALE, bounds.height * SCALE, -1);
cr = gdk_cairo_create (GDK_DRAWABLE (texture));
cairo_scale (cr, SCALE, SCALE);
gdk_cairo_set_source_color (cr, context.bg);
cairo_rectangle (cr, 0, 0, bounds.width, bounds.height);
gdk_cairo_set_source_color (cr, context.fg);
eek_draw_outline (cr, outline);
cairo_destroy (cr);
g_hash_table_insert (priv->large_outline_textures, outline, texture);
}
pixmap =
gdk_pixmap_new (gtk_widget_get_window (GTK_WIDGET (priv->widget)),
bounds.width * SCALE * priv->scale,
bounds.height * SCALE * priv->scale, -1);
cr = gdk_cairo_create (GDK_DRAWABLE (pixmap));
cairo_scale (cr, priv->scale, priv->scale);
gdk_cairo_set_source_pixmap (cr, texture, 0, 0);
cairo_rectangle (cr, 0, 0, bounds.width * SCALE, bounds.height * SCALE);
cairo_fill (cr);
cairo_move_to (cr, 0, 0);
cairo_scale (cr, SCALE, SCALE);
gdk_cairo_set_source_color (cr, context.fg);
eek_draw_key_label (cr, key, priv->fonts);
cairo_destroy (cr);
state = gtk_widget_get_state (GTK_WIDGET (priv->widget));
gdk_draw_drawable (gtk_widget_get_window (priv->widget),
gtk_widget_get_style (priv->widget)->fg_gc[state],
pixmap,
0, 0,
(ax - (bounds.width * SCALE - bounds.width) / 2) *
priv->scale,
(ay - (bounds.height * SCALE - bounds.height) / 2) *
priv->scale,
bounds.width * SCALE * priv->scale,
bounds.height * SCALE * priv->scale);
g_object_unref (pixmap);
}
static void
key_shrink (EekGtkKeyboard *keyboard, EekKey *key)
{
EekGtkKeyboardPrivate *priv =
EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
EekBounds bounds;
gdouble ax, ay;
GtkStateType state;
g_return_if_fail (priv->pixmap);
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
eek_element_get_absolute_position (EEK_ELEMENT(key), &ax, &ay);
state = gtk_widget_get_state (GTK_WIDGET (priv->widget));
ax -= (bounds.width * SCALE - bounds.width) / 2;
ay -= (bounds.height * SCALE - bounds.height) / 2;
gdk_draw_drawable (gtk_widget_get_window (priv->widget),
gtk_widget_get_style (priv->widget)->fg_gc[state],
priv->pixmap,
ax * priv->scale, ay * priv->scale,
ax * priv->scale, ay * priv->scale,
bounds.width * SCALE * priv->scale,
bounds.height * SCALE * priv->scale);
}
static void
on_key_pressed (EekKey *key, gpointer user_data)
{
EekGtkKeyboard *keyboard = user_data;
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
key_enlarge (EEK_GTK_KEYBOARD(keyboard), key);
priv->key = key;
}
static void
on_key_released (EekKey *key, gpointer user_data)
{
EekGtkKeyboard *keyboard = user_data;
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
if (priv->key) {
key_shrink (EEK_GTK_KEYBOARD(keyboard), EEK_KEY(priv->key));
priv->key = NULL;
}
key_shrink (EEK_GTK_KEYBOARD(keyboard), key);
}
static void
press_key (EekGtkKeyboard *keyboard, EekKey *key)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
if (priv->key != key)
g_signal_emit_by_name (key, "pressed", keyboard);
}
static void
release_key (EekGtkKeyboard *keyboard)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
if (priv->key)
g_signal_emit_by_name (priv->key, "released", keyboard);
}
static gboolean
on_key_event (GtkWidget *widget,
GdkEventKey *event,
gpointer user_data)
{
EekGtkKeyboard *keyboard = user_data;
EekKey *key;
key = eek_keyboard_find_key_by_keycode (EEK_KEYBOARD(keyboard),
event->hardware_keycode);
if (!key)
return FALSE;
switch (event->type) {
case GDK_KEY_PRESS:
press_key (keyboard, key);
return TRUE;
case GDK_KEY_RELEASE:
release_key (keyboard);
return TRUE;
default:
return FALSE;
}
}
static gboolean
on_button_event (GtkWidget *widget,
GdkEventButton *event,
gpointer user_data)
{
EekGtkKeyboard *keyboard = EEK_GTK_KEYBOARD(user_data);
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
EekKey *key;
gdouble x, y;
x = (gdouble)event->x / priv->scale;
y = (gdouble)event->y / priv->scale;
key = eek_keyboard_find_key_by_position (EEK_KEYBOARD(keyboard), x, y);
if (key)
switch (event->type) {
case GDK_BUTTON_PRESS:
press_key (EEK_GTK_KEYBOARD(keyboard), key);
return TRUE;
case GDK_BUTTON_RELEASE:
release_key (EEK_GTK_KEYBOARD(keyboard));
return TRUE;
default:
return FALSE;
}
return FALSE;
}
static void
on_size_allocate (GtkWidget *widget,
GtkAllocation *allocation,
gpointer user_data)
{
EekGtkKeyboard *keyboard = user_data;
EekGtkKeyboardPrivate *priv =
EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
EekBounds bounds;
GdkPixmap *pixmap;
if (priv->pixmap) {
pixmap = priv->pixmap;
priv->pixmap = NULL;
g_object_unref (pixmap);
}
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
priv->scale = allocation->width > allocation->height ?
allocation->width / bounds.width :
allocation->height / bounds.height;
}
GtkWidget *
eek_gtk_keyboard_get_widget (EekGtkKeyboard *keyboard)
eek_gtk_keyboard_new (EekKeyboard *keyboard)
{
EekGtkKeyboardPrivate *priv =
EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
if (!priv->widget) {
priv->widget = gtk_drawing_area_new ();
g_object_ref_sink (priv->widget);
gtk_widget_set_double_buffered (priv->widget, FALSE);
gtk_widget_set_events (priv->widget,
GDK_EXPOSURE_MASK |
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK);
g_signal_connect (priv->widget, "expose_event",
G_CALLBACK (on_expose_event), keyboard);
g_signal_connect (priv->widget, "size-allocate",
G_CALLBACK (on_size_allocate), keyboard);
g_signal_connect (priv->widget, "key-press-event",
G_CALLBACK (on_key_event), keyboard);
g_signal_connect (priv->widget, "key-release-event",
G_CALLBACK (on_key_event), keyboard);
g_signal_connect (priv->widget, "button-press-event",
G_CALLBACK (on_button_event), keyboard);
g_signal_connect (priv->widget, "button-release-event",
G_CALLBACK (on_button_event), keyboard);
eek_keyboard_realize (EEK_KEYBOARD(keyboard));
}
return priv->widget;
return g_object_new (EEK_TYPE_GTK_KEYBOARD, "keyboard", keyboard, NULL);
}
static EekColor *
color_from_gdk_color (GdkColor *gdk_color)
{
EekColor *color;
color = g_slice_new (EekColor);
color->red = gdk_color->red / (gdouble)0xFFFF;
color->green = gdk_color->green / (gdouble)0xFFFF;
color->blue = gdk_color->blue / (gdouble)0xFFFF;
color->alpha = 1.0;
return color;
}
static void
magnify_bounds (EekBounds *bounds, EekBounds *large_bounds, gdouble scale)
{
g_assert (scale >= 1.0);
large_bounds->width = bounds->width * scale;
large_bounds->height = bounds->height * scale;
large_bounds->x = bounds->x - (large_bounds->width - bounds->width) / 2;
large_bounds->y = bounds->y - (large_bounds->height - bounds->height) / 2;
}
static void
render_pressed_key (GtkWidget *widget,
EekKey *key)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(widget);
EekBounds bounds, large_bounds;
cairo_t *cr;
cr = gdk_cairo_create (GDK_DRAWABLE (gtk_widget_get_window (widget)));
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
magnify_bounds (&bounds, &large_bounds, 1.5);
cairo_translate (cr, large_bounds.x, large_bounds.y);
eek_renderer_render_key (priv->renderer, cr, key, 1.5, TRUE);
cairo_destroy (cr);
}
static void
on_key_pressed (EekKeyboard *keyboard,
EekKey *key,
gpointer user_data)
{
GtkWidget *widget = user_data;
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(widget);
/* renderer may have not been set yet if the widget is a popup */
if (!priv->renderer)
return;
render_pressed_key (widget, key);
}
static void
on_key_released (EekKeyboard *keyboard,
EekKey *key,
gpointer user_data)
{
GtkWidget *widget = user_data;
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(widget);
cairo_t *cr;
EekBounds bounds, large_bounds;
/* renderer may have not been set yet if the widget is a popup */
if (!priv->renderer)
return;
cr = gdk_cairo_create (GDK_DRAWABLE (gtk_widget_get_window (widget)));
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
magnify_bounds (&bounds, &large_bounds, 2.0);
cairo_rectangle (cr,
large_bounds.x,
large_bounds.y,
large_bounds.width,
large_bounds.height);
cairo_clip (cr);
eek_renderer_render_keyboard (priv->renderer, cr);
cairo_destroy (cr);
}
static void
on_symbol_index_changed (EekKeyboard *keyboard,
gint group,
gint level,
gpointer user_data)
{
GtkWidget *widget = user_data;
gtk_widget_queue_draw (widget);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -20,7 +20,9 @@
#ifndef EEK_GTK_KEYBOARD_H
#define EEK_GTK_KEYBOARD_H 1
#include <glib.h>
#include <gtk/gtk.h>
#include "eek-keyboard.h"
G_BEGIN_DECLS
@ -38,7 +40,7 @@ typedef struct _EekGtkKeyboardPrivate EekGtkKeyboardPrivate;
struct _EekGtkKeyboard
{
/*< private >*/
EekKeyboard parent;
GtkDrawingArea parent;
EekGtkKeyboardPrivate *priv;
};
@ -46,16 +48,15 @@ struct _EekGtkKeyboard
struct _EekGtkKeyboardClass
{
/*< private >*/
EekKeyboardClass parent_class;
GtkDrawingAreaClass parent_class;
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_gtk_keyboard_get_type (void) G_GNUC_CONST;
EekKeyboard *eek_gtk_keyboard_new (void);
GtkWidget *eek_gtk_keyboard_get_widget (EekGtkKeyboard *keyboard);
GType eek_gtk_keyboard_get_type (void) G_GNUC_CONST;
GtkWidget *eek_gtk_keyboard_new (EekKeyboard *keyboard);
G_END_DECLS
#endif /* EEK_GTK_KEYBOARD_H */

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -35,17 +35,18 @@
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-key.h"
#include "eek-keysym.h"
#include "eek-section.h"
#include "eek-keyboard.h"
#include "eek-symbol.h"
#include "eek-serializable.h"
enum {
PROP_0,
PROP_KEYCODE,
PROP_KEYSYMS,
PROP_SYMBOL_MATRIX,
PROP_COLUMN,
PROP_ROW,
PROP_OUTLINE,
PROP_GROUP,
PROP_LEVEL,
PROP_OREF,
PROP_LAST
};
@ -57,7 +58,11 @@ enum {
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (EekKey, eek_key, EEK_TYPE_ELEMENT);
static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_TYPE_WITH_CODE (EekKey, eek_key, EEK_TYPE_ELEMENT,
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init));
#define EEK_KEY_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_KEY, EekKeyPrivate))
@ -66,14 +71,110 @@ G_DEFINE_TYPE (EekKey, eek_key, EEK_TYPE_ELEMENT);
struct _EekKeyPrivate
{
guint keycode;
EekKeysymMatrix keysyms;
EekSymbolMatrix *symbol_matrix;
gint column;
gint row;
EekOutline *outline;
gint group;
gint level;
gulong oref;
gboolean is_pressed;
};
static EekSerializableIface *eek_key_parent_serializable_iface;
static GVariant *
_g_variant_new_symbol_matrix (EekSymbolMatrix *symbol_matrix)
{
GVariantBuilder builder, array;
gint i, num_symbols = symbol_matrix->num_groups * symbol_matrix->num_levels;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("(iiv)"));
g_variant_builder_add (&builder, "i", symbol_matrix->num_groups);
g_variant_builder_add (&builder, "i", symbol_matrix->num_levels);
g_variant_builder_init (&array, G_VARIANT_TYPE ("av"));
for (i = 0; i < num_symbols; i++) {
GVariant *symbol = eek_serializable_serialize
(EEK_SERIALIZABLE(symbol_matrix->data[i]));
g_variant_builder_add (&array, "v", symbol);
}
g_variant_builder_add (&builder, "v", g_variant_builder_end (&array));
return g_variant_builder_end (&builder);
}
static EekSymbolMatrix *
_g_variant_get_symbol_matrix (GVariant *variant)
{
gint num_groups, num_levels, i;
EekSymbolMatrix *symbol_matrix;
GVariant *array, *child;
GVariantIter iter;
g_variant_get_child (variant, 0, "i", &num_groups);
g_variant_get_child (variant, 1, "i", &num_levels);
symbol_matrix = eek_symbol_matrix_new (num_groups, num_levels);
g_variant_get_child (variant, 2, "v", &array);
g_variant_iter_init (&iter, array);
for (i = 0; i < num_groups * num_levels; i++) {
EekSerializable *serializable;
if (!g_variant_iter_next (&iter, "v", &child)) {
eek_symbol_matrix_free (symbol_matrix);
g_return_val_if_reached (NULL);
}
serializable = eek_serializable_deserialize (child);
symbol_matrix->data[i] = EEK_SYMBOL(serializable);
}
return symbol_matrix;
}
static void
eek_key_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self);
eek_key_parent_serializable_iface->serialize (self, builder);
g_variant_builder_add (builder, "u", priv->keycode);
g_variant_builder_add (builder, "v",
_g_variant_new_symbol_matrix (priv->symbol_matrix));
g_variant_builder_add (builder, "i", priv->column);
g_variant_builder_add (builder, "i", priv->row);
g_variant_builder_add (builder, "u", priv->oref);
}
static gsize
eek_key_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self);
GVariant *symbol_matrix;
index = eek_key_parent_serializable_iface->deserialize (self,
variant,
index);
g_variant_get_child (variant, index++, "u", &priv->keycode);
g_variant_get_child (variant, index++, "v", &symbol_matrix);
priv->symbol_matrix = _g_variant_get_symbol_matrix (symbol_matrix);
g_variant_get_child (variant, index++, "i", &priv->column);
g_variant_get_child (variant, index++, "i", &priv->row);
g_variant_get_child (variant, index++, "u", &priv->oref);
return index;
}
static void
eek_serializable_iface_init (EekSerializableIface *iface)
{
eek_key_parent_serializable_iface =
g_type_interface_peek_parent (iface);
iface->serialize = eek_key_real_serialize;
iface->deserialize = eek_key_real_deserialize;
}
static void
eek_key_real_set_keycode (EekKey *self, guint keycode)
{
@ -89,66 +190,19 @@ eek_key_real_get_keycode (EekKey *self)
}
static void
eek_key_real_set_keysyms (EekKey *self,
guint *keysyms,
gint num_groups,
gint num_levels)
eek_key_real_set_symbol_matrix (EekKey *self,
EekSymbolMatrix *matrix)
{
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self);
gint num_keysyms = num_groups * num_levels;
if (num_keysyms > 0) {
priv->keysyms.data =
g_slice_alloc (num_keysyms * sizeof(guint));
memcpy (priv->keysyms.data, keysyms,
num_keysyms * sizeof(guint));
}
priv->keysyms.num_groups = num_groups;
priv->keysyms.num_levels = num_levels;
#if DEBUG
{
const gchar *name;
gint i;
name = eek_element_get_name (EEK_ELEMENT(self));
fprintf (stderr, "%s: ", name);
for (i = 0; i < priv->keysyms.num_groups * priv->keysyms.num_levels; i++)
fprintf (stderr, "\"%s\" ", eek_keysym_to_string (priv->keysyms.data[i]));
fprintf (stderr, "\n");
}
#endif
eek_symbol_matrix_free (priv->symbol_matrix);
priv->symbol_matrix = eek_symbol_matrix_copy (matrix);
}
static void
eek_key_real_get_keysyms (EekKey *self,
guint **keysyms,
gint *num_groups,
gint *num_levels)
static EekSymbolMatrix *
eek_key_real_get_symbol_matrix (EekKey *self)
{
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self);
gint num_keysyms = priv->keysyms.num_groups * priv->keysyms.num_levels;
if (num_groups)
*num_groups = priv->keysyms.num_groups;
if (num_levels)
*num_levels = priv->keysyms.num_levels;
if (keysyms && num_keysyms > 0) {
*keysyms = g_slice_alloc (num_keysyms * sizeof(guint));
memcpy (*keysyms, priv->keysyms.data, num_keysyms * sizeof(guint));
}
}
static guint
eek_key_real_get_keysym (EekKey *self)
{
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self);
gint num_keysyms = priv->keysyms.num_groups * priv->keysyms.num_levels;
if (num_keysyms == 0)
return EEK_INVALID_KEYSYM;
return priv->keysyms.data[priv->group * priv->keysyms.num_levels +
priv->level];
return priv->symbol_matrix;
}
static void
@ -178,70 +232,53 @@ eek_key_real_get_index (EekKey *self,
}
static void
eek_key_real_set_outline (EekKey *self, EekOutline *outline)
eek_key_real_set_oref (EekKey *self, gulong oref)
{
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self);
priv->outline = outline;
priv->oref = oref;
}
static EekOutline *
eek_key_real_get_outline (EekKey *self)
static gulong
eek_key_real_get_oref (EekKey *self)
{
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self);
return priv->outline;
return priv->oref;
}
static gboolean
eek_key_real_is_pressed (EekKey *self)
{
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self);
return priv->is_pressed;
}
static void
eek_key_real_set_keysym_index (EekKey *self,
gint group,
gint level)
eek_key_real_pressed (EekKey *self)
{
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self);
g_return_if_fail (0 <= group);
if (group >= priv->keysyms.num_groups)
group = 0;
g_return_if_fail (0 <= level);
if (level >= priv->keysyms.num_levels)
level = 0;
priv->group = group;
priv->level = level;
priv->is_pressed = TRUE;
#if DEBUG
g_debug ("pressed %X", eek_key_get_keycode (self));
#endif
}
static void
eek_key_real_get_keysym_index (EekKey *self,
gint *group,
gint *level)
eek_key_real_released (EekKey *self)
{
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self);
g_return_if_fail (group);
g_return_if_fail (level);
if (group)
*group = priv->group;
if (level)
*level = priv->level;
}
static void
eek_key_real_pressed (EekKey *key)
{
g_debug ("pressed %X", eek_key_get_keycode (key));
}
static void
eek_key_real_released (EekKey *key)
{
g_debug ("released %X", eek_key_get_keycode (key));
priv->is_pressed = FALSE;
#if DEBUG
g_debug ("released %X", eek_key_get_keycode (self));
#endif
}
static void
eek_key_finalize (GObject *object)
{
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(object);
gint num_keysyms = priv->keysyms.num_groups * priv->keysyms.num_levels;
g_slice_free1 (num_keysyms * sizeof (guint), priv->keysyms.data);
eek_symbol_matrix_free (priv->symbol_matrix);
G_OBJECT_CLASS (eek_key_parent_class)->finalize (object);
}
@ -251,21 +288,16 @@ eek_key_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec)
{
EekKeysymMatrix *matrix;
EekSymbolMatrix *matrix;
gint column, row;
gint group, level;
g_return_if_fail (EEK_IS_KEY(object));
switch (prop_id) {
case PROP_KEYCODE:
eek_key_set_keycode (EEK_KEY(object), g_value_get_uint (value));
break;
case PROP_KEYSYMS:
case PROP_SYMBOL_MATRIX:
matrix = g_value_get_boxed (value);
eek_key_set_keysyms (EEK_KEY(object),
matrix->data,
matrix->num_groups,
matrix->num_levels);
eek_key_set_symbol_matrix (EEK_KEY(object), matrix);
break;
case PROP_COLUMN:
eek_key_get_index (EEK_KEY(object), &column, &row);
@ -275,18 +307,8 @@ eek_key_set_property (GObject *object,
eek_key_get_index (EEK_KEY(object), &column, &row);
eek_key_set_index (EEK_KEY(object), column, g_value_get_int (value));
break;
case PROP_OUTLINE:
eek_key_set_outline (EEK_KEY(object), g_value_get_pointer (value));
break;
case PROP_GROUP:
eek_key_get_keysym_index (EEK_KEY(object), &group, &level);
eek_key_set_keysym_index (EEK_KEY(object), g_value_get_int (value),
level);
break;
case PROP_LEVEL:
eek_key_get_keysym_index (EEK_KEY(object), &group, &level);
eek_key_set_keysym_index (EEK_KEY(object), group,
g_value_get_int (value));
case PROP_OREF:
eek_key_set_oref (EEK_KEY(object), g_value_get_uint (value));
break;
default:
g_object_set_property (object,
@ -302,19 +324,16 @@ eek_key_get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
EekKeysymMatrix matrix;
gint column, row;
gint group, level;
g_return_if_fail (EEK_IS_KEY(object));
switch (prop_id) {
case PROP_KEYCODE:
g_value_set_uint (value, eek_key_get_keycode (EEK_KEY(object)));
break;
case PROP_KEYSYMS:
eek_key_get_keysyms (EEK_KEY(object), &matrix.data, &matrix.num_groups,
&matrix.num_levels);
g_value_set_boxed (value, &matrix);
case PROP_SYMBOL_MATRIX:
g_value_set_boxed (value,
eek_key_get_symbol_matrix (EEK_KEY(object)));
break;
case PROP_COLUMN:
eek_key_get_index (EEK_KEY(object), &column, &row);
@ -324,16 +343,8 @@ eek_key_get_property (GObject *object,
eek_key_get_index (EEK_KEY(object), &column, &row);
g_value_set_int (value, row);
break;
case PROP_OUTLINE:
g_value_set_pointer (value, eek_key_get_outline (EEK_KEY(object)));
break;
case PROP_GROUP:
eek_key_get_keysym_index (EEK_KEY(object), &group, &level);
g_value_set_int (value, group);
break;
case PROP_LEVEL:
eek_key_get_keysym_index (EEK_KEY(object), &group, &level);
g_value_set_int (value, level);
case PROP_OREF:
g_value_set_uint (value, eek_key_get_oref (EEK_KEY(object)));
break;
default:
g_object_get_property (object,
@ -354,15 +365,13 @@ eek_key_class_init (EekKeyClass *klass)
klass->get_keycode = eek_key_real_get_keycode;
klass->set_keycode = eek_key_real_set_keycode;
klass->set_keysyms = eek_key_real_set_keysyms;
klass->get_keysyms = eek_key_real_get_keysyms;
klass->get_keysym = eek_key_real_get_keysym;
klass->set_symbol_matrix = eek_key_real_set_symbol_matrix;
klass->get_symbol_matrix = eek_key_real_get_symbol_matrix;
klass->set_index = eek_key_real_set_index;
klass->get_index = eek_key_real_get_index;
klass->set_outline = eek_key_real_set_outline;
klass->get_outline = eek_key_real_get_outline;
klass->set_keysym_index = eek_key_real_set_keysym_index;
klass->get_keysym_index = eek_key_real_get_keysym_index;
klass->set_oref = eek_key_real_set_oref;
klass->get_oref = eek_key_real_get_oref;
klass->is_pressed = eek_key_real_is_pressed;
gobject_class->set_property = eek_key_set_property;
gobject_class->get_property = eek_key_get_property;
@ -385,16 +394,16 @@ eek_key_class_init (EekKeyClass *klass)
g_object_class_install_property (gobject_class, PROP_KEYCODE, pspec);
/**
* EekKey:keysyms:
* EekKey:symbol-matrix:
*
* The symbol matrix of #EekKey.
*/
pspec = g_param_spec_boxed ("keysyms",
"Keysyms",
pspec = g_param_spec_boxed ("symbol-matrix",
"Symbol matrix",
"Symbol matrix of the key",
EEK_TYPE_KEYSYM_MATRIX,
EEK_TYPE_SYMBOL_MATRIX,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_KEYSYMS, pspec);
g_object_class_install_property (gobject_class, PROP_SYMBOL_MATRIX, pspec);
/**
* EekKey:column:
@ -421,42 +430,16 @@ eek_key_class_init (EekKeyClass *klass)
g_object_class_install_property (gobject_class, PROP_ROW, pspec);
/**
* EekKey:outline:
* EekKey:oref:
*
* The pointer to the outline shape of #EekKey.
* The outline id of #EekKey.
*/
/* Use pointer instead of boxed to avoid copy, since we can
assume that only a few outline shapes are used in a whole
keyboard (unlike keysyms and bounds). */
pspec = g_param_spec_pointer ("outline",
"Outline",
"Pointer to outline shape of the key",
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_OUTLINE, pspec);
/**
* EekKey:group:
*
* The column index of #EekKey in the symbol matrix #EekKey:keysyms.
*/
pspec = g_param_spec_int ("group",
"Group",
"Current group of the key",
0, 64, 0,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_GROUP, pspec);
/**
* EekKey:level:
*
* The row index of #EekKey in the symbol matrix #EekKey:keysyms.
*/
pspec = g_param_spec_int ("level",
"Level",
"Current level of the key",
0, 3, 0,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_LEVEL, pspec);
pspec = g_param_spec_ulong ("oref",
"Oref",
"Outline id of the key",
0, G_MAXULONG, 0,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_OREF, pspec);
/**
* EekKey::pressed:
@ -466,7 +449,7 @@ eek_key_class_init (EekKeyClass *klass)
* the pressed state.
*/
signals[PRESSED] =
g_signal_new ("pressed",
g_signal_new (I_("pressed"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(EekKeyClass, pressed),
@ -483,7 +466,7 @@ eek_key_class_init (EekKeyClass *klass)
* the released state.
*/
signals[RELEASED] =
g_signal_new ("released",
g_signal_new (I_("released"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(EekKeyClass, released),
@ -500,10 +483,9 @@ eek_key_init (EekKey *self)
priv = self->priv = EEK_KEY_GET_PRIVATE(self);
priv->keycode = 0;
memset (&priv->keysyms, 0, sizeof priv->keysyms);
priv->symbol_matrix = eek_symbol_matrix_new (0, 0);
priv->column = priv->row = 0;
priv->outline = NULL;
priv->group = priv->level = 0;
priv->oref = 0;
}
/**
@ -511,7 +493,11 @@ eek_key_init (EekKey *self)
* @key: an #EekKey
* @keycode: keycode
*
* Set keycode of @key to @keycode.
* Set the keycode of @key to @keycode. Since typically the keycode
* value is used to find a key in a keyboard by calling
* eek_keyboard_find_key_by_keycode, it is not necessarily the same as
* the X keycode but it should be unique in the keyboard @key belongs
* to.
*/
void
eek_key_set_keycode (EekKey *key,
@ -536,59 +522,137 @@ eek_key_get_keycode (EekKey *key)
}
/**
* eek_key_set_keysyms:
* eek_key_set_symbol_matrix:
* @key: an #EekKey
* @keysyms: symbol matrix of @key
* @num_groups: number of groups (rows) of @keysyms
* @num_levels: number of levels (columns) of @keysyms
* @matrix: an #EekSymbolMatrix
*
* Set the symbol matrix of @key to @keysyms. The length of @keysyms
* is @num_groups * @num_levels.
* Set the symbol matrix of @key to @matrix.
*/
void
eek_key_set_keysyms (EekKey *key,
guint *keysyms,
gint num_groups,
gint num_levels)
eek_key_set_symbol_matrix (EekKey *key,
EekSymbolMatrix *matrix)
{
g_return_if_fail (EEK_IS_KEY(key));
EEK_KEY_GET_CLASS(key)->set_keysyms (key, keysyms, num_groups, num_levels);
EEK_KEY_GET_CLASS(key)->set_symbol_matrix (key, matrix);
}
/**
* eek_key_get_keysyms:
* eek_key_get_symbol_matrix:
* @key: an #EekKey
* @keysyms: pointer where symbol matrix of @key will be stored
* @num_groups: pointer where the number of groups (rows) of @keysyms
* will be stored
* @num_levels: pointer where the number of levels (columns) of
* @keysyms will be stored
*
* Get the symbol matrix of @key. If either @keysyms, @num_groups, or
* @num_levels are NULL, this function does not try to get the value.
* Get the symbol matrix of @key.
* Returns: #EekSymbolMatrix or %NULL
*/
void
eek_key_get_keysyms (EekKey *key,
guint **keysyms,
gint *num_groups,
gint *num_levels)
EekSymbolMatrix *
eek_key_get_symbol_matrix (EekKey *key)
{
g_return_if_fail (EEK_IS_KEY(key));
EEK_KEY_GET_CLASS(key)->get_keysyms (key, keysyms, num_groups, num_levels);
g_return_val_if_fail (EEK_IS_KEY(key), NULL);
return EEK_KEY_GET_CLASS(key)->get_symbol_matrix (key);
}
static EekKeyboard *
get_keyboard (EekKey *key)
{
EekElement *parent;
parent = eek_element_get_parent (EEK_ELEMENT(key));
g_return_val_if_fail (EEK_IS_SECTION(parent), NULL);
parent = eek_element_get_parent (parent);
g_return_val_if_fail (EEK_IS_KEYBOARD(parent), NULL);
return EEK_KEYBOARD(parent);
}
/**
* eek_key_get_keysym:
* eek_key_get_symbol:
* @key: an #EekKey
* @returns: (transfer none): the current #EekSymbol or %NULL on failure
*
* Get the current symbol of @key.
* Returns: a symbol or %EEK_INVALID_KEYSYM on failure
*/
guint
eek_key_get_keysym (EekKey *key)
EekSymbol *
eek_key_get_symbol (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY(key), EEK_INVALID_KEYSYM);
return EEK_KEY_GET_CLASS(key)->get_keysym (key);
return eek_key_get_symbol_with_fallback (key, 0, 0);
}
/**
* eek_key_get_symbol_with_fallback:
* @key: an #EekKey
* @fallback_group: fallback group index
* @fallback_level: fallback level index
* @returns: (transfer none): the current #EekSymbol or %NULL on failure
*
* Get the current symbol of @key.
*/
EekSymbol *
eek_key_get_symbol_with_fallback (EekKey *key,
gint fallback_group,
gint fallback_level)
{
gint group, level;
EekKeyboard *keyboard;
g_return_val_if_fail (EEK_IS_KEY (key), NULL);
keyboard = get_keyboard (key);
g_return_val_if_fail (keyboard, NULL);
eek_keyboard_get_symbol_index (keyboard, &group, &level);
return eek_key_get_symbol_at_index (key,
group,
level,
fallback_group,
fallback_level);
}
/**
* eek_key_get_symbol_at_index:
* @key: an #EekKey
* @group: group index of the symbol matrix
* @level: level index of the symbol matrix
* @fallback_group: fallback group index
* @fallback_level: fallback level index
* @returns: (transfer none): an #EekSymbol at (@group, @level), or %NULL
*
* Get the symbol at (@group, @level) in the symbol matrix of @key.
*/
EekSymbol *
eek_key_get_symbol_at_index (EekKey *key,
gint group,
gint level,
gint fallback_group,
gint fallback_level)
{
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(key);
gint num_symbols;
g_return_val_if_fail (group >= 0, NULL);
g_return_val_if_fail (level >= 0, NULL);
if (!priv->symbol_matrix)
return NULL;
num_symbols = priv->symbol_matrix->num_groups *
priv->symbol_matrix->num_levels;
if (num_symbols == 0)
return NULL;
if (group >= priv->symbol_matrix->num_groups) {
if (fallback_group < 0)
return NULL;
group = fallback_group;
}
if (level >= priv->symbol_matrix->num_levels) {
if (fallback_level < 0)
return NULL;
level = fallback_level;
}
return priv->symbol_matrix->data[group * priv->symbol_matrix->num_levels +
level];
}
/**
@ -597,8 +661,7 @@ eek_key_get_keysym (EekKey *key)
* @column: column index of @key in #EekSection
* @row: row index of @key in #EekSection
*
* Set the index of @key (i.e. logical location of @key in
* #EekSection) to @column and @row.
* Set the location of @key in #EekSection with @column and @row.
*/
void
eek_key_set_index (EekKey *key,
@ -615,8 +678,7 @@ eek_key_set_index (EekKey *key,
* @column: pointer where the column index of @key in #EekSection will be stored
* @row: pointer where the row index of @key in #EekSection will be stored
*
* Get the index of @key (i.e. logical location of @key in
* #EekSection).
* Get the location of @key in #EekSection.
*/
void
eek_key_get_index (EekKey *key,
@ -628,66 +690,43 @@ eek_key_get_index (EekKey *key,
}
/**
* eek_key_set_outline:
* eek_key_set_oref:
* @key: an #EekKey
* @outline: outline of @key
* @oref: outline id of @key
*
* Set the outline shape of @key to @outline.
* Set the outline id of @key to @oref.
*/
void
eek_key_set_outline (EekKey *key,
EekOutline *outline)
eek_key_set_oref (EekKey *key,
gulong oref)
{
g_return_if_fail (EEK_IS_KEY(key));
EEK_KEY_GET_CLASS(key)->set_outline (key, outline);
EEK_KEY_GET_CLASS(key)->set_oref (key, oref);
}
/**
* eek_key_get_outline:
* eek_key_get_oref:
* @key: an #EekKey
*
* Get the outline shape of @key.
* Returns: an #EekOutline pointer or NULL on failure
* Get the outline id of @key.
* Returns: a non-zero unsigned integer on success, 0 if the id is not set
*/
EekOutline *
eek_key_get_outline (EekKey *key)
gulong
eek_key_get_oref (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY (key), NULL);
return EEK_KEY_GET_CLASS(key)->get_outline (key);
g_return_val_if_fail (EEK_IS_KEY (key), 0);
return EEK_KEY_GET_CLASS(key)->get_oref (key);
}
/**
* eek_key_set_keysym_index:
* eek_key_is_pressed:
* @key: an #EekKey
* @group: group (row) index of @key
* @level: level (column) index of @key
*
* Set the current group and/or level index of @key in its symbol
* matrix to @group and @level.
* Return %TRUE if key is marked as pressed.
*/
void
eek_key_set_keysym_index (EekKey *key,
gint group,
gint level)
gboolean
eek_key_is_pressed (EekKey *key)
{
g_return_if_fail (EEK_IS_KEY(key));
EEK_KEY_GET_CLASS(key)->set_keysym_index (key, group, level);
}
/**
* eek_key_get_keysym_index:
* @key: an #EekKey
* @group: pointer where group (row) index of @key will be stored
* @level: pointer where level (column) index of @key will be stored
*
* Get the current group and/or level index of @key in its symbol
* matrix.
*/
void
eek_key_get_keysym_index (EekKey *key,
gint *group,
gint *level)
{
g_return_if_fail (EEK_IS_KEY(key));
EEK_KEY_GET_CLASS(key)->get_keysym_index (key, group, level);
g_assert (EEK_IS_KEY(key));
return EEK_KEY_GET_CLASS(key)->is_pressed (key);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -48,19 +48,17 @@ struct _EekKey
* EekKeyClass:
* @set_keycode: virtual function for setting keycode of the key
* @get_keycode: virtual function for getting keycode of the key
* @set_keysyms: virtual function for setting symbol matrix of the key
* @get_keysyms: virtual function for getting symbol matrix of the key
* @get_keysym: virtual function for getting the current symbol of the key
* @set_symbol_matrix: virtual function for setting symbol matrix of the key
* @get_symbol_matrix: virtual function for getting symbol matrix of the key
* @set_index: virtual function for setting position of the key in the
* section
* @get_index: virtual function for getting position of the key in the
* section
* @set_outline: virtual function for setting outline shape of the key
* @get_outline: virtual function for getting outline shape of the key
* @set_keysym_index: virtual function for setting group and level of the key
* @get_keysym_index: virtual function for getting group and level of the key
* @set_oref: virtual function for setting outline id of the key
* @get_oref: virtual function for getting outline id of the key
* @pressed: class handler for #EekKey::pressed signal
* @released: class handler for #EekKey::released signal
* @is_pressed: virtual function for getting whether the key is pressed
*/
struct _EekKeyClass
{
@ -68,74 +66,66 @@ struct _EekKeyClass
EekElementClass parent_class;
/*< public >*/
void (* set_keycode) (EekKey *self,
guint keycode);
guint (* get_keycode) (EekKey *self);
void (* set_keysyms) (EekKey *self,
guint *keysyms,
gint num_groups,
gint num_levels);
void (* get_keysyms) (EekKey *self,
guint **keysyms,
gint *num_groups,
gint *num_levels);
guint (* get_keysym) (EekKey *self);
void (* set_keycode) (EekKey *self,
guint keycode);
guint (* get_keycode) (EekKey *self);
void (* set_symbol_matrix) (EekKey *self,
EekSymbolMatrix *matrix);
EekSymbolMatrix *(* get_symbol_matrix) (EekKey *self);
void (* set_index) (EekKey *self,
gint column,
gint row);
void (* get_index) (EekKey *self,
gint *column,
gint *row);
void (* set_index) (EekKey *self,
gint column,
gint row);
void (* get_index) (EekKey *self,
gint *column,
gint *row);
void (* set_outline) (EekKey *self,
EekOutline *outline);
EekOutline *(* get_outline) (EekKey *self);
void (* set_oref) (EekKey *self,
gulong oref);
gulong (* get_oref) (EekKey *self);
void (* set_keysym_index) (EekKey *self,
gint group,
gint level);
void (* get_keysym_index) (EekKey *self,
gint *group,
gint *level);
gboolean (* is_pressed) (EekKey *self);
/* signals */
void (* pressed) (EekKey *key);
void (* released) (EekKey *key);
void (* pressed) (EekKey *key);
void (* released) (EekKey *key);
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_key_get_type (void) G_GNUC_CONST;
GType eek_key_get_type (void) G_GNUC_CONST;
void eek_key_set_keycode (EekKey *key,
guint keycode);
guint eek_key_get_keycode (EekKey *key);
void eek_key_set_keysyms (EekKey *key,
guint *keysyms,
gint num_groups,
gint num_levels);
void eek_key_get_keysyms (EekKey *key,
guint **keysyms,
gint *num_groups,
gint *num_levels);
guint eek_key_get_keysym (EekKey *key);
void eek_key_set_keycode (EekKey *key,
guint keycode);
guint eek_key_get_keycode (EekKey *key);
void eek_key_set_symbol_matrix (EekKey *key,
EekSymbolMatrix *matrix);
EekSymbolMatrix *eek_key_get_symbol_matrix (EekKey *key);
EekSymbol *eek_key_get_symbol (EekKey *key);
EekSymbol *eek_key_get_symbol_with_fallback
(EekKey *key,
gint fallback_group,
gint fallback_level);
EekSymbol *eek_key_get_symbol_at_index (EekKey *key,
gint group,
gint level,
gint fallback_group,
gint fallback_level);
void eek_key_set_index (EekKey *key,
gint column,
gint row);
void eek_key_get_index (EekKey *key,
gint *column,
gint *row);
void eek_key_set_index (EekKey *key,
gint column,
gint row);
void eek_key_get_index (EekKey *key,
gint *column,
gint *row);
void eek_key_set_outline (EekKey *key,
EekOutline *outline);
EekOutline *eek_key_get_outline (EekKey *key);
void eek_key_set_oref (EekKey *key,
gulong oref);
gulong eek_key_get_oref (EekKey *key);
void eek_key_set_keysym_index (EekKey *key,
gint group,
gint level);
void eek_key_get_keysym_index (EekKey *key,
gint *group,
gint *level);
gboolean eek_key_is_pressed (EekKey *key);
G_END_DECLS
#endif /* EEK_KEY_H */

230
eek/eek-keyboard-drawing.c Normal file
View File

@ -0,0 +1,230 @@
/*
* Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
*
* 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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <math.h>
#include <pango/pangocairo.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-types.h"
static gdouble
length (gdouble x, gdouble y)
{
return sqrt (x * x + y * y);
}
static gdouble
point_line_distance (gdouble ax, gdouble ay, gdouble nx, gdouble ny)
{
return ax * nx + ay * ny;
}
static void
normal_form (gdouble ax, gdouble ay,
gdouble bx, gdouble by,
gdouble * nx, gdouble * ny, gdouble * d)
{
gdouble l;
*nx = by - ay;
*ny = ax - bx;
l = length (*nx, *ny);
*nx /= l;
*ny /= l;
*d = point_line_distance (ax, ay, *nx, *ny);
}
static void
inverse (gdouble a, gdouble b, gdouble c, gdouble d,
gdouble * e, gdouble * f, gdouble * g, gdouble * h)
{
gdouble det;
det = a * d - b * c;
*e = d / det;
*f = -b / det;
*g = -c / det;
*h = a / det;
}
static void
multiply (gdouble a, gdouble b, gdouble c, gdouble d,
gdouble e, gdouble f, gdouble * x, gdouble * y)
{
*x = a * e + b * f;
*y = c * e + d * f;
}
static void
intersect (gdouble n1x, gdouble n1y, gdouble d1,
gdouble n2x, gdouble n2y, gdouble d2, gdouble * x, gdouble * y)
{
gdouble e, f, g, h;
inverse (n1x, n1y, n2x, n2y, &e, &f, &g, &h);
multiply (e, f, g, h, d1, d2, x, y);
}
/* draw an angle from the current point to b and then to c,
* with a rounded corner of the given radius.
*/
static void
rounded_corner (cairo_t * cr,
gdouble bx, gdouble by,
gdouble cx, gdouble cy, gdouble radius)
{
gdouble ax, ay;
gdouble n1x, n1y, d1;
gdouble n2x, n2y, d2;
gdouble pd1, pd2;
gdouble ix, iy;
gdouble dist1, dist2;
gdouble nx, ny, d;
gdouble a1x, a1y, c1x, c1y;
gdouble phi1, phi2;
cairo_get_current_point (cr, &ax, &ay);
#ifdef KBDRAW_DEBUG
printf (" current point: (%f, %f), radius %f:\n", ax, ay,
radius);
#endif
/* make sure radius is not too large */
dist1 = length (bx - ax, by - ay);
dist2 = length (cx - bx, cy - by);
radius = MIN (radius, MIN (dist1, dist2));
/* construct normal forms of the lines */
normal_form (ax, ay, bx, by, &n1x, &n1y, &d1);
normal_form (bx, by, cx, cy, &n2x, &n2y, &d2);
/* find which side of the line a,b the point c is on */
if (point_line_distance (cx, cy, n1x, n1y) < d1)
pd1 = d1 - radius;
else
pd1 = d1 + radius;
/* find which side of the line b,c the point a is on */
if (point_line_distance (ax, ay, n2x, n2y) < d2)
pd2 = d2 - radius;
else
pd2 = d2 + radius;
/* intersect the parallels to find the center of the arc */
intersect (n1x, n1y, pd1, n2x, n2y, pd2, &ix, &iy);
nx = (bx - ax) / dist1;
ny = (by - ay) / dist1;
d = point_line_distance (ix, iy, nx, ny);
/* a1 is the point on the line a-b where the arc starts */
intersect (n1x, n1y, d1, nx, ny, d, &a1x, &a1y);
nx = (cx - bx) / dist2;
ny = (cy - by) / dist2;
d = point_line_distance (ix, iy, nx, ny);
/* c1 is the point on the line b-c where the arc ends */
intersect (n2x, n2y, d2, nx, ny, d, &c1x, &c1y);
/* determine the first angle */
if (a1x - ix == 0)
phi1 = (a1y - iy > 0) ? M_PI_2 : 3 * M_PI_2;
else if (a1x - ix > 0)
phi1 = atan ((a1y - iy) / (a1x - ix));
else
phi1 = M_PI + atan ((a1y - iy) / (a1x - ix));
/* determine the second angle */
if (c1x - ix == 0)
phi2 = (c1y - iy > 0) ? M_PI_2 : 3 * M_PI_2;
else if (c1x - ix > 0)
phi2 = atan ((c1y - iy) / (c1x - ix));
else
phi2 = M_PI + atan ((c1y - iy) / (c1x - ix));
/* compute the difference between phi2 and phi1 mod 2pi */
d = phi2 - phi1;
while (d < 0)
d += 2 * M_PI;
while (d > 2 * M_PI)
d -= 2 * M_PI;
#ifdef KBDRAW_DEBUG
printf (" line 1 to: (%f, %f):\n", a1x, a1y);
#endif
if (!(isnan (a1x) || isnan (a1y)))
cairo_line_to (cr, a1x, a1y);
/* pick the short arc from phi1 to phi2 */
if (d < M_PI)
cairo_arc (cr, ix, iy, radius, phi1, phi2);
else
cairo_arc_negative (cr, ix, iy, radius, phi1, phi2);
#ifdef KBDRAW_DEBUG
printf (" line 2 to: (%f, %f):\n", cx, cy);
#endif
cairo_line_to (cr, cx, cy);
}
/* renamed from rounded_polygon, use EekPoint instead of GdkPoint not
to depend on GTK+, and exported */
void
_eek_rounded_polygon (cairo_t *cr,
gdouble radius,
EekPoint *points,
gint num_points)
{
gint i, j;
cairo_move_to (cr,
(gdouble) (points[num_points - 1].x +
points[0].x) / 2,
(gdouble) (points[num_points - 1].y +
points[0].y) / 2);
#ifdef KBDRAW_DEBUG
printf (" rounded polygon of radius %f:\n", radius);
#endif
for (i = 0; i < num_points; i++) {
j = (i + 1) % num_points;
rounded_corner (cr, (gdouble) points[i].x,
(gdouble) points[i].y,
(gdouble) (points[i].x + points[j].x) / 2,
(gdouble) (points[i].y + points[j].y) / 2,
radius);
#ifdef KBDRAW_DEBUG
printf (" corner (%d, %d) -> (%d, %d):\n",
points[i].x, points[i].y, points[j].x,
points[j].y);
#endif
};
cairo_close_path (cr);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -34,23 +34,33 @@
#include "eek-keyboard.h"
#include "eek-section.h"
#include "eek-key.h"
#include "eek-symbol.h"
#include "eek-marshalers.h"
#include "eek-serializable.h"
enum {
PROP_0,
PROP_GROUP,
PROP_LEVEL,
PROP_LAYOUT,
PROP_MODIFIER_BEHAVIOR,
PROP_LAST
};
enum {
KEY_PRESSED,
KEY_RELEASED,
SYMBOL_INDEX_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (EekKeyboard, eek_keyboard, EEK_TYPE_CONTAINER);
static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_TYPE_WITH_CODE (EekKeyboard, eek_keyboard, EEK_TYPE_CONTAINER,
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init));
#define EEK_KEYBOARD_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_KEYBOARD, EekKeyboardPrivate))
@ -61,53 +71,136 @@ struct _EekKeyboardPrivate
gint group;
gint level;
EekLayout *layout;
gboolean is_realized;
EekModifierBehavior modifier_behavior;
EekModifierType modifiers;
GArray *outline_array;
};
struct keysym_index {
gint group;
gint level;
};
static EekSerializableIface *eek_keyboard_parent_serializable_iface;
static void
set_keysym_index_for_key (EekElement *element,
gpointer user_data)
static GVariant *_g_variant_new_outline (EekOutline *outline);
static EekOutline *_g_variant_get_outline (GVariant *variant);
static GVariant *
_g_variant_new_outline (EekOutline *outline)
{
struct keysym_index *ki;
GVariantBuilder builder, array;
gint i;
g_return_if_fail (EEK_IS_KEY(element));
g_variant_builder_init (&builder, G_VARIANT_TYPE ("(div)"));
g_variant_builder_add (&builder, "d", outline->corner_radius);
g_variant_builder_add (&builder, "i", outline->num_points);
g_variant_builder_init (&array, G_VARIANT_TYPE ("a(dd)"));
for (i = 0; i < outline->num_points; i++)
g_variant_builder_add (&array,
"(dd)",
outline->points[i].x,
outline->points[i].y);
g_variant_builder_add (&builder, "v", g_variant_builder_end (&array));
return g_variant_builder_end (&builder);
}
ki = user_data;
eek_key_set_keysym_index (EEK_KEY(element), ki->group, ki->level);
static EekOutline *
_g_variant_get_outline (GVariant *variant)
{
EekOutline *outline;
GVariant *array;
GVariantIter iter;
gdouble x, y;
gint i;
outline = g_slice_new0 (EekOutline);
g_variant_get_child (variant, 0, "d", &outline->corner_radius);
g_variant_get_child (variant, 1, "i", &outline->num_points);
outline->points = g_slice_alloc0 (sizeof (EekPoint) * outline->num_points);
g_variant_get_child (variant, 2, "v", &array);
g_variant_iter_init (&iter, array);
for (i = 0; i < outline->num_points; i++) {
if (!g_variant_iter_next (&iter, "(dd)", &x, &y)) {
eek_outline_free (outline);
g_return_val_if_reached (NULL);
}
outline->points[i].x = x;
outline->points[i].y = y;
}
return outline;
}
static void
set_keysym_index_for_section (EekElement *element,
gpointer user_data)
eek_keyboard_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
eek_container_foreach_child (EEK_CONTAINER(element),
set_keysym_index_for_key,
user_data);
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
GVariantBuilder array;
guint i;
eek_keyboard_parent_serializable_iface->serialize (self, builder);
g_variant_builder_init (&array, G_VARIANT_TYPE ("av"));
for (i = 0; i < priv->outline_array->len; i++) {
EekOutline *outline =
eek_keyboard_get_outline (EEK_KEYBOARD(self), i + 1);
g_variant_builder_add (&array, "v",
_g_variant_new_outline (outline));
}
g_variant_builder_add (builder, "v", g_variant_builder_end (&array));
}
static gsize
eek_keyboard_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
GVariant *array, *outline;
GVariantIter iter;
index = eek_keyboard_parent_serializable_iface->deserialize (self,
variant,
index);
g_variant_get_child (variant, index++, "v", &array);
g_variant_iter_init (&iter, array);
while (g_variant_iter_next (&iter, "v", &outline)) {
EekOutline *_outline = _g_variant_get_outline (outline);
g_array_append_val (priv->outline_array, *_outline);
}
return index;
}
static void
eek_keyboard_real_set_keysym_index (EekKeyboard *self,
eek_serializable_iface_init (EekSerializableIface *iface)
{
eek_keyboard_parent_serializable_iface =
g_type_interface_peek_parent (iface);
iface->serialize = eek_keyboard_real_serialize;
iface->deserialize = eek_keyboard_real_deserialize;
}
static void
eek_keyboard_real_set_symbol_index (EekKeyboard *self,
gint group,
gint level)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
struct keysym_index ki;
ki.group = priv->group = group;
ki.level = priv->level = level;
if (priv->group != group || priv->level != level) {
priv->group = group;
priv->level = level;
eek_container_foreach_child (EEK_CONTAINER(self),
set_keysym_index_for_section,
&ki);
g_signal_emit_by_name (self, "symbol-index-changed", group, level);
}
}
void
eek_keyboard_real_get_keysym_index (EekKeyboard *self,
eek_keyboard_real_get_symbol_index (EekKeyboard *self,
gint *group,
gint *level)
{
@ -121,17 +214,17 @@ eek_keyboard_real_get_keysym_index (EekKeyboard *self,
}
static void
key_pressed_event (EekSection *section,
EekKey *key,
EekKeyboard *keyboard)
on_key_pressed (EekSection *section,
EekKey *key,
EekKeyboard *keyboard)
{
g_signal_emit_by_name (keyboard, "key-pressed", key);
}
static void
key_released_event (EekSection *section,
EekKey *key,
EekKeyboard *keyboard)
on_key_released (EekSection *section,
EekKey *key,
EekKeyboard *keyboard)
{
g_signal_emit_by_name (keyboard, "key-released", key);
}
@ -144,64 +237,21 @@ eek_keyboard_real_create_section (EekKeyboard *self)
section = g_object_new (EEK_TYPE_SECTION, NULL);
g_return_val_if_fail (section, NULL);
g_signal_connect (section, "key-pressed",
G_CALLBACK(key_pressed_event), self);
g_signal_connect (section, "key-released",
G_CALLBACK(key_released_event), self);
EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self),
EEK_ELEMENT(section));
return section;
}
static void
on_group_changed (EekLayout *layout,
gint new_group,
gpointer user_data)
{
EekKeyboard *keyboard = user_data;
gint group, level;
eek_keyboard_get_keysym_index (keyboard, &group, &level);
eek_keyboard_set_keysym_index (keyboard, new_group, level);
}
static void
eek_keyboard_real_set_layout (EekKeyboard *self,
EekLayout *layout)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
g_return_if_fail (EEK_IS_LAYOUT(layout));
priv->layout = layout;
g_object_ref_sink (priv->layout);
g_signal_connect (priv->layout, "group_changed",
G_CALLBACK(on_group_changed), self);
}
static void
eek_keyboard_real_realize (EekKeyboard *self)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
g_return_if_fail (priv->layout);
g_return_if_fail (!priv->is_realized);
EEK_LAYOUT_GET_IFACE(priv->layout)->apply (priv->layout, self);
/* apply the initial group setting */
on_group_changed (priv->layout, eek_layout_get_group (priv->layout), self);
priv->is_realized = TRUE;
}
struct _FkbkData {
struct _FindKeyByKeycodeCallbackData {
EekKey *key;
guint keycode;
};
typedef struct _FkbkData FkbkData;
typedef struct _FindKeyByKeycodeCallbackData FindKeyByKeycodeCallbackData;
static gint
compare_section_by_keycode (EekElement *element, gpointer user_data)
find_key_by_keycode_section_callback (EekElement *element, gpointer user_data)
{
FkbkData *data = user_data;
FindKeyByKeycodeCallbackData *data = user_data;
data->key = eek_section_find_key_by_keycode (EEK_SECTION(element),
data->keycode);
@ -214,49 +264,39 @@ static EekKey *
eek_keyboard_real_find_key_by_keycode (EekKeyboard *self,
guint keycode)
{
FkbkData data;
FindKeyByKeycodeCallbackData data;
data.keycode = keycode;
if (eek_container_find (EEK_CONTAINER(self),
compare_section_by_keycode,
find_key_by_keycode_section_callback,
&data))
return data.key;
return NULL;
}
static void
eek_keyboard_dispose (GObject *object)
eek_keyboard_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
if (priv->layout) {
g_object_unref (priv->layout);
priv->layout = NULL;
}
G_OBJECT_CLASS(eek_keyboard_parent_class)->dispose (object);
}
static void
eek_keyboard_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
gint group, level;
g_return_if_fail (EEK_IS_KEYBOARD(object));
switch (prop_id) {
case PROP_GROUP:
eek_keyboard_get_keysym_index (EEK_KEYBOARD(object), &group, &level);
eek_keyboard_set_keysym_index (EEK_KEYBOARD(object),
g_value_get_int (value),
level);
eek_keyboard_set_group (EEK_KEYBOARD(object), g_value_get_int (value));
break;
case PROP_LEVEL:
eek_keyboard_get_keysym_index (EEK_KEYBOARD(object), &group, &level);
eek_keyboard_set_keysym_index (EEK_KEYBOARD(object),
group,
g_value_get_int (value));
eek_keyboard_set_level (EEK_KEYBOARD(object), g_value_get_int (value));
break;
case PROP_LAYOUT:
priv->layout = g_value_get_object (value);
if (priv->layout)
g_object_ref (priv->layout);
break;
case PROP_MODIFIER_BEHAVIOR:
eek_keyboard_set_modifier_behavior (EEK_KEYBOARD(object),
g_value_get_int (value));
break;
default:
g_object_set_property (object,
@ -272,17 +312,23 @@ eek_keyboard_get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
gint group, level;
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
g_return_if_fail (EEK_IS_KEYBOARD(object));
switch (prop_id) {
case PROP_GROUP:
eek_keyboard_get_keysym_index (EEK_KEYBOARD(object), &group, &level);
g_value_set_int (value, group);
g_value_set_int (value,
eek_keyboard_get_group (EEK_KEYBOARD(object)));
break;
case PROP_LEVEL:
eek_keyboard_get_keysym_index (EEK_KEYBOARD(object), &level, &level);
g_value_set_int (value, level);
g_value_set_int (value,
eek_keyboard_get_level (EEK_KEYBOARD(object)));
break;
case PROP_LAYOUT:
g_value_set_object (value, priv->layout);
break;
case PROP_MODIFIER_BEHAVIOR:
g_value_set_int (value,
eek_keyboard_get_modifier_behavior (EEK_KEYBOARD(object)));
break;
default:
g_object_get_property (object,
@ -292,25 +338,158 @@ eek_keyboard_get_property (GObject *object,
}
}
static void
eek_keyboard_real_symbol_index_changed (EekKeyboard *self,
gint group,
gint level)
{
/* g_debug ("symbol-index-changed"); */
}
static void
set_level_from_modifiers (EekKeyboard *self)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
guint level = 0;
if (priv->modifiers & EEK_MOD5_MASK)
level |= 2;
if (priv->modifiers & EEK_SHIFT_MASK)
level |= 1;
eek_keyboard_set_level (self, level);
}
static void
eek_keyboard_real_key_pressed (EekKeyboard *self,
EekKey *key)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
EekSymbol *symbol;
EekModifierType modifier;
symbol = eek_key_get_symbol_at_index (key,
priv->group,
priv->level,
0,
0);
if (!symbol)
return;
modifier = eek_symbol_get_modifier_mask (symbol);
switch (priv->modifier_behavior) {
case EEK_MODIFIER_BEHAVIOR_NONE:
priv->modifiers |= modifier;
break;
case EEK_MODIFIER_BEHAVIOR_LOCK:
priv->modifiers ^= modifier;
break;
case EEK_MODIFIER_BEHAVIOR_LATCH:
priv->modifiers = (priv->modifiers ^ modifier) & modifier;
break;
}
set_level_from_modifiers (self);
}
static void
eek_keyboard_real_key_released (EekKeyboard *self,
EekKey *key)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
EekSymbol *symbol;
EekModifierType modifier;
symbol = eek_key_get_symbol_at_index (key,
priv->group,
priv->level,
0,
0);
if (!symbol)
return;
modifier = eek_symbol_get_modifier_mask (symbol);
if (modifier != 0) {
if (priv->modifier_behavior == EEK_MODIFIER_BEHAVIOR_NONE)
priv->modifiers &= ~modifier;
}
set_level_from_modifiers (self);
}
static void
eek_keyboard_dispose (GObject *object)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
if (priv->layout) {
g_object_unref (priv->layout);
priv->layout = NULL;
}
G_OBJECT_CLASS (eek_keyboard_parent_class)->dispose (object);
}
static void
eek_keyboard_finalize (GObject *object)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
gint i;
for (i = 0; i < priv->outline_array->len; i++) {
EekOutline *outline = &g_array_index (priv->outline_array,
EekOutline,
i);
g_slice_free1 (sizeof (EekPoint) * outline->num_points,
outline->points);
}
g_array_free (priv->outline_array, TRUE);
G_OBJECT_CLASS (eek_keyboard_parent_class)->finalize (object);
}
static void
eek_keyboard_real_child_added (EekContainer *self,
EekElement *element)
{
g_signal_connect (element, "key-pressed",
G_CALLBACK(on_key_pressed), self);
g_signal_connect (element, "key-released",
G_CALLBACK(on_key_released), self);
}
static void
eek_keyboard_real_child_removed (EekContainer *self,
EekElement *element)
{
g_signal_handlers_disconnect_by_func (element, on_key_pressed, self);
g_signal_handlers_disconnect_by_func (element, on_key_released, self);
}
static void
eek_keyboard_class_init (EekKeyboardClass *klass)
{
EekContainerClass *container_class = EEK_CONTAINER_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class,
sizeof (EekKeyboardPrivate));
klass->set_keysym_index = eek_keyboard_real_set_keysym_index;
klass->get_keysym_index = eek_keyboard_real_get_keysym_index;
klass->set_symbol_index = eek_keyboard_real_set_symbol_index;
klass->get_symbol_index = eek_keyboard_real_get_symbol_index;
klass->create_section = eek_keyboard_real_create_section;
klass->set_layout = eek_keyboard_real_set_layout;
klass->realize = eek_keyboard_real_realize;
klass->find_key_by_keycode = eek_keyboard_real_find_key_by_keycode;
/* signals */
klass->key_pressed = eek_keyboard_real_key_pressed;
klass->key_released = eek_keyboard_real_key_released;
klass->symbol_index_changed = eek_keyboard_real_symbol_index_changed;
container_class->child_added = eek_keyboard_real_child_added;
container_class->child_removed = eek_keyboard_real_child_removed;
gobject_class->get_property = eek_keyboard_get_property;
gobject_class->set_property = eek_keyboard_set_property;
gobject_class->dispose = eek_keyboard_dispose;
gobject_class->finalize = eek_keyboard_finalize;
/**
* EekKeyboard:group:
@ -340,6 +519,34 @@ eek_keyboard_class_init (EekKeyboardClass *klass)
PROP_LEVEL,
pspec);
/**
* EekKeyboard:layout:
*
* The layout used to create this #EekKeyboard.
*/
pspec = g_param_spec_object ("layout",
"Layout",
"Layout used to create the keyboard",
EEK_TYPE_LAYOUT,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_LAYOUT,
pspec);
/**
* EekKeyboard:modifier-behavior:
*
* The modifier handling mode of #EekKeyboard.
*/
pspec = g_param_spec_int ("modifier-behavior",
"Modifier behavior",
"Modifier handling mode of the keyboard",
0, G_MAXINT, EEK_MODIFIER_BEHAVIOR_NONE,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_MODIFIER_BEHAVIOR,
pspec);
/**
* EekKeyboard::key-pressed:
* @keyboard: an #EekKeyboard
@ -349,10 +556,10 @@ eek_keyboard_class_init (EekKeyboardClass *klass)
* is shifted to the pressed state.
*/
signals[KEY_PRESSED] =
g_signal_new ("key-pressed",
g_signal_new (I_("key-pressed"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_FIRST,
0,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekKeyboardClass, key_pressed),
NULL,
NULL,
g_cclosure_marshal_VOID__OBJECT,
@ -369,16 +576,38 @@ eek_keyboard_class_init (EekKeyboardClass *klass)
* is shifted to the released state.
*/
signals[KEY_RELEASED] =
g_signal_new ("key-released",
g_signal_new (I_("key-released"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_FIRST,
0,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekKeyboardClass, key_released),
NULL,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE,
1,
EEK_TYPE_KEY);
/**
* EekKeyboard::symbol-index-changed:
* @keyboard: an #EekKeyboard
* @group: row index of the symbol matrix of keys on @keyboard
* @level: column index of the symbol matrix of keys on @keyboard
*
* The ::symbol-index-changed signal is emitted each time the
* global configuration of group/level index changes.
*/
signals[SYMBOL_INDEX_CHANGED] =
g_signal_new (I_("symbol-index-changed"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekKeyboardClass, symbol_index_changed),
NULL,
NULL,
_eek_marshal_VOID__INT_INT,
G_TYPE_NONE,
2,
G_TYPE_INT,
G_TYPE_INT);
}
static void
@ -389,11 +618,13 @@ eek_keyboard_init (EekKeyboard *self)
priv = self->priv = EEK_KEYBOARD_GET_PRIVATE(self);
priv->group = priv->level = 0;
priv->layout = NULL;
priv->is_realized = FALSE;
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_NONE;
priv->modifiers = 0;
priv->outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline));
}
/**
* eek_keyboard_set_keysym_index:
* eek_keyboard_set_symbol_index:
* @keyboard: an #EekKeyboard
* @group: row index of the symbol matrix of keys on @keyboard
* @level: column index of the symbol matrix of keys on @keyboard
@ -401,16 +632,16 @@ eek_keyboard_init (EekKeyboard *self)
* Select a cell of the symbol matrix of each key on @keyboard.
*/
void
eek_keyboard_set_keysym_index (EekKeyboard *keyboard,
eek_keyboard_set_symbol_index (EekKeyboard *keyboard,
gint group,
gint level)
{
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
EEK_KEYBOARD_GET_CLASS(keyboard)->set_keysym_index (keyboard, group, level);
EEK_KEYBOARD_GET_CLASS(keyboard)->set_symbol_index (keyboard, group, level);
}
/**
* eek_keyboard_get_keysym_index:
* eek_keyboard_get_symbol_index:
* @keyboard: an #EekKeyboard
* @group: a pointer where row index of the symbol matrix of keys on
* @keyboard will be stored
@ -420,12 +651,70 @@ eek_keyboard_set_keysym_index (EekKeyboard *keyboard,
* Get the current cell position of the symbol matrix of each key on @keyboard.
*/
void
eek_keyboard_get_keysym_index (EekKeyboard *keyboard,
eek_keyboard_get_symbol_index (EekKeyboard *keyboard,
gint *group,
gint *level)
{
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
EEK_KEYBOARD_GET_CLASS(keyboard)->get_keysym_index (keyboard, group, level);
EEK_KEYBOARD_GET_CLASS(keyboard)->get_symbol_index (keyboard, group, level);
}
/**
* eek_keyboard_set_group:
* @keyboard: an #EekKeyboard
* @group: group index of @keyboard
*
* Set the group index of symbol matrix of @keyboard.
*/
void
eek_keyboard_set_group (EekKeyboard *keyboard,
gint group)
{
gint level = eek_keyboard_get_level (keyboard);
eek_keyboard_set_symbol_index (keyboard, group, level);
}
/**
* eek_keyboard_set_level:
* @keyboard: an #EekKeyboard
* @level: level index of @keyboard
*
* Set the level index of symbol matrix of @keyboard.
*/
void
eek_keyboard_set_level (EekKeyboard *keyboard,
gint level)
{
gint group = eek_keyboard_get_group (keyboard);
eek_keyboard_set_symbol_index (keyboard, group, level);
}
/**
* eek_keyboard_get_group:
* @keyboard: an #EekKeyboard
*
* Return the group index of @keyboard.
*/
gint
eek_keyboard_get_group (EekKeyboard *keyboard)
{
gint group;
eek_keyboard_get_symbol_index (keyboard, &group, NULL);
return group;
}
/**
* eek_keyboard_get_level:
* @keyboard: an #EekKeyboard
*
* Return the level index of @keyboard.
*/
gint
eek_keyboard_get_level (EekKeyboard *keyboard)
{
gint level;
eek_keyboard_get_symbol_index (keyboard, NULL, &level);
return level;
}
/**
@ -445,100 +734,158 @@ eek_keyboard_create_section (EekKeyboard *keyboard)
return section;
}
/**
* eek_keyboard_set_layout:
* @keyboard: an #EekKeyboard
* @layout: an #EekLayout
*
* Set the layout of @keyboard to @layout. This actually turns
* @keyboard to be ready to be drawn on the screen.
*/
void
eek_keyboard_set_layout (EekKeyboard *keyboard,
EekLayout *layout)
{
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
EEK_KEYBOARD_GET_CLASS(keyboard)->set_layout (keyboard, layout);
}
void
eek_keyboard_realize (EekKeyboard *keyboard)
{
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
EEK_KEYBOARD_GET_CLASS(keyboard)->realize (keyboard);
}
/**
* eek_keyboard_find_key_by_keycode:
* @keyboard: an #EekKeyboard
* @keycode: a keycode
* @returns: (transfer none): #EekKey whose keycode is @keycode
*
* Find an #EekKey whose keycode is @keycode.
* Returns: an #EekKey or NULL (if not found)
*/
EekKey *
eek_keyboard_find_key_by_keycode (EekKeyboard *keyboard,
guint keycode)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
return EEK_KEYBOARD_GET_CLASS(keyboard)->find_key_by_keycode (keyboard,
keycode);
g_assert (EEK_IS_KEYBOARD(keyboard));
return EEK_KEYBOARD_GET_CLASS(keyboard)->
find_key_by_keycode (keyboard, keycode);
}
static gint
compare_section_by_position (EekElement *element, gpointer user_data)
/**
* eek_keyboard_get_layout:
* @keyboard: an #EekKeyboard
*
* Get the layout used to create @keyboard.
* Returns: an #EekLayout
*/
EekLayout *
eek_keyboard_get_layout (EekKeyboard *keyboard)
{
EekSection *section = EEK_SECTION(element);
EekPoint *point = user_data;
gint angle;
EekBounds bounds;
EekPoint rotated;
EekKeyboardPrivate *priv;
eek_element_get_bounds (element, &bounds);
rotated.x = point->x - bounds.x;
rotated.y = point->y - bounds.y;
angle = eek_section_get_angle (section);
eek_point_rotate (&rotated, -angle);
if (0 <= rotated.x && 0 <= rotated.y &&
rotated.x <= bounds.width &&
rotated.y <= bounds.height)
return 0;
return -1;
g_assert (EEK_IS_KEYBOARD(keyboard));
priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
return priv->layout;
}
static EekSection *
eek_keyboard_find_section_by_position (EekKeyboard *keyboard,
gdouble x,
gdouble y)
/**
* eek_keyboard_get_size:
* @keyboard: an #EekKeyboard
* @width: width of @keyboard
* @height: height of @keyboard
*
* Get the size of @keyboard.
*/
void
eek_keyboard_get_size (EekKeyboard *keyboard,
gdouble *width,
gdouble *height)
{
EekBounds bounds;
EekPoint point;
EekElement *element;
g_assert (EEK_IS_KEYBOARD(keyboard));
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
point.x = x - bounds.x;
point.y = y - bounds.y;
element = eek_container_find (EEK_CONTAINER(keyboard),
compare_section_by_position,
&point);
return EEK_SECTION(element);
*width = bounds.width;
*height = bounds.height;
}
EekKey *
eek_keyboard_find_key_by_position (EekKeyboard *keyboard,
gdouble x,
gdouble y)
/**
* eek_keyboard_set_modifier_behavior:
* @keyboard: an #EekKeyboard
* @modifier_behavior: modifier behavior of @keyboard
*
* Set the modifier handling mode of @keyboard.
*/
void
eek_keyboard_set_modifier_behavior (EekKeyboard *keyboard,
EekModifierBehavior modifier_behavior)
{
EekSection *section;
EekBounds bounds;
EekKeyboardPrivate *priv;
section = eek_keyboard_find_section_by_position (keyboard, x, y);
if (!section)
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
priv->modifier_behavior = modifier_behavior;
}
/**
* eek_keyboard_get_modifier_behavior:
* @keyboard: an #EekKeyboard
*
* Get the modifier handling mode of @keyboard.
* Returns: #EekModifierBehavior
*/
EekModifierBehavior
eek_keyboard_get_modifier_behavior (EekKeyboard *keyboard)
{
EekKeyboardPrivate *priv;
g_assert (EEK_IS_KEYBOARD(keyboard));
priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
return priv->modifier_behavior;
}
/**
* eek_keyboard_get_modifiers:
* @keyboard: an #EekKeyboard
*
* Get the current modifier status of @keyboard.
* Returns: #EekModifierType
*/
EekModifierType
eek_keyboard_get_modifiers (EekKeyboard *keyboard)
{
EekKeyboardPrivate *priv;
g_assert (EEK_IS_KEYBOARD(keyboard));
priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
return priv->modifiers;
}
/**
* eek_keyboard_add_outline:
* @keyboard: an #EekKeyboard
* @outline: an #EekOutline
*
* Register an outline of @keyboard.
* Returns: an unsigned long id of the registered outline, for later reference
*/
gulong
eek_keyboard_add_outline (EekKeyboard *keyboard,
EekOutline *outline)
{
EekKeyboardPrivate *priv;
EekOutline *_outline;
g_assert (EEK_IS_KEYBOARD(keyboard));
priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
_outline = eek_outline_copy (outline);
g_array_append_val (priv->outline_array, *_outline);
return priv->outline_array->len;
}
/**
* eek_keyboard_get_outline:
* @keyboard: an #EekKeyboard
* @oref: an unsigned long id
*
* Get an outline associated with @oref in @keyboard.
* Returns: an #EekOutline, which should not be released
*/
EekOutline *
eek_keyboard_get_outline (EekKeyboard *keyboard,
gulong oref)
{
EekKeyboardPrivate *priv;
g_assert (EEK_IS_KEYBOARD(keyboard));
priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
if (oref > priv->outline_array->len)
return NULL;
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
x -= bounds.x;
y -= bounds.y;
return eek_section_find_key_by_position (section, x, y);
return &g_array_index (priv->outline_array, EekOutline, oref - 1);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -37,6 +37,12 @@ G_BEGIN_DECLS
typedef struct _EekKeyboardClass EekKeyboardClass;
typedef struct _EekKeyboardPrivate EekKeyboardPrivate;
/**
* EekKeyboard:
*
* The #EekKeyboard structure contains only private data and should
* only be accessed using the provided API.
*/
struct _EekKeyboard
{
/*< private >*/
@ -47,15 +53,16 @@ struct _EekKeyboard
/**
* EekKeyboardClass:
* @set_keysym_index: virtual function for setting group and level of
* @set_symbol_index: virtual function for setting group and level of
* the entire keyboard
* @get_keysym_index: virtual function for getting group and level of
* @get_symbol_index: virtual function for getting group and level of
* the entire keyboard
* @create_section: virtual function for creating a section
* @set_layout: virtual function for setting layout engine
* @find_key_by_keycode: virtual function for finding a key in the
* keyboard by keycode
* @realize: virtual function for applying a layout to the keyboard
* @key_pressed: class handler for #EekKeyboard::key-pressed signal
* @key_released: class handler for #EekKeyboard::key-released signal
* @symbol_index_changed: class handler for #EekKeyboard::symbol-index-changed signal
*/
struct _EekKeyboardClass
{
@ -63,45 +70,90 @@ struct _EekKeyboardClass
EekContainerClass parent_class;
/*< public >*/
void (* set_keysym_index) (EekKeyboard *self,
gint group,
gint level);
void (* get_keysym_index) (EekKeyboard *self,
gint *group,
gint *level);
void (* set_symbol_index) (EekKeyboard *self,
gint group,
gint level);
void (* get_symbol_index) (EekKeyboard *self,
gint *group,
gint *level);
EekSection *(* create_section) (EekKeyboard *self);
EekSection *(* create_section) (EekKeyboard *self);
void (* set_layout) (EekKeyboard *self,
EekLayout *layout);
EekKey *(* find_key_by_keycode) (EekKeyboard *self,
guint keycode);
void (* realize) (EekKeyboard *self);
EekKey *(* find_key_by_keycode) (EekKeyboard *self,
guint keycode);
/* signals */
void (* key_pressed) (EekKeyboard *self,
EekKey *key);
void (* key_released) (EekKeyboard *self,
EekKey *key);
void (* symbol_index_changed) (EekKeyboard *self,
gint group,
gint level);
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_keyboard_get_type (void) G_GNUC_CONST;
GType eek_keyboard_get_type
(void) G_GNUC_CONST;
void eek_keyboard_set_keysym_index (EekKeyboard *keyboard,
gint group,
gint level);
void eek_keyboard_get_keysym_index (EekKeyboard *keyboard,
gint *group,
gint *level);
EekKeyboard *eek_keyboard_new (EekLayout *layout,
gdouble initial_width,
gdouble initial_height);
EekLayout *eek_keyboard_get_layout
(EekKeyboard *keyboard);
void eek_keyboard_get_size
(EekKeyboard *keyboard,
gdouble *width,
gdouble *height);
void eek_keyboard_set_size
(EekKeyboard *keyboard,
gdouble width,
gdouble height);
void eek_keyboard_set_symbol_index
(EekKeyboard *keyboard,
gint group,
gint level);
void eek_keyboard_get_symbol_index
(EekKeyboard *keyboard,
gint *group,
gint *level);
EekSection *eek_keyboard_create_section (EekKeyboard *keyboard);
void eek_keyboard_set_group
(EekKeyboard *keyboard,
gint group);
void eek_keyboard_set_level
(EekKeyboard *keyboard,
gint level);
gint eek_keyboard_get_group
(EekKeyboard *keyboard);
gint eek_keyboard_get_level
(EekKeyboard *keyboard);
void eek_keyboard_set_layout (EekKeyboard *keyboard,
EekLayout *layout);
void eek_keyboard_realize (EekKeyboard *keyboard);
EekKey *eek_keyboard_find_key_by_keycode (EekKeyboard *keyboard,
guint keycode);
EekKey *eek_keyboard_find_key_by_position (EekKeyboard *keyboard,
gdouble x,
gdouble y);
void eek_keyboard_set_modifier_behavior
(EekKeyboard *keyboard,
EekModifierBehavior modifier_behavior);
EekModifierBehavior eek_keyboard_get_modifier_behavior
(EekKeyboard *keyboard);
EekModifierType eek_keyboard_get_modifiers
(EekKeyboard *keyboard);
EekSection *eek_keyboard_create_section
(EekKeyboard *keyboard);
EekKey *eek_keyboard_find_key_by_keycode
(EekKeyboard *keyboard,
guint keycode);
gulong eek_keyboard_add_outline
(EekKeyboard *keyboard,
EekOutline *outline);
EekOutline *eek_keyboard_get_outline
(EekKeyboard *keyboard,
gulong oref);
G_END_DECLS
#endif /* EEK_KEYBOARD_H */

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -20,26 +20,99 @@
/**
* SECTION:eek-keysym
* @short_description: Keysym conversion utilities
* @short_description: an #EekSymbol represents an X keysym
*/
#include <glib.h>
#include <string.h>
#include <stdlib.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-keysym.h"
struct eek_keysym_label {
guint keysym;
const gchar *label;
EekKeysymCategory category;
#include "eek-keysym.h"
#include "eek-serializable.h"
/* modifier keys */
#define EEK_KEYSYM_Shift_L 0xffe1
#define EEK_KEYSYM_Shift_R 0xffe2
#define EEK_KEYSYM_ISO_Level3_Shift 0xfe03
#define EEK_KEYSYM_Caps_Lock 0xffe5
#define EEK_KEYSYM_Shift_Lock 0xffe6
#define EEK_KEYSYM_Control_L 0xffe3
#define EEK_KEYSYM_Control_R 0xffe4
#define EEK_KEYSYM_Alt_L 0xffe9
#define EEK_KEYSYM_Alt_R 0xffea
#define EEK_KEYSYM_Meta_L 0xffe7
#define EEK_KEYSYM_Meta_R 0xffe8
#define EEK_KEYSYM_Super_L 0xffeb
#define EEK_KEYSYM_Super_R 0xffec
#define EEK_KEYSYM_Hyper_L 0xffed
#define EEK_KEYSYM_Hyper_R 0xffee
struct _EekKeysymPrivate {
guint xkeysym;
};
#include "eek-special-keysym-labels.h"
#include "eek-unicode-keysym-labels.h"
#include "eek-keyname-keysym-labels.h"
struct _EekKeysymEntry {
guint xkeysym;
const gchar *name;
EekSymbolCategory category;
};
typedef struct _EekKeysymEntry EekKeysymEntry;
#include "eek-special-keysym-entries.h"
#include "eek-unicode-keysym-entries.h"
#include "eek-xkeysym-keysym-entries.h"
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))
static EekSerializableIface *eek_keysym_parent_serializable_iface;
static void
eek_keysym_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekKeysymPrivate *priv = EEK_KEYSYM_GET_PRIVATE(self);
eek_keysym_parent_serializable_iface->serialize (self, builder);
g_variant_builder_add (builder, "u", priv->xkeysym);
}
static gsize
eek_keysym_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekKeysymPrivate *priv = EEK_KEYSYM_GET_PRIVATE(self);
index = eek_keysym_parent_serializable_iface->deserialize (self,
variant,
index);
g_variant_get_child (variant, index++, "u", &priv->xkeysym);
return index;
}
static void
eek_serializable_iface_init (EekSerializableIface *iface)
{
eek_keysym_parent_serializable_iface =
g_type_interface_peek_parent (iface);
iface->serialize = eek_keysym_real_serialize;
iface->deserialize = eek_keysym_real_deserialize;
}
static gchar *
unichar_to_utf8 (gunichar uc)
@ -57,115 +130,194 @@ unichar_to_utf8 (gunichar uc)
}
static int
keysym_label_compare (const void *key0, const void *key1)
keysym_entry_compare_by_xkeysym (const void *key0, const void *key1)
{
const struct eek_keysym_label *entry0 = key0, *entry1 = key1;
return (gint)entry0->keysym - (gint)entry1->keysym;
const EekKeysymEntry *entry0 = key0, *entry1 = key1;
return (gint) (entry0->xkeysym - entry1->xkeysym);
}
static EekKeysymEntry *
find_keysym_entry_by_xkeysym (guint xkeysym,
const EekKeysymEntry *entries,
gint num_entries)
{
EekKeysymEntry key;
key.xkeysym = xkeysym;
return bsearch (&key, entries, num_entries, sizeof (EekKeysymEntry),
keysym_entry_compare_by_xkeysym);
}
static gboolean
find_keysym (guint keysym,
gchar **label,
EekKeysymCategory *category)
{
struct eek_keysym_label bsearch_key, *bsearch_val;
/* First, search special keysyms. */
bsearch_key.keysym = keysym;
bsearch_val = bsearch (&bsearch_key,
special_keysym_labels,
G_N_ELEMENTS(special_keysym_labels),
sizeof (struct eek_keysym_label),
keysym_label_compare);
if (bsearch_val) {
if (label)
*label = g_strdup (bsearch_val->label);
if (category)
*category = bsearch_val->category;
return TRUE;
}
get_unichar (guint xkeysym, gunichar *uc) {
/* Check for Latin-1 characters (1:1 mapping) */
if ((keysym >= 0x0020 && keysym <= 0x007e) ||
(keysym >= 0x00a0 && keysym <= 0x00ff)) {
if (label)
*label = unichar_to_utf8 (keysym);
if (category)
*category = EEK_KEYSYM_CATEGORY_LETTER;
if ((xkeysym >= 0x0020 && xkeysym <= 0x007e) ||
(xkeysym >= 0x00a0 && xkeysym <= 0x00ff)) {
*uc = xkeysym;
return TRUE;
}
/* Also check for directly encoded 24-bit UCS characters:
*/
if ((keysym & 0xff000000) == 0x01000000) {
if (label)
*label = unichar_to_utf8 (keysym & 0x00ffffff);
if (category)
*category = EEK_KEYSYM_CATEGORY_LETTER;
return TRUE;
}
/* Search known unicode keysyms. */
bsearch_key.keysym = keysym;
bsearch_val = bsearch (&bsearch_key,
unicode_keysym_labels,
G_N_ELEMENTS(unicode_keysym_labels),
sizeof (struct eek_keysym_label),
keysym_label_compare);
if (bsearch_val) {
if (label)
*label = g_strdup (bsearch_val->label);
if (category)
*category = bsearch_val->category;
return TRUE;
}
/* Finally, search keynames. */
bsearch_key.keysym = keysym;
bsearch_val = bsearch (&bsearch_key,
keyname_keysym_labels,
G_N_ELEMENTS(keyname_keysym_labels),
sizeof (struct eek_keysym_label),
keysym_label_compare);
if (bsearch_val) {
if (label)
*label = g_strdup (bsearch_val->label);
if (category)
*category = bsearch_val->category;
if ((xkeysym & 0xff000000) == 0x01000000) {
*uc = xkeysym & 0x00ffffff;
return TRUE;
}
return FALSE;
}
/**
* eek_keysym_to_string:
* @keysym: keysym ID
*
* Return a string representation of @keysym.
*/
gchar *
eek_keysym_to_string (guint keysym)
G_INLINE_FUNC EekModifierType
get_modifier_mask (guint xkeysym)
{
gchar *label;
if (find_keysym (keysym, &label, NULL))
return label;
return g_strdup ("");
switch (xkeysym) {
case EEK_KEYSYM_Shift_L:
case EEK_KEYSYM_Shift_R:
case EEK_KEYSYM_Caps_Lock:
case EEK_KEYSYM_Shift_Lock:
return EEK_SHIFT_MASK;
case EEK_KEYSYM_ISO_Level3_Shift:
return EEK_MOD5_MASK;
case EEK_KEYSYM_Control_L:
case EEK_KEYSYM_Control_R:
return EEK_CONTROL_MASK;
case EEK_KEYSYM_Alt_L:
case EEK_KEYSYM_Alt_R:
return EEK_MOD1_MASK;
case EEK_KEYSYM_Meta_L:
case EEK_KEYSYM_Meta_R:
return EEK_META_MASK;
case EEK_KEYSYM_Super_L:
case EEK_KEYSYM_Super_R:
return EEK_SUPER_MASK;
case EEK_KEYSYM_Hyper_L:
case EEK_KEYSYM_Hyper_R:
return EEK_HYPER_MASK;
}
return 0;
}
/**
* eek_keysym_get_category:
* @keysym: keysym ID
*
* Return a string representation of @keysym.
*/
EekKeysymCategory
eek_keysym_get_category (guint keysym)
static void
eek_keysym_class_init (EekKeysymClass *klass)
{
EekKeysymCategory category;
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
if (find_keysym (keysym, NULL, &category))
return category;
return EEK_KEYSYM_CATEGORY_UNKNOWN;
g_type_class_add_private (gobject_class, sizeof (EekKeysymPrivate));
}
static void
eek_keysym_init (EekKeysym *self)
{
EekKeysymPrivate *priv;
priv = self->priv = EEK_KEYSYM_GET_PRIVATE(self);
priv->xkeysym = EEK_INVALID_KEYSYM;
}
EekKeysym *
eek_keysym_new (guint xkeysym)
{
EekKeysym *keysym;
EekKeysymPrivate *priv;
EekKeysymEntry *special_entry, *xkeysym_entry, *unicode_entry,
*unichar_entry;
gchar *name, *label;
EekSymbolCategory category;
EekModifierType modifier_mask;
gunichar uc;
special_entry =
find_keysym_entry_by_xkeysym (xkeysym,
special_keysym_entries,
G_N_ELEMENTS(special_keysym_entries));
xkeysym_entry =
find_keysym_entry_by_xkeysym (xkeysym,
xkeysym_keysym_entries,
G_N_ELEMENTS(xkeysym_keysym_entries));
unicode_entry =
find_keysym_entry_by_xkeysym (xkeysym,
unicode_keysym_entries,
G_N_ELEMENTS(unicode_keysym_entries));
unichar_entry = NULL;
if (get_unichar (xkeysym, &uc)) {
unichar_entry = g_slice_new (EekKeysymEntry);
unichar_entry->xkeysym = xkeysym;
unichar_entry->name = unichar_to_utf8 (uc);
unichar_entry->category = EEK_SYMBOL_CATEGORY_LETTER;
}
/* name and category */
name = NULL;
if (xkeysym_entry) {
name = g_strdup (xkeysym_entry->name);
category = xkeysym_entry->category;
} else if (unichar_entry) {
name = g_strdup (unichar_entry->name);
category = unichar_entry->category;
} else if (unicode_entry) {
name = g_strdup (unicode_entry->name);
category = unicode_entry->category;
} else {
name = g_strdup ("");
category = EEK_SYMBOL_CATEGORY_UNKNOWN;
}
/* label */
if (special_entry)
label = g_strdup (special_entry->name);
else if (unichar_entry)
label = g_strdup (unichar_entry->name);
else if (unicode_entry)
label = g_strdup (unicode_entry->name);
else
label = g_strdup (name);
modifier_mask = get_modifier_mask (xkeysym);
keysym = g_object_new (EEK_TYPE_KEYSYM,
"name", name,
"label", label,
"category", category,
"modifier-mask", modifier_mask,
NULL);
g_free (name);
g_free (label);
if (unichar_entry) {
g_free ((gpointer) unichar_entry->name);
g_slice_free (EekKeysymEntry, unichar_entry);
}
priv = EEK_KEYSYM_GET_PRIVATE(keysym);
priv->xkeysym = xkeysym;
return keysym;
}
EekKeysym *
eek_keysym_new_from_name (const gchar *name)
{
gint i;
for (i = 0; i < G_N_ELEMENTS(xkeysym_keysym_entries); i++)
if (g_strcmp0 (xkeysym_keysym_entries[i].name, name) == 0)
return eek_keysym_new (xkeysym_keysym_entries[i].xkeysym);
// g_warning ("can't find keysym entry for %s", name);
return g_object_new (EEK_TYPE_KEYSYM,
"name", name,
"label", name,
"category", EEK_SYMBOL_CATEGORY_UNKNOWN,
"modifier-mask", 0,
NULL);
}
guint
eek_keysym_get_xkeysym (EekKeysym *keysym)
{
EekKeysymPrivate *priv;
g_assert (EEK_IS_KEYSYM(keysym));
priv = EEK_KEYSYM_GET_PRIVATE(keysym);
return priv->xkeysym;
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -20,42 +20,45 @@
#ifndef EEK_KEYSYM_H
#define EEK_KEYSYM_H 1
#include <glib-object.h>
#include "eek-symbol.h"
G_BEGIN_DECLS
/**
* EEK_INVALID_KEYSYM:
*
* Pseudo keysym used for error reporting.
*/
#define EEK_INVALID_KEYSYM ((guint)(-1))
#define EEK_INVALID_KEYSYM (0)
/**
* EEK_INVALID_KEYCODE:
*
* Pseudo keycode used for error reporting.
*/
#define EEK_INVALID_KEYCODE ((guint)(-1))
#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))
/**
* EekKeysymCategory:
* @EEK_KEYSYM_CATEGORY_LETTER: the symbol represents an alphabet letter
* @EEK_KEYSYM_CATEGORY_FUNCTION: the symbol represents a function
* @EEK_KEYSYM_CATEGORY_KEYNAME: the symbol does not have meaning but
* have a name
* @EEK_KEYSYM_CATEGORY_UNKNOWN: used for error reporting
*
* Category of the key symbols.
*/
typedef enum {
EEK_KEYSYM_CATEGORY_LETTER,
EEK_KEYSYM_CATEGORY_FUNCTION,
EEK_KEYSYM_CATEGORY_KEYNAME,
EEK_KEYSYM_CATEGORY_UNKNOWN,
typedef struct _EekKeysymClass EekKeysymClass;
typedef struct _EekKeysymPrivate EekKeysymPrivate;
struct _EekKeysym {
/*< private >*/
EEK_KEYSYM_CATEGORY_LAST = EEK_KEYSYM_CATEGORY_UNKNOWN
} EekKeysymCategory;
EekSymbol parent;
gchar *eek_keysym_to_string (guint keysym);
EekKeysymCategory eek_keysym_get_category (guint keysym);
EekKeysymPrivate *priv;
};
struct _EekKeysymClass {
/*< private >*/
EekSymbolClass parent_class;
};
GType eek_keysym_get_type (void) G_GNUC_CONST;
EekKeysym *eek_keysym_new (guint xkeysym);
guint eek_keysym_get_xkeysym (EekKeysym *keysym);
EekKeysym *eek_keysym_new_from_name (const gchar *name);
G_END_DECLS
#endif /* EEK_KEYSYM_H */

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -20,9 +20,9 @@
/**
* SECTION:eek-layout
* @short_description: Base interface of a layout engine
* @short_description: Base class of a layout engine
*
* The #EekLayout class is a base interface of layout engine which
* The #EekLayout class is a base class of layout engine which
* arranges keyboard elements.
*/
@ -33,103 +33,36 @@
#include "eek-layout.h"
#include "eek-keyboard.h"
enum {
GROUP_CHANGED,
CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_ABSTRACT_TYPE (EekLayout, eek_layout, G_TYPE_OBJECT);
static void
eek_layout_base_init (gpointer gobject_class)
eek_layout_class_init (EekLayoutClass *klass)
{
static gboolean is_initialized = FALSE;
if (!is_initialized) {
/**
* EekLayout::group-changed:
* @layout: an #EekLayout that received the signal
* @group: group index
*
* The ::group-changed signal is emitted each time group
* configuration of @layout changed.
*/
signals[GROUP_CHANGED] =
g_signal_new ("group-changed",
G_TYPE_FROM_INTERFACE(gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(EekLayoutIface, group_changed),
NULL,
NULL,
g_cclosure_marshal_VOID__INT,
G_TYPE_NONE, 1,
G_TYPE_INT);
/**
* EekLayout::changed:
* @layout: an #EekLayout that received the signal
*
* The ::changed signal is emitted each time @layout changed
* and re-layout of #EekKeyboard is needed.
*/
signals[CHANGED] =
g_signal_new ("changed",
G_TYPE_FROM_INTERFACE(gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(EekLayoutIface, changed),
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
is_initialized = TRUE;
}
klass->create_keyboard = NULL;
}
GType
eek_layout_get_type (void)
{
static GType iface_type = 0;
if (iface_type == 0) {
static const GTypeInfo info = {
sizeof (EekLayoutIface),
eek_layout_base_init,
NULL,
};
iface_type = g_type_register_static (G_TYPE_INTERFACE,
"EekLayout",
&info, 0);
}
return iface_type;
}
/**
* eek_layout_apply:
* @layout: an #EekLayout
* @keyboard: an #EekKeyboard
*
* Apply @layout to @keyboard. This function is rarely called by user
* programs but called by the subclasses of #EekKeyboard.
*/
void
eek_layout_apply (EekLayout *layout,
EekKeyboard *keyboard)
eek_layout_init (EekLayout *self)
{
g_return_if_fail (EEK_IS_LAYOUT(layout));
EEK_LAYOUT_GET_IFACE(layout)->apply (layout, keyboard);
}
/**
* eek_layout_get_group:
* eek_keyboard_new:
* @layout: an #EekLayout
* @initial_width: initial width of the keyboard
* @initial_height: initial height of the keyboard
*
* Get the group index from the @layout. This function normally
* called after #EekLayout::group-changed signal to change group index
* of all the keys in #EekKeyboard at a time.
* Create a new #EekKeyboard based on @layout.
*/
gint
eek_layout_get_group (EekLayout *layout)
EekKeyboard *
eek_keyboard_new (EekLayout *layout,
gdouble initial_width,
gdouble initial_height)
{
g_return_val_if_fail (EEK_IS_LAYOUT(layout), -1);
return EEK_LAYOUT_GET_IFACE(layout)->get_group (layout);
g_assert (EEK_IS_LAYOUT(layout));
g_assert (EEK_LAYOUT_GET_CLASS(layout)->create_keyboard);
return EEK_LAYOUT_GET_CLASS(layout)->create_keyboard (layout,
initial_width,
initial_height);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -28,44 +28,40 @@ 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_LAYOUT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), EEK_TYPE_LAYOUT, EekLayoutIface))
#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 _EekLayoutIface EekLayoutIface;
typedef struct _EekLayoutClass EekLayoutClass;
typedef struct _EekLayout EekLayout;
/**
* EekLayoutIface:
* @apply: virtual function for applying the layout to a keyboard
* @get_group: virtual function for getting the current group setting
* of the layout
* @group_changed: class handler for #EekLayout::group-changed signal
* @changed: class handler for #EekLayout::changed signal
*/
struct _EekLayoutIface
struct _EekLayout
{
/*< private >*/
GTypeInterface parent_iface;
GObject parent;
};
/**
* EekLayoutClass:
* @create_keyboard: virtual function for creating a keyboard
*/
struct _EekLayoutClass
{
/*< private >*/
GObjectClass parent_class;
/*< public >*/
void (* apply) (EekLayout *self,
EekKeyboard *keyboard);
gint (* get_group) (EekLayout *self);
/* signals */
void (* group_changed) (EekLayout *self,
gint group);
void (* changed) (EekLayout *self);
EekKeyboard* (* create_keyboard) (EekLayout *self,
gdouble initial_width,
gdouble initial_height);
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_layout_get_type (void) G_GNUC_CONST;
void eek_layout_apply (EekLayout *layout,
EekKeyboard *keyboard);
gint eek_layout_get_group (EekLayout *layout);
GType eek_layout_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* EEK_LAYOUT_H */

1
eek/eek-marshalers.list Normal file
View File

@ -0,0 +1 @@
VOID:INT,INT

1059
eek/eek-renderer.c Normal file

File diff suppressed because it is too large Load Diff

127
eek/eek-renderer.h Normal file
View File

@ -0,0 +1,127 @@
/*
* 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 EEK_RENDERER_H
#define EEK_RENDERER_H 1
#include <pango/pangocairo.h>
#include "eek-keyboard.h"
#include "eek-keysym.h"
#include "eek-types.h"
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;
};
struct _EekRendererClass
{
GObjectClass parent_class;
void (* render_key_label) (EekRenderer *self,
PangoLayout *layout,
EekKey *key);
void (* render_key_outline) (EekRenderer *self,
cairo_t *cr,
EekKey *key,
gdouble scale,
gboolean rotate);
void (* render_key) (EekRenderer *self,
cairo_t *cr,
EekKey *key,
gdouble scale,
gboolean rotate);
void (* render_keyboard) (EekRenderer *self,
cairo_t *cr);
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_renderer_get_type (void) G_GNUC_CONST;
EekRenderer *eek_renderer_new (EekKeyboard *keyboard,
PangoContext *pcontext);
void eek_renderer_set_allocation_size (EekRenderer *renderer,
gdouble width,
gdouble height);
void eek_renderer_get_size (EekRenderer *renderer,
gdouble *width,
gdouble *height);
void eek_renderer_get_key_bounds (EekRenderer *renderer,
EekKey *key,
EekBounds *bounds,
gboolean rotate);
gdouble eek_renderer_get_scale (EekRenderer *renderer);
PangoLayout *eek_renderer_create_pango_layout (EekRenderer *renderer);
void eek_renderer_render_key_label (EekRenderer *renderer,
PangoLayout *layout,
EekKey *key);
void eek_renderer_render_key_outline (EekRenderer *renderer,
cairo_t *cr,
EekKey *key,
gdouble scale,
gboolean rotate);
void eek_renderer_render_key (EekRenderer *renderer,
cairo_t *cr,
EekKey *key,
gdouble scale,
gboolean rotate);
void eek_renderer_render_keyboard (EekRenderer *renderer,
cairo_t *cr);
void eek_renderer_set_foreground (EekRenderer *renderer,
EekColor *foreground);
void eek_renderer_set_background (EekRenderer *renderer,
EekColor *background);
void eek_renderer_get_foreground (EekRenderer *renderer,
EekColor *foreground);
void eek_renderer_get_background (EekRenderer *renderer,
EekColor *background);
void eek_renderer_set_border_width (EekRenderer *renderer,
gdouble border_width);
EekKey *eek_renderer_find_key_by_position (EekRenderer *renderer,
gdouble x,
gdouble y);
G_END_DECLS
#endif /* EEK_RENDERER_H */

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -34,6 +34,7 @@
#endif /* HAVE_CONFIG_H */
#include "eek-section.h"
#include "eek-key.h"
#include "eek-serializable.h"
enum {
PROP_0,
@ -49,7 +50,11 @@ enum {
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (EekSection, eek_section, EEK_TYPE_CONTAINER);
static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_TYPE_WITH_CODE (EekSection, eek_section, EEK_TYPE_CONTAINER,
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init));
#define EEK_SECTION_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_SECTION, EekSectionPrivate))
@ -66,9 +71,82 @@ struct _EekSectionPrivate
{
gint angle;
GSList *rows;
GSList *keys;
};
static EekSerializableIface *eek_section_parent_serializable_iface;
static GVariant *
_g_variant_new_row (EekRow *row)
{
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("(iu)"));
g_variant_builder_add (&builder, "i", row->num_columns);
g_variant_builder_add (&builder, "u", row->orientation);
return g_variant_builder_end (&builder);
}
static EekRow *
_g_variant_get_row (GVariant *variant)
{
EekRow *row = g_slice_new (EekRow);
g_variant_get_child (variant, 0, "i", &row->num_columns);
g_variant_get_child (variant, 1, "u", &row->orientation);
return row;
}
static void
eek_section_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekSectionPrivate *priv = EEK_SECTION_GET_PRIVATE(self);
GSList *head;
GVariantBuilder array;
eek_section_parent_serializable_iface->serialize (self, builder);
g_variant_builder_add (builder, "i", priv->angle);
g_variant_builder_init (&array, G_VARIANT_TYPE("av"));
for (head = priv->rows; head; head = g_slist_next (head))
g_variant_builder_add (&array, "v", _g_variant_new_row (head->data));
g_variant_builder_add (builder, "v", g_variant_builder_end (&array));
}
static gsize
eek_section_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekSectionPrivate *priv = EEK_SECTION_GET_PRIVATE(self);
GVariant *array, *child;
GVariantIter iter;
index = eek_section_parent_serializable_iface->deserialize (self,
variant,
index);
g_variant_get_child (variant, index++, "i", &priv->angle);
g_variant_get_child (variant, index++, "v", &array);
g_variant_iter_init (&iter, array);
while (g_variant_iter_next (&iter, "v", &child))
priv->rows = g_slist_prepend (priv->rows, _g_variant_get_row (child));
priv->rows = g_slist_reverse (priv->rows);
return index;
}
static void
eek_serializable_iface_init (EekSerializableIface *iface)
{
eek_section_parent_serializable_iface =
g_type_interface_peek_parent (iface);
iface->serialize = eek_section_real_serialize;
iface->deserialize = eek_section_real_deserialize;
}
static void
eek_section_real_set_angle (EekSection *self,
gint angle)
@ -128,13 +206,15 @@ eek_section_real_get_row (EekSection *self,
}
static void
pressed_event (EekKey *key, EekSection *section)
on_pressed (EekKey *key,
EekSection *section)
{
g_signal_emit_by_name (section, "key-pressed", key);
}
static void
released_event (EekKey *key, EekSection *section)
on_released (EekKey *key,
EekSection *section)
{
g_signal_emit_by_name (section, "key-released", key);
}
@ -159,9 +239,6 @@ eek_section_real_create_key (EekSection *self,
NULL);
g_return_val_if_fail (key, NULL);
g_signal_connect (key, "pressed", G_CALLBACK(pressed_event), self);
g_signal_connect (key, "released", G_CALLBACK(released_event), self);
EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self),
EEK_ELEMENT(key));
@ -235,9 +312,26 @@ eek_section_get_property (GObject *object,
}
}
static void
eek_section_real_child_added (EekContainer *self,
EekElement *element)
{
g_signal_connect (element, "pressed", G_CALLBACK(on_pressed), self);
g_signal_connect (element, "released", G_CALLBACK(on_released), self);
}
static void
eek_section_real_child_removed (EekContainer *self,
EekElement *element)
{
g_signal_handlers_disconnect_by_func (element, on_pressed, self);
g_signal_handlers_disconnect_by_func (element, on_released, self);
}
static void
eek_section_class_init (EekSectionClass *klass)
{
EekContainerClass *container_class = EEK_CONTAINER_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
@ -251,6 +345,10 @@ eek_section_class_init (EekSectionClass *klass)
klass->create_key = eek_section_real_create_key;
klass->find_key_by_keycode = eek_section_real_find_key_by_keycode;
/* signals */
container_class->child_added = eek_section_real_child_added;
container_class->child_removed = eek_section_real_child_removed;
gobject_class->set_property = eek_section_set_property;
gobject_class->get_property = eek_section_get_property;
gobject_class->finalize = eek_section_finalize;
@ -278,7 +376,7 @@ eek_section_class_init (EekSectionClass *klass)
* is shifted to the pressed state.
*/
signals[KEY_PRESSED] =
g_signal_new ("key-pressed",
g_signal_new (I_("key-pressed"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_FIRST,
0,
@ -298,7 +396,7 @@ eek_section_class_init (EekSectionClass *klass)
* is shifted to the released state.
*/
signals[KEY_RELEASED] =
g_signal_new ("key-released",
g_signal_new (I_("key-released"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_FIRST,
0,
@ -438,26 +536,3 @@ eek_section_find_key_by_keycode (EekSection *section,
return EEK_SECTION_GET_CLASS(section)->find_key_by_keycode (section,
keycode);
}
EekKey *
eek_section_find_key_by_position (EekSection *section,
gdouble x,
gdouble y)
{
gint angle;
EekBounds bounds;
EekPoint point;
EekElement *key;
eek_element_get_bounds (EEK_ELEMENT(section), &bounds);
point.x = x - bounds.x;
point.y = y - bounds.y;
angle = eek_section_get_angle (section);
eek_point_rotate (&point, -angle);
key = eek_container_find_by_position (EEK_CONTAINER(section),
point.x + bounds.x,
point.y + bounds.y);
if (!key)
return NULL;
return EEK_KEY(key);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010 Red Hat, Inc.
* 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
@ -107,9 +107,6 @@ EekKey *eek_section_create_key (EekSection *section,
EekKey *eek_section_find_key_by_keycode (EekSection *section,
guint keycode);
EekKey *eek_section_find_key_by_position (EekSection *section,
gdouble x,
gdouble y);
G_END_DECLS
#endif /* EEK_SECTION_H */

93
eek/eek-serializable.c Normal file
View File

@ -0,0 +1,93 @@
/*
* Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
* Copyright (C) 2008-2010 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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:eek-serializable
* @short_description: Interface implemented by #EekElement to
* serialize it to #GVariant
*
* The #EekSerializableIface interface defines serialize/deserialize
* method of #EekElement.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-serializable.h"
GType
eek_serializable_get_type (void)
{
static GType iface_type = 0;
if (iface_type == 0) {
static const GTypeInfo info = {
sizeof (EekSerializableIface),
NULL,
NULL,
};
iface_type = g_type_register_static (G_TYPE_INTERFACE,
"EekSerializable",
&info, 0);
}
return iface_type;
}
GVariant *
eek_serializable_serialize (EekSerializable *object)
{
GVariantBuilder builder;
g_return_val_if_fail (EEK_IS_SERIALIZABLE (object), FALSE);
g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
g_variant_builder_add (&builder, "s", g_type_name (G_OBJECT_TYPE (object)));
EEK_SERIALIZABLE_GET_IFACE (object)->serialize (object, &builder);
return g_variant_builder_end (&builder);
}
EekSerializable *
eek_serializable_deserialize (GVariant *variant)
{
gchar *type_name = NULL;
GType type;
EekSerializable *object;
gsize index = 0;
g_return_val_if_fail (variant != NULL, NULL);
g_variant_get_child (variant, index++, "&s", &type_name);
type = g_type_from_name (type_name);
g_return_val_if_fail (g_type_is_a (type, EEK_TYPE_SERIALIZABLE), NULL);
object = g_object_new (type, NULL);
index = EEK_SERIALIZABLE_GET_IFACE (object)->deserialize (object,
variant,
index);
if (index < 0) {
g_object_unref (object);
g_return_val_if_reached (NULL);
}
return object;
}

62
eek/eek-serializable.h Normal file
View File

@ -0,0 +1,62 @@
/*
* 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 EEK_SERIALIZABLE_H
#define EEK_SERIALIZABLE_H 1
#include <glib-object.h>
G_BEGIN_DECLS
#define EEK_TYPE_SERIALIZABLE (eek_serializable_get_type())
#define EEK_SERIALIZABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_SERIALIZABLE, EekSerializable))
#define EEK_IS_SERIALIZABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_SERIALIZABLE))
#define EEK_SERIALIZABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), EEK_TYPE_SERIALIZABLE, EekSerializableIface))
typedef struct _EekSerializable EekSerializable;
typedef struct _EekSerializableIface EekSerializableIface;
/**
* EekSerializableIface:
*
* @serialize: virtual function for serializing object into #GVariant
* @deserialize: virtual function for deserializing object from #GVariant
*/
struct _EekSerializableIface
{
/*< private >*/
GTypeInterface parent_iface;
void (* serialize) (EekSerializable *object,
GVariantBuilder *builder);
gsize (* deserialize) (EekSerializable *object,
GVariant *variant,
gsize index);
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_serializable_get_type (void);
GVariant *eek_serializable_serialize (EekSerializable *object);
EekSerializable *eek_serializable_deserialize (GVariant *variant);
G_END_DECLS
#endif /* EEK_SERIALIZABLE_H */

349
eek/eek-symbol.c Normal file
View File

@ -0,0 +1,349 @@
/*
* 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
*/
/**
* SECTION:eek-symbol
* @short_description: Base class of a symbol
*
* The #EekSymbolClass class represents a symbol assigned to a key.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-symbol.h"
#include "eek-serializable.h"
enum {
PROP_0,
PROP_NAME,
PROP_LABEL,
PROP_CATEGORY,
PROP_MODIFIER_MASK,
PROP_LAST
};
struct _EekSymbolPrivate {
gchar *name;
gchar *label;
EekSymbolCategory category;
EekModifierType modifier_mask;
};
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))
static void
eek_symbol_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekSymbolPrivate *priv = EEK_SYMBOL_GET_PRIVATE(self);
g_variant_builder_add (builder, "s", priv->name);
g_variant_builder_add (builder, "s", priv->label);
g_variant_builder_add (builder, "u", priv->category);
g_variant_builder_add (builder, "u", priv->modifier_mask);
}
static gsize
eek_symbol_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekSymbolPrivate *priv = EEK_SYMBOL_GET_PRIVATE(self);
g_variant_get_child (variant, index++, "s", &priv->name);
g_variant_get_child (variant, index++, "s", &priv->label);
g_variant_get_child (variant, index++, "u", &priv->category);
g_variant_get_child (variant, index++, "u", &priv->modifier_mask);
return index;
}
static void
eek_serializable_iface_init (EekSerializableIface *iface)
{
iface->serialize = eek_symbol_real_serialize;
iface->deserialize = eek_symbol_real_deserialize;
}
static void
eek_symbol_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
switch (prop_id) {
case PROP_NAME:
eek_symbol_set_name (EEK_SYMBOL(object), g_value_get_string (value));
break;
case PROP_LABEL:
eek_symbol_set_label (EEK_SYMBOL(object), g_value_get_string (value));
break;
case PROP_CATEGORY:
eek_symbol_set_category (EEK_SYMBOL(object), g_value_get_uint (value));
break;
case PROP_MODIFIER_MASK:
eek_symbol_set_modifier_mask (EEK_SYMBOL(object),
g_value_get_uint (value));
break;
default:
g_object_set_property (object,
g_param_spec_get_name (pspec),
value);
break;
}
}
static void
eek_symbol_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
switch (prop_id) {
case PROP_NAME:
g_value_set_string (value, eek_symbol_get_name (EEK_SYMBOL(object)));
break;
case PROP_LABEL:
g_value_set_string (value, eek_symbol_get_label (EEK_SYMBOL(object)));
break;
case PROP_CATEGORY:
g_value_set_uint (value, eek_symbol_get_category (EEK_SYMBOL(object)));
break;
case PROP_MODIFIER_MASK:
g_value_set_uint (value,
eek_symbol_get_modifier_mask (EEK_SYMBOL(object)));
break;
default:
g_object_get_property (object,
g_param_spec_get_name (pspec),
value);
break;
}
}
static void
eek_symbol_finalize (GObject *object)
{
EekSymbolPrivate *priv = EEK_SYMBOL_GET_PRIVATE(object);
g_free (priv->name);
G_OBJECT_CLASS (eek_symbol_parent_class)->finalize (object);
}
static void
eek_symbol_class_init (EekSymbolClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
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;
pspec = g_param_spec_string ("name",
"Name",
"Canonical name of the symbol",
NULL,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_NAME, pspec);
pspec = g_param_spec_string ("label",
"Label",
"Text used to display the symbol",
NULL,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_LABEL, pspec);
pspec = g_param_spec_uint ("category",
"Category",
"Category of the symbol",
0, G_MAXUINT, 0,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_CATEGORY, pspec);
pspec = g_param_spec_uint ("modifier-mask",
"Modifier mask",
"Modifier mask of the symbol",
0, G_MAXUINT, 0,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_MODIFIER_MASK, pspec);
}
static void
eek_symbol_init (EekSymbol *self)
{
EekSymbolPrivate *priv;
priv = self->priv = EEK_SYMBOL_GET_PRIVATE(self);
priv->name = NULL;
priv->label = NULL;
priv->category = EEK_SYMBOL_CATEGORY_UNKNOWN;
priv->modifier_mask = 0;
}
EekSymbol *
eek_symbol_new (const gchar *name)
{
return g_object_new (EEK_TYPE_SYMBOL, "name", name);
}
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);
g_free (priv->name);
priv->name = g_strdup (name);
}
G_CONST_RETURN 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);
return priv->name;
}
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);
g_free (priv->label);
priv->label = g_strdup (label);
}
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);
return g_strdup (priv->label);
}
/**
* eek_symbol_set_category:
* @symbol: an #EekSymbol
* @category: an #EekSymbolCategory
*
* Set symbol category of @symbol to @category.
*/
void
eek_symbol_set_category (EekSymbol *symbol,
EekSymbolCategory category)
{
EekSymbolPrivate *priv;
g_return_if_fail (EEK_IS_SYMBOL(symbol));
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
priv->category = category;
}
/**
* eek_symbol_get_category:
* @symbol: an #EekSymbol
*
* Returns symbol category of @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);
return priv->category;
}
/**
* eek_symbol_set_modifier_mask:
* @symbol: an #EekSymbol
*
* Set modifier mask @symbol can trigger.
*/
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);
priv->modifier_mask = mask;
}
/**
* eek_symbol_get_modifier_mask:
* @symbol: an #EekSymbol
*
* Returns modifier mask @symbol can trigger.
*/
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);
return priv->modifier_mask;
}
/**
* eek_symbol_is_modifier:
* @symbol: an #EekSymbol
*
* Check if @symbol is a modifier.
* Returns: %TRUE if @symbol is a modifier.
*/
gboolean
eek_symbol_is_modifier (EekSymbol *symbol)
{
return eek_symbol_get_modifier_mask (symbol) != 0;
}

Some files were not shown because too many files have changed in this diff Show More