--- /dev/null
+aclocal.m4
+libtool.m4
+ltoptions.m4
+ltsugar.m4
+ltversion.m4
+lt~obsolete.m4
+autom4te.cache
+config.*
+configure
+depcomp
+install-sh
+libtool
+ltmain.sh
+Makefile
+Makefile.in
+missing
+patch
+weekeyboard
+stamp-h1
+*.o
+*.lo
+.deps
+.libs
+*.orig
+*.rej
+*.bak
+*~
+input-method-client-protocol.h
+input-method-protocol.c
+text-client-protocol.h
+text-protocol.c
+weekeyboard-ibus-test
+weekeyboard-config-eet-test
--- /dev/null
+Eduardo Lima (Etrunko) <eduardo.lima@intel.com>
--- /dev/null
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
--- /dev/null
+SUBDIRS=protocol src data/themes
+
+clean-local:
+ rm -f $(top_builddir)/install-sh
+ rm -f $(top_builddir)/missing
+ rm -f $(top_builddir)/config.guess
+ rm -f $(top_builddir)/ltmain.sh
+ rm -f $(top_builddir)/depcomp
+ rm -f $(top_builddir)/config.sub
--- /dev/null
+#! /bin/sh
+
+test -n "$srcdir" || srcdir=`dirname "$0"`
+test -n "$srcdir" || srcdir=.
+(
+ cd "$srcdir" &&
+ autoreconf --force -v --install
+) || exit
+test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"
--- /dev/null
+m4_define([wkb_major], [0])
+m4_define([wkb_minor], [0])
+m4_define([wkb_micro], [1])
+m4_define([wkb_version], [wkb_major.wkb_minor.wkb_micro])
+
+AC_PREREQ([2.64])
+AC_INIT([weekeyboard], [wkb_version])
+
+AC_SUBST([weekeyboard_MAJOR], [wkb_major])
+AC_SUBST([weekeyboard_MINOR], [wkb_minor])
+AC_SUBST([weekeyboard_MICRO], [wkb_micro])
+AC_SUBST([weekeyboard_VERSION], [wkb_version])
+
+AC_CONFIG_HEADERS([config.h])
+
+AM_INIT_AUTOMAKE([1.11 -Wall -Wextra parallel-tests foreign color-tests])
+
+AM_SILENT_RULES([yes])
+
+# Check for programs
+AC_PROG_CC
+AC_PROG_SED
+
+# Initialize libtool
+LT_PREREQ([2.2])
+LT_INIT([disable-static])
+
+PKG_PROG_PKG_CONFIG()
+
+PKG_CHECK_MODULES(WAYLAND, [wayland-client >= 1.2.0])
+PKG_CHECK_MODULES(EFL, [eina eet evas ecore ecore-evas ecore-wayland edje])
+
+AC_ARG_WITH(edje-cc,
+ AS_HELP_STRING([--with-edje-cc=PATH], [Path to edje_cc binary]),
+ [EDJE_CC_PATH=${withval}], [EDJE_CC_PATH=$($PKG_CONFIG --variable=prefix edje)/bin/edje_cc])
+AC_SUBST([EDJE_CC_PATH])
+
+
+AC_ARG_ENABLE([ibus],
+ [AC_HELP_STRING([--disable-ibus],
+ [Disable integration with IBus input method system])],
+ [], [enable_ibus=yes])
+
+AM_CONDITIONAL(ENABLE_IBUS, test "x$enable_ibus" = "xyes")
+
+if test "x$enable_ibus" = "xyes"; then
+ PKG_CHECK_MODULES(ELDBUS, [eldbus])
+ AC_CHECK_PROG([have_ibus], [ibus], [yes], [no])
+
+ AS_IF([ test "x$have ibus" = "xno" ],
+ [ AC_MSG_ERROR([The ibus executable was not found.]) ])
+
+ IBUS_ADDR=`ibus address > /dev/null 2>&1`
+ AS_IF([ test $? -ne 0 ],
+ [ AC_MSG_WARN([The ibus executable does not support 'address' argument.]) ])
+
+ AC_DEFINE(BUILD_IBUS, [1], [Build integration with IBus input method system])
+fi
+
+WAYLAND_SCANNER_RULES(['$(top_srcdir)/protocol'])
+
+AC_CONFIG_FILES([Makefile
+ src/Makefile
+ data/themes/Makefile
+ protocol/Makefile])
+AC_OUTPUT
--- /dev/null
+MAINTAINERCLEANFILES = Makefile.in
+
+EDJE_CC = @EDJE_CC_PATH@
+EDJE_FLAGS_VERBOSE_ =
+EDJE_FLAGS_VERBOSE_0 =
+EDJE_FLAGS_VERBOSE_1 = -v
+EDJE_FLAGS = $(EDJE_FLAGS_VERBOSE_$(V))
+
+filesdir = $(pkgdatadir)
+files_DATA = default_600.edj \
+ default_720.edj
+
+DEFAULT_FILES = default/default.edc \
+ default/default_600.edc \
+ default/default_720.edc \
+ default/ignorekeys.txt \
+ default/fonts/DroidSans-Bold.ttf \
+ default/fonts/DroidSans.ttf \
+ default/images/key-hint-bg.png \
+ default/images/icon-language.png \
+ default/images/icon-backspace.png \
+ default/images/key-special.png \
+ default/images/icon-space.png \
+ default/images/key-hint.png \
+ default/images/icon-shift.png \
+ default/images/icon-shift-active.png \
+ default/images/icon-enter.png \
+ default/images/key-special-pressed.png \
+ default/images/key-default.png \
+ default/images/key-default-pressed.png
+
+EXTRA_DIST = $(DEFAULT_FILES)
+
+default_600.edj: Makefile default/default_600.edc $(default_FILES)
+ $(EDJE_CC) $(EDJE_FLAGS) \
+ -dd $(top_srcdir)/data/themes/default \
+ -id $(top_srcdir)/data/themes/default/images \
+ -fd $(top_srcdir)/data/themes/default/fonts \
+ $(top_srcdir)/data/themes/default/default_600.edc \
+ $(top_builddir)/data/themes/default_600.edj
+
+default_720.edj: Makefile default/default_720.edc $(default_FILES)
+ $(EDJE_CC) $(EDJE_FLAGS) \
+ -dd $(top_srcdir)/data/themes/default \
+ -id $(top_srcdir)/data/themes/default/images \
+ -fd $(top_srcdir)/data/themes/default/fonts \
+ $(top_srcdir)/data/themes/default/default_720.edc \
+ $(top_builddir)/data/themes/default_720.edj
+
+clean-local:
+ rm -f $(top_builddir)/data/themes/*.edj
--- /dev/null
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+images {
+ image: "icon-backspace.png" COMP;
+ image: "icon-enter.png" COMP;
+ image: "icon-language.png" COMP;
+ image: "icon-shift-active.png" COMP;
+ image: "icon-shift.png" COMP;
+ image: "icon-space.png" COMP;
+
+ image: "key-default.png" COMP;
+ image: "key-default-pressed.png" COMP;
+ image: "key-hint.png" COMP;
+ image: "key-hint-bg.png" COMP;
+ image: "key-special.png" COMP;
+ image: "key-special-pressed.png" COMP;
+}
+
+fonts {
+ font: "DroidSans.ttf" "DroidSans";
+ font: "DroidSans-Bold.ttf" "DroidSansBold";
+}
+
+data {
+ file: "ignore-keys" "ignorekeys.txt";
+}
+
+collections {
+ group {
+ name: "main";
+
+ min: MIN_WIDTH MIN_HEIGHT;
+ max: MAX_WIDTH MAX_HEIGHT;
+
+ parts {
+ part {
+ name: "rect_bg";
+ mouse_events: 0;
+ type: RECT;
+ description {
+ state: "default" 0.0;
+ color: 255 255 255 0;
+ rel1 {
+ relative: 0.0 0.0;
+ offset: 0 0;
+ }
+ rel2 {
+ relative: 1.0 1.0;
+ offset: -1 -1;
+ }
+ }
+ }
+
+ part {
+ name: "background";
+ mouse_events: 1;
+ pointer_mode: NOGRAB;
+ type: RECT;
+ description {
+ state: "default" 0.0;
+ color: 214 215 218 255;
+ rel1 {
+ relative: 0.0 0.0;
+ offset: 0 (150*SCALE);
+ }
+ rel2 {
+ relative: 1.0 1.0;
+ offset: -1 -1;
+ }
+ }
+ }
+ }
+
+#define KEY_GROUP(_name) \
+ parts { \
+ part { \
+ name: _name"_clip"; \
+ type: RECT; \
+ description { \
+ state: "default" 0.0; \
+ rel1 { \
+ relative: 0.0 0.0; \
+ offset: 0 0; \
+ } \
+ rel2 { \
+ relative: 1.0 1.0; \
+ offset: -1 -1; \
+ } \
+ } \
+ description { \
+ state: "hidden" 0.0; \
+ inherit: "default" 0.0; \
+ visible: 0; \
+ } \
+ } \
+ part { \
+ name: _name; \
+ type: GROUP; \
+ source: _name; \
+ clip_to: _name"_clip"; \
+ description { \
+ state: "default" 0.0; \
+ rel1 { \
+ to: "background"; \
+ relative: 0.0 0.0; \
+ offset: (5*SCALE) (10*SCALE); \
+ } \
+ rel2 { \
+ to: "background"; \
+ relative: 1.0 1.0; \
+ offset: -1 -1; \
+ } \
+ } \
+ } \
+ } \
+ programs { \
+ program { \
+ name: "show-"_name; \
+ action: STATE_SET "default" 0.0; \
+ target: _name"_clip"; \
+ } \
+ program { \
+ name: "hide-"_name; \
+ action: STATE_SET "hidden" 0.0; \
+ target: _name"_clip"; \
+ } \
+ }
+
+ KEY_GROUP("alphanum")
+ KEY_GROUP("numeric")
+ KEY_GROUP("special-1")
+ KEY_GROUP("special-2")
+ KEY_GROUP("fixed")
+
+ programs {
+ program {
+ name: "alphanum_show";
+ signal: "show,alphanumeric";
+ after: "show-alphanum";
+ after: "hide-numeric";
+ after: "hide-special-1";
+ after: "hide-special-2";
+ after: "show-fixed";
+ }
+
+ program {
+ name: "numeric_show";
+ signal: "show,numeric";
+ after: "show-numeric";
+ after: "hide-alphanum";
+ after: "hide-special-1";
+ after: "hide-special-2";
+ after: "hide-fixed";
+ }
+
+ program {
+ name: "special-1_show";
+ signal: "show,special,1";
+ after: "show-special-1";
+ after: "hide-numeric";
+ after: "hide-alphanum";
+ after: "hide-special-2";
+ after: "show-fixed";
+ }
+
+ program {
+ name: "special-2_show";
+ signal: "show,special,2";
+ after: "show-special-2";
+ after: "hide-numeric";
+ after: "hide-alphanum";
+ after: "hide-special-1";
+ after: "show-fixed";
+ }
+
+ program {
+ name: "?123_clicked";
+ signal: "key_down";
+ source: "alphanum:?123";
+ after: "special-1_show";
+ }
+ program {
+ name: "special-1_abc_clicked";
+ signal: "key_down";
+ source: "special-1:abc";
+ after: "alphanum_show";
+ }
+ program {
+ name: "special-2_abc_clicked";
+ signal: "key_down";
+ source: "special-2:abc";
+ after: "alphanum_show";
+ }
+ program {
+ name: "1/2_clicked";
+ signal: "key_down";
+ source: "special-1:1/2";
+ after: "special-2_show";
+ }
+ program {
+ name: "2/2_clicked";
+ signal: "key_down";
+ source: "special-2:2/2";
+ after: "special-1_show";
+ }
+ program {
+ name: "init";
+ signal: "show";
+ after: "alphanum_show";
+ }
+ }
+ }
+
+ group {
+ name: "alphanum";
+
+#define MOUSE_DOWN_UP_PROGRAMS \
+ script { \
+ public shift_pressed = 0; \
+ public mouse_down = 0; \
+ public long_press_timer = 0; \
+ public long_press = 0; \
+ public pressed_key; \
+ \
+ public _set_long_press(val) { \
+ new _cur[20]; \
+ new _timer; \
+ _timer = get_int(long_press_timer); \
+ if (_timer) { \
+ cancel_timer(_timer); \
+ set_int(long_press_timer, 0); \
+ } \
+ set_int(long_press, val); \
+ if (!val) \
+ return; \
+ get_str(pressed_key, _cur, 20); \
+ if (strlen(_cur) > 0) { \
+ emit("long_press", _cur); \
+ } \
+ } \
+ \
+ _set_key_pressed(_key[]) { \
+ new _cur[20]; \
+ new _prg[30]; \
+ new _timer; \
+ get_str(pressed_key, _cur, 20); \
+ if (strlen(_cur) > 0) { \
+ _set_key_released(_cur); \
+ } \
+ set_str(pressed_key, _key); \
+ _timer = timer(1.0, "_set_long_press", 1); \
+ set_int(long_press_timer, _timer); \
+ snprintf(_prg, 30, "key-press-%s", _key); \
+ run_program(get_program_id(_prg)); \
+ } \
+ \
+ _set_key_released(_key[]) { \
+ new _prg[30]; \
+ _set_long_press(0); \
+ set_str(pressed_key, ""); \
+ snprintf(_prg, 30, "key-release-%s", _key); \
+ run_program(get_program_id(_prg)); \
+ } \
+ } \
+ programs { \
+ program { \
+ name: "mouse-down"; \
+ signal: "mouse,down,1"; \
+ source: "*"; \
+ script { \
+ set_int(mouse_down, 1); \
+ } \
+ } \
+ program { \
+ name: "mouse-up"; \
+ signal: "mouse,up,1"; \
+ source: "*"; \
+ script { \
+ set_int(mouse_down, 0); \
+ } \
+ } \
+ }
+
+ MOUSE_DOWN_UP_PROGRAMS
+ parts {
+#undef INIT_HSPACE
+#define INIT_HSPACE 5
+#define KEY_WIDTH (65*SCALE)
+#define KEY_HEIGHT (90*SCALE)
+#define COL_SPACE 5
+#define KEY_OFFSET(index) ((COL_SPACE+KEY_WIDTH)*index)+INIT_HSPACE
+
+#define FIRST_ROW 0
+#define ROW_SPACE (20*SCALE)
+
+#define SKEY_FULL(key_low, key_up, key_name, key_alt, x, y) \
+ part { \
+ name: "key-img-"key_name; \
+ type: IMAGE; \
+ mouse_events: 0; \
+ description { \
+ state: "default" 0.0; \
+ min: KEY_WIDTH KEY_HEIGHT; \
+ max: KEY_WIDTH KEY_HEIGHT; \
+ fixed: 1 1; \
+ rel1 { \
+ relative: 0.0 0.0; \
+ offset: (x) (y); \
+ } \
+ rel2 { \
+ relative: 0.0 0.0; \
+ offset: (x+KEY_WIDTH-1) (y+KEY_HEIGHT-1); \
+ } \
+ image { \
+ normal: "key-default.png"; \
+ border: 8 8 10 10; \
+ } \
+ } \
+ description { \
+ state: "down" 0.0; \
+ inherit: "default" 0.0; \
+ rel1.offset: (x+1) (y+1); \
+ rel2.offset: (x+1+KEY_WIDTH-1) (y+1+KEY_HEIGHT-1); \
+ image.normal: "key-default-pressed.png"; \
+ } \
+ } \
+ part { \
+ name: "key-bg-"key_name; \
+ type: RECT; \
+ pointer_mode: NOGRAB; \
+ description { \
+ state: "default" 0.0; \
+ color: 0 0 0 0; \
+ rel1 { \
+ to: "key-img-"key_name; \
+ relative: 0.0 0.0; \
+ offset: 3 2; \
+ } \
+ rel2 { \
+ to: "key-img-"key_name; \
+ relative: 1.0 1.0; \
+ offset: -4 -6; \
+ } \
+ } \
+ } \
+ part { \
+ name: "key-lbl-"key_name; \
+ type: TEXT; \
+ mouse_events: 0; \
+ effect: SHADOW BOTTOM; \
+ description { \
+ state: "default" 0.0; \
+ color: 63 67 72 255; \
+ color2: 240 240 240 255; \
+ color3: 240 240 240 255; \
+ rel1 { \
+ to: "key-bg-"key_name; \
+ relative: 0.0 0.4; \
+ } \
+ rel2 { \
+ to: "key-bg-"key_name; \
+ relative: 1.0 0.9; \
+ } \
+ text { \
+ font: "DroidSans"; \
+ size: (40*SCALE); \
+ text: key_low; \
+ } \
+ } \
+ } \
+ part { \
+ name: "key-lbl-alt-"key_name; \
+ type: TEXT; \
+ mouse_events: 0; \
+ effect: SHADOW BOTTOM; \
+ description { \
+ state: "default" 0.0; \
+ color: 63 67 72 255; \
+ color2: 240 240 240 255; \
+ color3: 240 240 240 255; \
+ rel1 { \
+ to: "key-bg-"key_name; \
+ relative: 0.0 0.1; \
+ } \
+ rel2 { \
+ to: "key-bg-"key_name; \
+ relative: 1.0 0.4; \
+ } \
+ text { \
+ font: "DroidSans"; \
+ size: (20*SCALE); \
+ align: 0.8 0.0; \
+ text: key_alt; \
+ } \
+ } \
+ } \
+ part { \
+ name: "key-img-hint-"key_name; \
+ type: IMAGE; \
+ mouse_events: 0; \
+ description { \
+ state: "default" 0.0; \
+ min: KEY_WIDTH KEY_HEIGHT; \
+ max: KEY_WIDTH KEY_HEIGHT; \
+ fixed: 1 1; \
+ rel1 { \
+ to: "key-img-"key_name; \
+ relative: 0.0 0.0; \
+ offset: 0 ((-20*SCALE)-KEY_HEIGHT); \
+ } \
+ rel2 { \
+ to: "key-img-"key_name; \
+ relative: 1.0 0.0; \
+ offset: 0 (-20*SCALE); \
+ } \
+ image { \
+ normal: "key-hint.png"; \
+ border: 8 8 10 10; \
+ } \
+ visible: 0; \
+ } \
+ description { \
+ state: "down" 0.0; \
+ inherit: "default" 0.0; \
+ visible: 1; \
+ } \
+ } \
+ part { \
+ name: "key-lbl-hint-"key_name; \
+ type: TEXT; \
+ mouse_events: 0; \
+ effect: SHADOW BOTTOM; \
+ description { \
+ state: "default" 0.0; \
+ color: 63 67 72 255; \
+ color2: 240 240 240 255; \
+ color3: 240 240 240 255; \
+ rel1 { \
+ to: "key-img-hint-"key_name; \
+ relative: 0.0 0.0; \
+ } \
+ rel2 { \
+ to: "key-img-hint-"key_name; \
+ relative: 1.0 1.0; \
+ } \
+ text { \
+ font: "DroidSans"; \
+ size: (44*SCALE); \
+ text: key_low; \
+ } \
+ visible: 0; \
+ } \
+ description { \
+ state: "down" 0.0; \
+ inherit: "default" 0.0; \
+ visible: 1; \
+ } \
+ } \
+ programs { \
+ program { \
+ name: "key-mouse-in-"key_name; \
+ signal: "mouse,in"; \
+ source: "key-bg-"key_name; \
+ script { \
+ if (get_int(mouse_down) == 0) \
+ return; \
+ _set_key_pressed(key_name); \
+ } \
+ } \
+ program { \
+ name: "key-mouse-out-"key_name; \
+ signal: "mouse,out"; \
+ source: "key-bg-"key_name; \
+ script { \
+ if (get_int(mouse_down) == 0) \
+ return; \
+ _set_key_released(key_name); \
+ } \
+ } \
+ program { \
+ name: "key-mouse-down-"key_name; \
+ signal: "mouse,down,1"; \
+ source: "key-bg-"key_name; \
+ script { \
+ _set_key_pressed(key_name); \
+ } \
+ } \
+ program { \
+ name: "key-mouse-up-"key_name; \
+ signal: "mouse,up,1"; \
+ source: "key-bg-"key_name; \
+ script { \
+ if (get_int(long_press) == 0) { \
+ if (get_int(shift_pressed) == 0) \
+ emit("key_down", key_low); \
+ else \
+ emit("key_down", key_up); \
+ } else { \
+ if (strcmp(key_alt, " ")) \
+ emit("key_down", key_alt); \
+ else if (get_int(shift_pressed) == 0) \
+ emit("key_down", key_low); \
+ else \
+ emit("key_down", key_up); \
+ } \
+ _set_key_released(key_name); \
+ } \
+ } \
+ program { \
+ name: "key-press-"key_name; \
+ action: STATE_SET "down" 0.0; \
+ target: "key-img-"key_name; \
+ target: "key-img-hint-"key_name; \
+ target: "key-lbl-hint-"key_name; \
+ } \
+ program { \
+ name: "key-release-"key_name; \
+ action: STATE_SET "default" 0.0; \
+ transition: LINEAR 0.2; \
+ target: "key-img-"key_name; \
+ target: "key-img-hint-"key_name; \
+ target: "key-lbl-hint-"key_name; \
+ after: "shift-pressed-"key_name; \
+ } \
+ program { \
+ name: "long-press-"key_name; \
+ signal: "long_press"; \
+ source: key_name; \
+ script { \
+ if (strcmp(key_alt, " ")) \
+ set_text(PART:"key-lbl-hint-"key_name, key_alt); \
+ } \
+ } \
+ program { \
+ name: "shift-pressed-"key_name; \
+ signal: "key_down"; \
+ source: "shift"; \
+ script { \
+ if (get_int(shift_pressed) == 0) { \
+ set_text(PART:"key-lbl-"key_name, key_low); \
+ set_text(PART:"key-lbl-hint-"key_name, key_low); \
+ } else { \
+ set_text(PART:"key-lbl-"key_name, key_up); \
+ set_text(PART:"key-lbl-hint-"key_name, key_up); \
+ } \
+ } \
+ } \
+ }
+#define KEY_FULL(low, up, alt, x, y) SKEY_FULL(low, up, low, alt, x, y)
+#define SKEY(name, text, alt, x, y) SKEY_FULL(name, name, text, alt, x, y)
+#define KEY(v, alt, x, y) SKEY(v, v, alt, x, y)
+
+ KEY_FULL("q", "Q", "1", KEY_OFFSET(0), FIRST_ROW)
+ KEY_FULL("w", "W", "2", KEY_OFFSET(1), FIRST_ROW)
+ KEY_FULL("e", "E", "3", KEY_OFFSET(2), FIRST_ROW)
+ KEY_FULL("r", "R", "4", KEY_OFFSET(3), FIRST_ROW)
+ KEY_FULL("t", "T", "5", KEY_OFFSET(4), FIRST_ROW)
+ KEY_FULL("y", "Y", "6", KEY_OFFSET(5), FIRST_ROW)
+ KEY_FULL("u", "U", "7", KEY_OFFSET(6), FIRST_ROW)
+ KEY_FULL("i", "I", "8", KEY_OFFSET(7), FIRST_ROW)
+ KEY_FULL("o", "O", "9", KEY_OFFSET(8), FIRST_ROW)
+ KEY_FULL("p", "P", "0", KEY_OFFSET(9), FIRST_ROW)
+
+#undef INIT_HSPACE
+#define INIT_HSPACE (45*SCALE)
+#define SECOND_ROW FIRST_ROW+KEY_HEIGHT+ROW_SPACE
+
+ KEY_FULL("a", "A", "-", KEY_OFFSET(0), SECOND_ROW)
+ KEY_FULL("s", "S", "@", KEY_OFFSET(1), SECOND_ROW)
+ KEY_FULL("d", "D", "*", KEY_OFFSET(2), SECOND_ROW)
+ KEY_FULL("f", "F", "^", KEY_OFFSET(3), SECOND_ROW)
+ KEY_FULL("g", "G", ":", KEY_OFFSET(4), SECOND_ROW)
+ KEY_FULL("h", "H", ";", KEY_OFFSET(5), SECOND_ROW)
+ KEY_FULL("j", "J", "(", KEY_OFFSET(6), SECOND_ROW)
+ KEY_FULL("k", "K", ")", KEY_OFFSET(7), SECOND_ROW)
+ KEY_FULL("l", "L", "~", KEY_OFFSET(8), SECOND_ROW)
+
+#undef INIT_HSPACE
+#define INIT_HSPACE (110*SCALE)
+#define THIRD_ROW SECOND_ROW+KEY_HEIGHT+ROW_SPACE
+
+ KEY_FULL("z", "Z", "/", KEY_OFFSET(0), THIRD_ROW)
+ KEY_FULL("x", "X", "'", KEY_OFFSET(1), THIRD_ROW)
+ KEY_FULL("c", "C", "\"", KEY_OFFSET(2), THIRD_ROW)
+ KEY_FULL("v", "V", ".", KEY_OFFSET(3), THIRD_ROW)
+ KEY_FULL("b", "B", ",", KEY_OFFSET(4), THIRD_ROW)
+ KEY_FULL("n", "N", "?", KEY_OFFSET(5), THIRD_ROW)
+ KEY_FULL("m", "M", "!", KEY_OFFSET(6), THIRD_ROW)
+
+#define KEY_SPECIAL(val, x, y, w) \
+ part { \
+ name: "key-img-"val; \
+ type: IMAGE; \
+ mouse_events: 0; \
+ description { \
+ state: "default" 0.0; \
+ min: w KEY_HEIGHT; \
+ max: w KEY_HEIGHT; \
+ fixed: 1 1; \
+ rel1 { \
+ relative: 0.0 0.0; \
+ offset: (x) (y); \
+ } \
+ rel2 { \
+ relative: 0.0 0.0; \
+ offset: (x+w-1) (y+KEY_HEIGHT-1); \
+ } \
+ image { \
+ normal: "key-special.png"; \
+ border: 8 8 10 10; \
+ } \
+ } \
+ description { \
+ state: "down" 0.0; \
+ inherit: "default" 0.0; \
+ rel1.offset: (x+1) (y+1); \
+ rel2.offset: (x+1+w-1) (y+1+KEY_HEIGHT-1); \
+ image.normal: "key-special-pressed.png"; \
+ } \
+ } \
+ part { \
+ name: "key-bg-"val; \
+ type: RECT; \
+ pointer_mode: NOGRAB; \
+ description { \
+ state: "default" 0.0; \
+ rel1 { \
+ to: "key-img-"val; \
+ relative: 0.0 0.0; \
+ offset: 3 2; \
+ } \
+ rel2 { \
+ to: "key-img-"val; \
+ relative: 1.0 1.0; \
+ offset: -4 -6; \
+ } \
+ color: 0 0 0 0; \
+ } \
+ } \
+ programs { \
+ program { \
+ name: "key-down-"val; \
+ signal: "mouse,up,1"; \
+ source: "key-bg-"val; \
+ script { \
+ emit("key_down", val); \
+ run_program(PROGRAM:"key-release-"val); \
+ } \
+ } \
+ program { \
+ name: "key-mouse-in-"val; \
+ signal: "mouse,in"; \
+ source: "key-bg-"val; \
+ script { \
+ if (get_int(mouse_down) == 0) \
+ return; \
+ run_program(PROGRAM:"key-press-"val); \
+ } \
+ } \
+ program { \
+ name: "key-mouse-out-"val; \
+ signal: "mouse,out"; \
+ source: "key-bg-"val; \
+ script { \
+ if (get_int(mouse_down) == 0) \
+ return; \
+ run_program(PROGRAM:"key-release-"val); \
+ } \
+ } \
+ program { \
+ name: "key-press-"val; \
+ signal: "mouse,down,1"; \
+ source: "key-bg-"val; \
+ action: STATE_SET "down" 0.0; \
+ target: "key-img-"val; \
+ target: "key-lbl-"val; \
+ } \
+ program { \
+ name: "key-release-"val; \
+ action: STATE_SET "default" 0.0; \
+ transition: LINEAR 0.2; \
+ target: "key-img-"val; \
+ target: "key-lbl-"val; \
+ } \
+ }
+
+#define KEY_SPECIAL_TEXT(val, x, y, w) \
+ KEY_SPECIAL(val, x, y, w) \
+ part { \
+ name: "key-lbl-"val; \
+ type: TEXT; \
+ mouse_events: 0; \
+ effect: SHADOW BOTTOM; \
+ description { \
+ state: "default" 0.0; \
+ color: 63 67 72 255; \
+ color2: 240 240 240 255; \
+ color3: 240 240 240 255; \
+ rel1 { \
+ to: "key-bg-"val; \
+ relative: 0.0 0.4; \
+ } \
+ rel2 { \
+ to: "key-bg-"val; \
+ relative: 1.0 1.0; \
+ } \
+ text { \
+ font: "DroidSans"; \
+ size: (28*SCALE); \
+ text: val; \
+ } \
+ } \
+ }
+
+#define KEY_SPECIAL_ICON(val, x, y, w, icon_size) \
+ KEY_SPECIAL(val, x, y, w) \
+ part { \
+ name: "key-lbl-"val; \
+ type: IMAGE; \
+ mouse_events: 0; \
+ description { \
+ state: "default" 0.0; \
+ min: icon_size icon_size; \
+ max: icon_size icon_size; \
+ fixed: 1 1; \
+ rel1 { \
+ to: "key-bg-"val; \
+ relative: 0.5 0.4; \
+ } \
+ rel2 { \
+ to: "key-bg-"val; \
+ relative: 0.5 0.8; \
+ } \
+ image.normal: "icon-"val".png"; \
+ } \
+ } \
+
+#define FOURTH_ROW THIRD_ROW+KEY_HEIGHT+ROW_SPACE
+ KEY_SPECIAL_TEXT("?123", (5*SCALE), FOURTH_ROW, (95*SCALE))
+
+ part {
+ name: "key-img-shift";
+ type: IMAGE;
+ mouse_events: 0;
+ description {
+ state: "default" 0.0;
+ min: (85*SCALE) KEY_HEIGHT;
+ max: (85*SCALE) KEY_HEIGHT;
+ fixed: 1 1;
+ rel1 {
+ relative: 0.0 0.0;
+ offset: (5*SCALE) (THIRD_ROW);
+ }
+ rel2 {
+ relative: 0.0 0.0;
+ offset: (((5+85)*SCALE)-1) (THIRD_ROW+KEY_HEIGHT-1);
+ }
+ image {
+ normal: "key-special.png";
+ border: 8 8 10 10;
+ }
+ }
+ description {
+ state: "down" 0.0;
+ inherit: "default" 0.0;
+ rel1.offset: ((5*SCALE)+2) (THIRD_ROW+2);
+ rel2.offset: ((((5+85)*SCALE)+2)-1) (THIRD_ROW+2+KEY_HEIGHT-1);
+ image.normal: "key-special-pressed.png";
+ }
+ }
+ part {
+ name: "key-bg-shift";
+ type: RECT;
+ pointer_mode: NOGRAB;
+ description {
+ state: "default" 0.0;
+ rel1 {
+ to: "key-img-shift";
+ relative: 0.0 0.0;
+ offset: 3 2;
+ }
+ rel2 {
+ to: "key-img-shift";
+ relative: 1.0 1.0;
+ offset: -4 -6;
+ }
+ color: 0 0 0 0;
+ }
+ }
+ part {
+ name: "key-lbl-shift";
+ type: IMAGE;
+ mouse_events: 0;
+ description {
+ state: "default" 0.0;
+ max: (50*SCALE) (50*SCALE);
+ min: (50*SCALE) (50*SCALE);
+ fixed: 1 1;
+ rel1 {
+ to: "key-bg-shift";
+ relative: 0.5 0.4;
+ }
+ rel2 {
+ to: "key-bg-shift";
+ relative: 0.5 0.8;
+ }
+ image.normal: "icon-shift.png";
+ }
+ description {
+ state: "down" 0.0;
+ inherit: "default" 0.0;
+ image.normal: "icon-shift-active.png";
+ }
+ }
+ programs {
+ program {
+ name: "key-press-shift";
+ signal: "mouse,down,1";
+ source: "key-bg-shift";
+ action: STATE_SET "down" 0.0;
+ target: "key-img-shift";
+ target: "key-lbl-shift";
+ }
+ program {
+ name: "key-release-shift";
+ action: STATE_SET "default" 0.0;
+ transition: LINEAR 0.2;
+ target: "key-img-shift";
+ target: "key-lbl-shift";
+ }
+ program {
+ name: "key-mouse-in-shift";
+ signal: "mouse,in";
+ source: "key-bg-shift";
+ script {
+ if (get_int(mouse_down) == 0)
+ return;
+ run_program(PROGRAM:"key-press-shift");
+ }
+ }
+ program {
+ name: "key-mouse-out-shift";
+ signal: "mouse,out";
+ source: "key-bg-shift";
+ script {
+ if (get_int(mouse_down) == 0)
+ return;
+ run_program(PROGRAM:"key-release-shift");
+ }
+ }
+ program {
+ name: "key-down-shift";
+ signal: "mouse,up,1";
+ source: "key-bg-shift";
+ script {
+ emit("key_down", "shift");
+ if (get_int(shift_pressed) == 0) {
+ run_program(PROGRAM:"key-press-shift");
+ set_int(shift_pressed, 1);
+ } else {
+ run_program(PROGRAM:"key-release-shift");
+ set_int(shift_pressed, 0);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ group {
+ name: "special-1";
+
+ MOUSE_DOWN_UP_PROGRAMS
+ parts {
+#undef INIT_HSPACE
+#define INIT_HSPACE 5
+
+ KEY("1", "#", KEY_OFFSET(0), FIRST_ROW)
+ KEY("2", "&", KEY_OFFSET(1), FIRST_ROW)
+ KEY("3", "%", KEY_OFFSET(2), FIRST_ROW)
+ KEY("4", "+", KEY_OFFSET(3), FIRST_ROW)
+ KEY("5", "=", KEY_OFFSET(4), FIRST_ROW)
+ KEY("6", "_", KEY_OFFSET(5), FIRST_ROW)
+ KEY("7", "\\", KEY_OFFSET(6), FIRST_ROW)
+ KEY("8", "|", KEY_OFFSET(7), FIRST_ROW)
+ KEY("9", "<", KEY_OFFSET(8), FIRST_ROW)
+ KEY("0", ">", KEY_OFFSET(9), FIRST_ROW)
+
+#undef INIT_HSPACE
+#define INIT_HSPACE (45*SCALE)
+
+ SKEY("-", "dash", "{", KEY_OFFSET(0), SECOND_ROW)
+ SKEY("@", "at", "}", KEY_OFFSET(1), SECOND_ROW)
+ SKEY("*", "star", "[", KEY_OFFSET(2), SECOND_ROW)
+ SKEY("^", "circumflex", "]", KEY_OFFSET(3), SECOND_ROW)
+ SKEY(":", "colon", "$", KEY_OFFSET(4), SECOND_ROW)
+ SKEY(";", "semi_colon", "£", KEY_OFFSET(5), SECOND_ROW)
+ SKEY("(", "open_par", "¥", KEY_OFFSET(6), SECOND_ROW)
+ SKEY(")", "close_par", "€", KEY_OFFSET(7), SECOND_ROW)
+ SKEY("~", "tilde", "₩", KEY_OFFSET(8), SECOND_ROW)
+
+#undef INIT_HSPACE
+#define INIT_HSPACE (110*SCALE)
+
+ SKEY("/", "slash", "¢", KEY_OFFSET(0), THIRD_ROW)
+ SKEY("'", "single_quote", "`", KEY_OFFSET(1), THIRD_ROW)
+ SKEY("\"", "double_quote", "°", KEY_OFFSET(2), THIRD_ROW)
+ SKEY(".", "dot", "˙", KEY_OFFSET(3), THIRD_ROW)
+ SKEY(",", "comma", "®", KEY_OFFSET(4), THIRD_ROW)
+ SKEY("?", "question", "©", KEY_OFFSET(5), THIRD_ROW)
+ SKEY("!", "exclamation", "¿", KEY_OFFSET(6), THIRD_ROW)
+
+ KEY_SPECIAL_TEXT("1/2", (5*SCALE), THIRD_ROW, (85*SCALE))
+ KEY_SPECIAL_TEXT("abc", (5*SCALE), FOURTH_ROW, (95*SCALE))
+ }
+ }
+
+ group {
+ name: "special-2";
+
+ MOUSE_DOWN_UP_PROGRAMS
+ parts {
+#undef INIT_HSPACE
+#define INIT_HSPACE 5
+
+ SKEY("#", "hash", "1", KEY_OFFSET(0), FIRST_ROW)
+ SKEY("&", "amp", "2", KEY_OFFSET(1), FIRST_ROW)
+ SKEY("%", "percent", "3", KEY_OFFSET(2), FIRST_ROW)
+ SKEY("+", "plus", "4", KEY_OFFSET(3), FIRST_ROW)
+ SKEY("=", "equal", "5", KEY_OFFSET(4), FIRST_ROW)
+ SKEY("_", "underline", "6", KEY_OFFSET(5), FIRST_ROW)
+ SKEY("\\", "backslash", "7", KEY_OFFSET(6), FIRST_ROW)
+ SKEY("|", "vert_bar", "8", KEY_OFFSET(7), FIRST_ROW)
+ SKEY("<", "less", "9", KEY_OFFSET(8), FIRST_ROW)
+ SKEY(">", "greater", "0", KEY_OFFSET(9), FIRST_ROW)
+
+#undef INIT_HSPACE
+#define INIT_HSPACE (45*SCALE)
+
+ SKEY("{", "open_brace", "-", KEY_OFFSET(0), SECOND_ROW)
+ SKEY("}", "close_brace", "@", KEY_OFFSET(1), SECOND_ROW)
+ SKEY("[", "open_bracket", "*", KEY_OFFSET(2), SECOND_ROW)
+ SKEY("]", "close_bracket", "^", KEY_OFFSET(3), SECOND_ROW)
+ SKEY("$", "dollar", ":", KEY_OFFSET(4), SECOND_ROW)
+ SKEY("£", "pound", ";", KEY_OFFSET(5), SECOND_ROW)
+ SKEY("¥", "yen", "(", KEY_OFFSET(6), SECOND_ROW)
+ SKEY("€", "euro", ")", KEY_OFFSET(7), SECOND_ROW)
+ SKEY("₩", "won", "~", KEY_OFFSET(8), SECOND_ROW)
+
+#undef INIT_HSPACE
+#define INIT_HSPACE (110*SCALE)
+
+ SKEY("¢", "cent" , "/", KEY_OFFSET(0), THIRD_ROW)
+ SKEY("`", "back_quote", "'", KEY_OFFSET(1), THIRD_ROW)
+ SKEY("°", "ring", "\"", KEY_OFFSET(2), THIRD_ROW)
+ SKEY("˙", "dot", ".", KEY_OFFSET(3), THIRD_ROW)
+ SKEY("®", "registered", ",", KEY_OFFSET(4), THIRD_ROW)
+ SKEY("©", "copyright", "?", KEY_OFFSET(5), THIRD_ROW)
+ SKEY("¿", "inv_question", "!", KEY_OFFSET(6), THIRD_ROW)
+
+ KEY_SPECIAL_TEXT("2/2", (5*SCALE), THIRD_ROW, (85*SCALE))
+ KEY_SPECIAL_TEXT("abc", (5*SCALE), FOURTH_ROW, (95*SCALE))
+ }
+ }
+
+ group {
+ name: "fixed";
+
+ script {
+ public mouse_down = 0;
+ }
+
+ programs {
+ program {
+ name: "mouse-down";
+ signal: "mouse,down,1";
+ source: "*";
+ script {
+ set_int(mouse_down, 1);
+ }
+ }
+ program {
+ name: "mouse-up";
+ signal: "mouse,up,1";
+ source: "*";
+ script {
+ set_int(mouse_down, 0);
+ }
+ }
+ }
+
+ parts {
+ KEY_SPECIAL_ICON("backspace", (620*SCALE), THIRD_ROW, (85*SCALE), (60*SCALE))
+ KEY_SPECIAL_ICON("enter", (610*SCALE), FOURTH_ROW, (95*SCALE), (60*SCALE))
+
+#undef INIT_HSPACE
+#define INIT_HSPACE (120*SCALE)
+ /*KEY_SPECIAL_ICON("space", (KEY_OFFSET(0)), FOURTH_ROW, (KEY_OFFSET(5)), 82);*/
+ KEY_SPECIAL_ICON("space", KEY_OFFSET(0), FOURTH_ROW, KEY_OFFSET(5), (64*SCALE));
+ }
+ }
+
+ group {
+ name: "numeric";
+ MOUSE_DOWN_UP_PROGRAMS
+
+ parts {
+#undef KEY_WIDTH
+#define KEY_WIDTH (200*SCALE)
+#undef KEY_HEIGHT
+#define KEY_HEIGHT NUMERIC_KEY_HEIGHT
+#undef INIT_HSPACE
+#define INIT_HSPACE (45*SCALE)
+#undef ROW_SPACE
+#define ROW_SPACE (10*SCALE)
+#undef COL_SPACE
+#define COL_SPACE (10*SCALE)
+ KEY("1", " ", KEY_OFFSET(0), FIRST_ROW)
+ KEY("2", " ", KEY_OFFSET(1), FIRST_ROW)
+ KEY("3", " ", KEY_OFFSET(2), FIRST_ROW)
+
+ KEY("4", " ", KEY_OFFSET(0), SECOND_ROW)
+ KEY("5", " ", KEY_OFFSET(1), SECOND_ROW)
+ KEY("6", " ", KEY_OFFSET(2), SECOND_ROW)
+
+ KEY("7", " ", KEY_OFFSET(0), THIRD_ROW)
+ KEY("8", " ", KEY_OFFSET(1), THIRD_ROW)
+ KEY("9", " ", KEY_OFFSET(2), THIRD_ROW)
+
+ KEY_SPECIAL_ICON("backspace", KEY_OFFSET(0), FOURTH_ROW, KEY_WIDTH, (50*SCALE))
+ KEY("0", " ", KEY_OFFSET(1), FOURTH_ROW)
+ KEY_SPECIAL_ICON("enter", KEY_OFFSET(2), FOURTH_ROW, KEY_WIDTH, (60*SCALE))
+
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define SCALE 0.83
+
+#define MIN_WIDTH 600
+#define MAX_WIDTH 1024
+#define MIN_HEIGHT 480
+#define MAX_HEIGHT 480
+
+#define NUMERIC_KEY_HEIGHT 80
+
+#include "default.edc"
--- /dev/null
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define SCALE 1.0
+
+#define MIN_WIDTH 720
+#define MAX_WIDTH 1280
+#define MIN_HEIGHT 600
+#define MAX_HEIGHT 600
+
+#define NUMERIC_KEY_HEIGHT 100
+
+#include "default.edc"
--- /dev/null
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
--- /dev/null
+shift
+abc
+?123
+1/2
+2/2
--- /dev/null
+EXTRA_DIST = \
+ input-method.xml \
+ text.xml
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="input_method">
+ <copyright>
+ Copyright © 2012, 2013 Intel Corporation
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that copyright notice and this permission
+ notice appear in supporting documentation, and that the name of
+ the copyright holders not be used in advertising or publicity
+ pertaining to distribution of the software without specific,
+ written prior permission. The copyright holders make no
+ representations about the suitability of this software for any
+ purpose. It is provided "as is" without express or implied
+ warranty.
+
+ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ THIS SOFTWARE.
+ </copyright>
+
+
+ <interface name="wl_input_method_context" version="1">
+ <description summary="input method context">
+ Corresponds to a text model on input method side. An input method context
+ is created on text mode activation on the input method side. It allows to
+ receive information about the text model from the application via events.
+ Input method contexts do not keep state after deactivation and should be
+ destroyed after deactivation is handled.
+
+ Text is generally UTF-8 encoded, indices and lengths are in bytes.
+
+ Serials are used to synchronize the state between the text input and
+ an input method. New serials are sent by the text input in the
+ commit_state request and are used by the input method to indicate
+ the known text input state in events like preedit_string, commit_string,
+ and keysym. The text input can then ignore events from the input method
+ which are based on an outdated state (for example after a reset).
+ </description>
+ <request name="destroy" type="destructor"/>
+ <request name="commit_string">
+ <description summary="commit string">
+ Send the commit string text for insertion to the application.
+
+ The text to commit could be either just a single character after a key
+ press or the result of some composing (pre-edit). It could be also an
+ empty text when some text should be removed (see
+ delete_surrounding_text) or when the input cursor should be moved (see
+ cursor_position).
+
+ Any previously set composing text will be removed.
+ </description>
+ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
+ <arg name="text" type="string"/>
+ </request>
+ <request name="preedit_string">
+ <description summary="pre-edit string">
+ Send the pre-edit string text to the application text input.
+
+ The commit text can be used to replace the preedit text on reset (for
+ example on unfocus).
+
+ Also previously sent preedit_style and preedit_cursor requests are
+ processed bt the text_input also.
+ </description>
+ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
+ <arg name="text" type="string"/>
+ <arg name="commit" type="string"/>
+ </request>
+ <request name="preedit_styling">
+ <description summary="pre-edit styling">
+ Sets styling information on composing text. The style is applied for
+ length in bytes from index relative to the beginning of
+ the composing text (as byte offset). Multiple styles can
+ be applied to a composing text.
+
+ This request should be sent before sending preedit_string request.
+ </description>
+ <arg name="index" type="uint"/>
+ <arg name="length" type="uint"/>
+ <arg name="style" type="uint"/>
+ </request>
+ <request name="preedit_cursor">
+ <description summary="pre-edit cursor">
+ Sets the cursor position inside the composing text (as byte offset)
+ relative to the start of the composing text.
+
+ When index is negative no cursor should be displayed.
+
+ This request should be sent before sending preedit_string request.
+ </description>
+ <arg name="index" type="int"/>
+ </request>
+ <request name="delete_surrounding_text">
+ <description summary="delete text">
+
+
+ This request will be handled on text_input side as part of a directly
+ following commit_string request.
+ </description>
+ <arg name="index" type="int"/>
+ <arg name="length" type="uint"/>
+ </request>
+ <request name="cursor_position">
+ <description summary="set cursor to a new position">
+ Sets the cursor and anchor to a new position. Index is the new cursor
+ position in bytess (when >= 0 relative to the end of inserted text
+ else relative to beginning of inserted text). Anchor is the new anchor
+ position in bytes (when >= 0 relative to the end of inserted text, else
+ relative to beginning of inserted text). When there should be no
+ selected text anchor should be the same as index.
+
+ This request will be handled on text_input side as part of a directly
+ following commit_string request.
+ </description>
+ <arg name="index" type="int"/>
+ <arg name="anchor" type="int"/>
+ </request>
+ <request name="modifiers_map">
+ <arg name="map" type="array"/>
+ </request>
+ <request name="keysym">
+ <description summary="keysym">
+ Notify when a key event was sent. Key events should not be used for
+ normal text input operations, which should be done with commit_string,
+ delete_surrounfing_text, etc. The key event follows the wl_keyboard key
+ event convention. Sym is a XKB keysym, state a wl_keyboard key_state.
+ </description>
+ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
+ <arg name="time" type="uint"/>
+ <arg name="sym" type="uint"/>
+ <arg name="state" type="uint"/>
+ <arg name="modifiers" type="uint"/>
+ </request>
+ <request name="grab_keyboard">
+ <description summary="grab hardware keyboard">
+ Allows an input method to receive hardware keyboard input and process
+ key events to generate text events (with pre-edit) over the wire. This
+ allows input methods which compose multiple key events for inputting
+ text like it is done for CJK languages.
+ </description>
+ <arg name="keyboard" type="new_id" interface="wl_keyboard"/>
+ </request>
+ <request name="key">
+ <description summary="forward key event">
+ Should be used when filtering key events with grab_keyboard.
+
+ When the wl_keyboard::key event is not processed by the input
+ method itself and should be sent to the client instead, forward it
+ with this request. The arguments should be the ones from the
+ wl_keyboard::key event.
+
+ For generating custom key events use the keysym request instead.
+ </description>
+ <arg name="serial" type="uint" summary="serial from wl_keyboard::key"/>
+ <arg name="time" type="uint" summary="time from wl_keyboard::key"/>
+ <arg name="key" type="uint" summary="key from wl_keyboard::key"/>
+ <arg name="state" type="uint" summary="state from wl_keyboard::key"/>
+ </request>
+ <request name="modifiers">
+ <description summary="forward modifiers event">
+ Should be used when filtering key events with grab_keyboard.
+
+ When the wl_keyboard::modifiers event should be also send to the
+ client, forward it with this request. The arguments should be the ones
+ from the wl_keyboard::modifiers event.
+ </description>
+ <arg name="serial" type="uint" summary="serial from wl_keyboard::modifiers"/>
+ <arg name="mods_depressed" type="uint" summary="mods_depressed from wl_keyboard::modifiers"/>
+ <arg name="mods_latched" type="uint" summary="mods_latched from wl_keyboard::modifiers"/>
+ <arg name="mods_locked" type="uint" summary="mods_locked from wl_keyboard::modifiers"/>
+ <arg name="group" type="uint" summary="group from wl_keyboard::modifiers"/>
+ </request>
+ <request name="language">
+ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
+ <arg name="language" type="string"/>
+ </request>
+ <request name="text_direction">
+ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
+ <arg name="direction" type="uint"/>
+ </request>
+ <event name="surrounding_text">
+ <description summary="surrounding text event">
+ The plain surrounding text around the input position. Cursor is the
+ position in bytes within the surrounding text relative to the beginning
+ of the text. Anchor is the position in bytes of the selection anchor
+ within the surrounding text relative to the beginning of the text. If
+ there is no selected text anchor is the same as cursor.
+ </description>
+ <arg name="text" type="string"/>
+ <arg name="cursor" type="uint"/>
+ <arg name="anchor" type="uint"/>
+ </event>
+ <event name="reset">
+ </event>
+ <event name="content_type">
+ <arg name="hint" type="uint"/>
+ <arg name="purpose" type="uint"/>
+ </event>
+ <event name="invoke_action">
+ <arg name="button" type="uint"/>
+ <arg name="index" type="uint"/>
+ </event>
+ <event name="commit_state">
+ <arg name="serial" type="uint" summary="serial of text input state"/>
+ </event>
+ <event name="preferred_language">
+ <arg name="language" type="string"/>
+ </event>
+ </interface>
+
+ <interface name="wl_input_method" version="1">
+ <description summary="input method">
+ An input method object is responsible to compose text in response to
+ input from hardware or virtual keyboards. There is one input method
+ object per seat. On activate there is a new input method context object
+ created which allows the input method to communicate with the text model.
+ </description>
+ <event name="activate">
+ <description summary="activate event">
+ A text model was activated. Creates an input method context object
+ which allows communication with the text model.
+ </description>
+ <arg name="id" type="new_id" interface="wl_input_method_context"/>
+ </event>
+ <event name="deactivate">
+ <description summary="activate event">
+ The text model corresponding to the context argument was deactivated.
+ The input method context should be destroyed after deactivation is
+ handled.
+ </description>
+ <arg name="context" type="object" interface="wl_input_method_context"/>
+ </event>
+ </interface>
+
+ <interface name="wl_input_panel" version="1">
+ <description summary="interface for implementing keyboards">
+ Only one client can bind this interface at a time.
+ </description>
+
+ <request name="get_input_panel_surface">
+ <arg name="id" type="new_id" interface="wl_input_panel_surface"/>
+ <arg name="surface" type="object" interface="wl_surface"/>
+ </request>
+ </interface>
+
+ <interface name="wl_input_panel_surface" version="1">
+ <enum name="position">
+ <entry name="center_bottom" value="0"/>
+ </enum>
+
+ <request name="set_toplevel">
+ <description summary="set the surface type as a keyboard">
+ A keybaord surface is only shown, when a text model is active
+ </description>
+ <arg name="output" type="object" interface="wl_output"/>
+ <arg name="position" type="uint"/>
+ </request>
+
+ <request name="set_overlay_panel">
+ <description summary="set the surface type as an overlay panel">
+ An overlay panel is shown near the input cursor above the application
+ window hwne a text model is active.
+ </description>
+ </request>
+
+ <event name="cursor_rectangle">
+ <description summary="cursor rectangle">
+ Notify when the cursor rectangle relative to the input panel surface change.
+ </description>
+ <arg name="x" type="int"/>
+ <arg name="y" type="int"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ </event>
+ </interface>
+</protocol>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="text">
+
+ <copyright>
+ Copyright © 2012, 2013 Intel Corporation
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that copyright notice and this permission
+ notice appear in supporting documentation, and that the name of
+ the copyright holders not be used in advertising or publicity
+ pertaining to distribution of the software without specific,
+ written prior permission. The copyright holders make no
+ representations about the suitability of this software for any
+ purpose. It is provided "as is" without express or implied
+ warranty.
+
+ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ THIS SOFTWARE.
+ </copyright>
+
+ <interface name="wl_text_input" version="1">
+ <description summary="text input">
+ An object used for text input. Adds support for text input and input
+ methods to applications. A text-input object is created from a
+ wl_text_input_manager and corresponds typically to a text entry in an
+ application.
+ Requests are used to activate/deactivate the text-input object and set
+ state information like surrounding and selected text or the content type.
+ The information about entered text is sent to the text-input object via
+ the pre-edit and commit events. Using this interface removes the need
+ for applications to directly process hardware key events and compose text
+ out of them.
+
+ Text is generally UTF-8 encoded, indices and lengths are in bytes.
+
+ Serials are used to synchronize the state between the text input and
+ an input method. New serials are sent by the text input in the
+ commit_state request and are used by the input method to indicate
+ the known text input state in events like preedit_string, commit_string,
+ and keysym. The text input can then ignore events from the input method
+ which are based on an outdated state (for example after a reset).
+ </description>
+ <request name="activate">
+ <description summary="request activation">
+ Requests the text-input object to be activated (typically when the
+ text entry gets focus).
+ The seat argument is a wl_seat which maintains the focus for this
+ activation. The surface argument is a wl_surface assigned to the
+ text-input object and tracked for focus lost. The enter event
+ is emitted on successful activation.
+ </description>
+ <arg name="seat" type="object" interface="wl_seat"/>
+ <arg name="surface" type="object" interface="wl_surface"/>
+ </request>
+ <request name="deactivate">
+ <description summary="request deactivation">
+ Requests the text-input object to be deactivated (typically when the
+ text entry lost focus). The seat argument is a wl_seat which was used
+ for activation.
+ </description>
+ <arg name="seat" type="object" interface="wl_seat"/>
+ </request>
+ <request name="show_input_panel">
+ <description summary="show input panels">
+ Requests input panels (virtual keyboard) to show.
+ </description>
+ </request>
+ <request name="hide_input_panel">
+ <description summary="hide input panels">
+ Requests input panels (virtual keyboard) to hide.
+ </description>
+ </request>
+ <request name="reset">
+ <description summary="reset">
+ Should be called by an editor widget when the input state should be
+ reset, for example after the text was changed outside of the normal
+ input method flow.
+ </description>
+ </request>
+ <request name="set_surrounding_text">
+ <description summary="sets the surrounding text">
+ Sets the plain surrounding text around the input position. Text is
+ UTF-8 encoded. Cursor is the byte offset within the
+ surrounding text. Anchor is the byte offset of the
+ selection anchor within the surrounding text. If there is no selected
+ text anchor is the same as cursor.
+ </description>
+ <arg name="text" type="string"/>
+ <arg name="cursor" type="uint"/>
+ <arg name="anchor" type="uint"/>
+ </request>
+ <enum name="content_hint">
+ <description summary="content hint">
+ Content hint is a bitmask to allow to modify the behavior of the text
+ input.
+ </description>
+ <entry name="none" value="0x0" summary="no special behaviour"/>
+ <entry name="default" value="0x7" summary="auto completion, correction and capitalization"/>
+ <entry name="password" value="0xc0" summary="hidden and sensitive text"/>
+ <entry name="auto_completion" value="0x1" summary="suggest word completions"/>
+ <entry name="auto_correction" value="0x2" summary="suggest word corrections"/>
+ <entry name="auto_capitalization" value="0x4" summary="switch to uppercase letters at the start of a sentence"/>
+ <entry name="lowercase" value="0x8" summary="prefer lowercase letters"/>
+ <entry name="uppercase" value="0x10" summary="prefer uppercase letters"/>
+ <entry name="titlecase" value="0x20" summary="prefer casing for titles and headings (can be language dependent)"/>
+ <entry name="hidden_text" value="0x40" summary="characters should be hidden"/>
+ <entry name="sensitive_data" value="0x80" summary="typed text should not be stored"/>
+ <entry name="latin" value="0x100" summary="just latin characters should be entered"/>
+ <entry name="multiline" value="0x200" summary="the text input is multiline"/>
+ </enum>
+ <enum name="content_purpose">
+ <description summary="content purpose">
+ The content purpose allows to specify the primary purpose of a text
+ input.
+
+ This allows an input method to show special purpose input panels with
+ extra characters or to disallow some characters.
+ </description>
+ <entry name="normal" value="0" summary="default input, allowing all characters"/>
+ <entry name="alpha" value="1" summary="allow only alphabetic characters"/>
+ <entry name="digits" value="2" summary="allow only digits"/>
+ <entry name="number" value="3" summary="input a number (including decimal separator and sign)"/>
+ <entry name="phone" value="4" summary="input a phone number"/>
+ <entry name="url" value="5" summary="input an URL"/>
+ <entry name="email" value="6" summary="input an email address"/>
+ <entry name="name" value="7" summary="input a name of a person"/>
+ <entry name="password" value="8" summary="input a password (combine with password or sensitive_data hint)"/>
+ <entry name="date" value="9" summary="input a date"/>
+ <entry name="time" value="10" summary="input a time"/>
+ <entry name="datetime" value="11" summary="input a date and time"/>
+ <entry name="terminal" value="12" summary="input for a terminal"/>
+ </enum>
+ <request name="set_content_type">
+ <description summary="set content purpose and hint">
+ Sets the content purpose and content hint. While the purpose is the
+ basic purpose of an input field, the hint flags allow to modify some
+ of the behavior.
+
+ When no content type is explicitly set, a normal content purpose with
+ default hints (auto completion, auto correction, auto capitalization)
+ should be assumed.
+ </description>
+ <arg name="hint" type="uint"/>
+ <arg name="purpose" type="uint"/>
+ </request>
+ <request name="set_cursor_rectangle">
+ <arg name="x" type="int"/>
+ <arg name="y" type="int"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ </request>
+ <request name="set_preferred_language">
+ <description summary="sets preferred language">
+ Sets a specific language. This allows for example a virtual keyboard to
+ show a language specific layout. The "language" argument is a RFC-3066
+ format language tag.
+
+ It could be used for example in a word processor to indicate language of
+ currently edited document or in an instant message application which tracks
+ languages of contacts.
+ </description>
+ <arg name="language" type="string"/>
+ </request>
+ <request name="commit_state">
+ <arg name="serial" type="uint" summary="used to identify the known state"/>
+ </request>
+ <request name="invoke_action">
+ <arg name="button" type="uint"/>
+ <arg name="index" type="uint"/>
+ </request>
+ <event name="enter">
+ <description summary="enter event">
+ Notify the text-input object when it received focus. Typically in
+ response to an activate request.
+ </description>
+ <arg name="surface" type="object" interface="wl_surface"/>
+ </event>
+ <event name="leave">
+ <description summary="leave event">
+ Notify the text-input object when it lost focus. Either in response
+ to a deactivate request or when the assigned surface lost focus or was
+ destroyed.
+ </description>
+ </event>
+ <event name="modifiers_map">
+ <description summary="modifiers map">
+ Transfer an array of 0-terminated modifiers names. The position in
+ the array is the index of the modifier as used in the modifiers
+ bitmask in the keysym event.
+ </description>
+ <arg name="map" type="array"/>
+ </event>
+ <event name="input_panel_state">
+ <description summary="state of the input panel">
+ Notify when the visibility state of the input panel changed.
+ </description>
+ <arg name="state" type="uint"/>
+ </event>
+ <event name="preedit_string">
+ <description summary="pre-edit">
+ Notify when a new composing text (pre-edit) should be set around the
+ current cursor position. Any previously set composing text should
+ be removed.
+
+ The commit text can be used to replace the preedit text on reset
+ (for example on unfocus).
+
+ The text input should also handle all preedit_style and preedit_cursor
+ events occuring directly before preedit_string.
+ </description>
+ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
+ <arg name="text" type="string"/>
+ <arg name="commit" type="string"/>
+ </event>
+ <enum name="preedit_style">
+ <entry name="default" value="0" summary="default style for composing text"/>
+ <entry name="none" value="1" summary="style should be the same as in non-composing text"/>
+ <entry name="active" value="2"/>
+ <entry name="inactive" value="3"/>
+ <entry name="highlight" value="4"/>
+ <entry name="underline" value="5"/>
+ <entry name="selection" value="6"/>
+ <entry name="incorrect" value="7"/>
+ </enum>
+ <event name="preedit_styling">
+ <description summary="pre-edit styling">
+ Sets styling information on composing text. The style is applied for
+ length bytes from index relative to the beginning of the composing
+ text (as byte offset). Multiple styles can
+ be applied to a composing text by sending multiple preedit_styling
+ events.
+
+ This event is handled as part of a following preedit_string event.
+ </description>
+ <arg name="index" type="uint"/>
+ <arg name="length" type="uint"/>
+ <arg name="style" type="uint"/>
+ </event>
+ <event name="preedit_cursor">
+ <description summary="pre-edit cursor">
+ Sets the cursor position inside the composing text (as byte
+ offset) relative to the start of the composing text. When index is a
+ negative number no cursor is shown.
+
+ This event is handled as part of a following preedit_string event.
+ </description>
+ <arg name="index" type="int"/>
+ </event>
+ <event name="commit_string">
+ <description summary="commit">
+ Notify when text should be inserted into the editor widget. The text to
+ commit could be either just a single character after a key press or the
+ result of some composing (pre-edit). It could be also an empty text
+ when some text should be removed (see delete_surrounding_text) or when
+ the input cursor should be moved (see cursor_position).
+
+ Any previously set composing text should be removed.
+ </description>
+ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
+ <arg name="text" type="string"/>
+ </event>
+ <event name="cursor_position">
+ <description summary="set cursor to new position">
+ Notify when the cursor or anchor position should be modified.
+
+ This event should be handled as part of a following commit_string
+ event.
+ </description>
+ <arg name="index" type="int"/>
+ <arg name="anchor" type="int"/>
+ </event>
+ <event name="delete_surrounding_text">
+ <description summary="delete surrounding text">
+ Notify when the text around the current cursor position should be
+ deleted.
+
+ Index is relative to the current cursor (in bytes).
+ Length is the length of deleted text (in bytes).
+
+ This event should be handled as part of a following commit_string
+ event.
+ </description>
+ <arg name="index" type="int"/>
+ <arg name="length" type="uint"/>
+ </event>
+ <event name="keysym">
+ <description summary="keysym">
+ Notify when a key event was sent. Key events should not be used
+ for normal text input operations, which should be done with
+ commit_string, delete_surrounding_text, etc. The key event follows
+ the wl_keyboard key event convention. Sym is a XKB keysym, state a
+ wl_keyboard key_state. Modifiers are a mask for effective modifiers
+ (where the modifier indices are set by the modifiers_map event)
+ </description>
+ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
+ <arg name="time" type="uint"/>
+ <arg name="sym" type="uint"/>
+ <arg name="state" type="uint"/>
+ <arg name="modifiers" type="uint"/>
+ </event>
+ <event name="language">
+ <description summary="language">
+ Sets the language of the input text. The "language" argument is a RFC-3066
+ format language tag.
+ </description>
+ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
+ <arg name="language" type="string"/>
+ </event>
+ <enum name="text_direction">
+ <entry name="auto" value="0" summary="automatic text direction based on text and language"/>
+ <entry name="ltr" value="1" summary="left-to-right"/>
+ <entry name="rtl" value="2" summary="right-to-left"/>
+ </enum>
+ <event name="text_direction">
+ <description summary="text direction">
+ Sets the text direction of input text.
+
+ It is mainly needed for showing input cursor on correct side of the
+ editor when there is no input yet done and making sure neutral
+ direction text is laid out properly.
+ </description>
+ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
+ <arg name="direction" type="uint"/>
+ </event>
+ </interface>
+
+ <interface name="wl_text_input_manager" version="1">
+ <description summary="text input manager">
+ A factory for text-input objects. This object is a global singleton.
+ </description>
+ <request name="create_text_input">
+ <description summary="create text input">
+ Creates a new text-input object.
+ </description>
+ <arg name="id" type="new_id" interface="wl_text_input"/>
+ </request>
+ </interface>
+</protocol>
--- /dev/null
+bin_PROGRAMS = \
+ weekeyboard
+
+AM_CFLAGS= \
+ @WAYLAND_CFLAGS@ \
+ @EFL_CFLAGS@ \
+ @ELDBUS_CFLAGS@ \
+ -DPKGDATADIR='"$(pkgdatadir)"'
+
+AM_LDFLAGS= \
+ @WAYLAND_LIBS@ \
+ @EFL_LIBS@ \
+ @ELDBUS_LIBS@
+
+weekeyboard_SOURCES= \
+ wkb-main.c \
+ input-method-protocol.c \
+ input-method-client-protocol.h \
+ text-protocol.c \
+ text-client-protocol.h
+
+
+if ENABLE_IBUS
+noinst_PROGRAMS = \
+ weekeyboard-config-eet-test
+
+weekeyboard_config_eet_test_SOURCES = \
+ wkb-ibus-config-eet.c \
+ wkb-ibus-config-eet.h \
+ wkb-ibus-config-eet-test.c
+
+noinst_PROGRAMS += \
+ weekeyboard-ibus-test
+
+weekeyboard_ibus_test_SOURCES = \
+ wkb-ibus.h \
+ wkb-ibus.c \
+ wkb-ibus-panel.c \
+ wkb-ibus-config.c \
+ wkb-ibus-config-eet.c \
+ wkb-ibus-config-eet.h \
+ wkb-ibus-test.c
+endif
+
+@wayland_scanner_rules@
+
+BUILT_SOURCES= \
+ input-method-protocol.c \
+ input-method-client-protocol.h \
+ text-protocol.c \
+ text-client-protocol.h
--- /dev/null
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wkb-ibus-config-eet.h"
+
+#include <Eina.h>
+#include <Eet.h>
+
+int
+main (int argc, char *argv[])
+{
+ struct wkb_ibus_config_eet *cfg;
+
+ if (!eina_init())
+ {
+ printf("Error initializing eina");
+ return 1;
+ }
+
+ if (!eet_init())
+ {
+ printf("Error initializing eet");
+ return 1;
+ }
+
+ cfg = wkb_ibus_config_eet_new("ibus-cfg.eet");
+ wkb_ibus_config_eet_free(cfg);
+
+ eet_shutdown();
+ eina_shutdown();
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the eetific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <Eina.h>
+#include <Eet.h>
+
+#include "wkb-ibus-config-eet.h"
+
+/*
+ * Base struct for all config types
+ */
+struct _config_section
+{
+ const char *id;
+
+ void (*free)(struct _config_section *);
+ void (*set_defaults)(struct _config_section *);
+ Eina_Bool (*set_value)(struct _config_section *, const char *, const char *, Eldbus_Message_Iter *);
+ void *(*get_value)(struct _config_section *, const char *, const char *);
+ void *(*get_values)(struct _config_section *, const char *);
+};
+
+static void
+_config_section_free(struct _config_section *base)
+{
+ eina_stringshare_del(base->id);
+ base->free(base);
+}
+
+static void
+_config_section_set_defaults(struct _config_section *base)
+{
+ base->set_defaults(base);
+}
+
+static Eina_Bool
+_config_section_set_value(struct _config_section *base, const char *section, const char *name, Eldbus_Message_Iter *value)
+{
+ return base->set_value(base, section, name, value);
+}
+
+static void *
+_config_section_get_value(struct _config_section *base, const char *section, const char *name)
+{
+ return base->get_value(base, section, name);
+}
+
+static void *
+_config_section_get_values(struct _config_section *base, const char *section)
+{
+ return base->get_values(base, section);
+}
+
+/*
+ * Helpers for manipulating list of strings
+ */
+static void
+_config_string_list_free(Eina_List *list)
+{
+ const char *str;
+
+ EINA_LIST_FREE(list, str)
+ eina_stringshare_del(str);
+
+ eina_list_free(list);
+}
+
+static Eina_List *
+_config_string_list_new(const char **strs)
+{
+ Eina_List *list = NULL;
+ const char *str;
+
+ for (str = *strs; str != NULL; str = *++strs)
+ list = eina_list_append(list, eina_stringshare_add(str));
+
+ return list;
+}
+
+/*
+ * <schema path="/desktop/ibus/general/hotkey/" id="org.freedesktop.ibus.general.hotkey">
+ * <key type="as" name="trigger">
+ * <default>[ 'Control+space', 'Zenkaku_Hankaku', 'Alt+Kanji', 'Alt+grave', 'Hangul', 'Alt+Release+Alt_R' ]</default>
+ * <summary>Trigger shortcut keys</summary>
+ * <description>The shortcut keys for turning input method on or off</description>
+ * </key>
+ * <key type="as" name="triggers">
+ * <default>[ '<Super>space' ]</default>
+ * <summary>Trigger shortcut keys for gtk_accelerator_parse</summary>
+ * <description>The shortcut keys for turning input method on or off</description>
+ * </key>
+ * <key type="as" name="enable-unconditional">
+ * <default>[]</default>
+ * <summary>Enable shortcut keys</summary>
+ * <description>The shortcut keys for turning input method on</description>
+ * </key>
+ * <key type="as" name="disable-unconditional">
+ * <default>[]</default>
+ * <summary>Disable shortcut keys</summary>
+ * <description>The shortcut keys for turning input method off</description>
+ * </key>
+ * <key type="as" name="next-engine">
+ * <default>[ 'Alt+Shift_L' ]</default>
+ * <summary>Next engine shortcut keys</summary>
+ * <description>The shortcut keys for switching to the next input method in the list</description>
+ * </key>
+ * <key type="as" name="next-engine-in-menu">
+ * <default>[ 'Alt+Shift_L' ]</default>
+ * <summary>Next engine shortcut keys</summary>
+ * <description>The shortcut keys for switching to the next input method in the list</description>
+ * </key>
+ * <key type="as" name="prev-engine">
+ * <default>[]</default>
+ * <summary>Prev engine shortcut keys</summary>
+ * <description>The shortcut keys for switching to the previous input method</description>
+ * </key>
+ * <key type="as" name="previous-engine">
+ * <default>[]</default>
+ * <summary>Prev engine shortcut keys</summary>
+ * <description>The shortcut keys for switching to the previous input method</description>
+ * </key>
+ * </schema>
+ */
+struct _config_hotkey
+{
+ struct _config_section base;
+
+ Eina_List *trigger;
+ Eina_List *triggers;
+ Eina_List *enable_unconditional;
+ Eina_List *disable_unconditional;
+ Eina_List *next_engine;
+ Eina_List *next_engine_in_menu;
+ Eina_List *prev_engine;
+ Eina_List *previous_engine;
+};
+
+static Eet_Data_Descriptor *
+_config_hotkey_edd_new(void)
+{
+ Eet_Data_Descriptor *edd;
+ Eet_Data_Descriptor_Class eddc;
+
+ EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, struct _config_hotkey);
+ edd = eet_data_descriptor_stream_new(&eddc);
+
+ EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_hotkey, "trigger", trigger);
+ EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_hotkey, "triggers", triggers);
+ EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_hotkey, "enable-unconditional", enable_unconditional);
+ EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_hotkey, "disable-unconditional", disable_unconditional);
+ EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_hotkey, "next-engine", next_engine);
+ EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_hotkey, "next-engine-in-menu", next_engine_in_menu);
+ EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_hotkey, "prev-engine", prev_engine);
+ EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_hotkey, "previous-engine", previous_engine);
+
+ return edd;
+}
+
+static void
+_config_hotkey_set_defaults(struct _config_section *base)
+{
+ struct _config_hotkey *hotkey = (struct _config_hotkey *) base;
+
+ const char *trigger[] = { "Control+space", "Zenkaku_Hankaku", "Alt+Kanji", "Alt+grave", "Hangul", "Alt+Release+Alt_R", NULL };
+ const char *triggers[] = { "<Super>space", NULL };
+ const char *enable_unconditional[] = { NULL };
+ const char *disable_unconditional[] = { NULL };
+ const char *next_engine[] = { NULL };
+ const char *next_engine_in_menu[] = { NULL };
+ const char *prev_engine[] = { NULL };
+ const char *previous_engine[] = { NULL };
+
+ hotkey->trigger = _config_string_list_new(trigger);
+ hotkey->triggers = _config_string_list_new(triggers);
+ hotkey->enable_unconditional = _config_string_list_new(enable_unconditional);
+ hotkey->disable_unconditional = _config_string_list_new(disable_unconditional);
+ hotkey->next_engine = _config_string_list_new(next_engine);
+ hotkey->next_engine_in_menu = _config_string_list_new(next_engine_in_menu);
+ hotkey->prev_engine = _config_string_list_new(prev_engine);
+ hotkey->previous_engine = _config_string_list_new(previous_engine);
+}
+
+static void
+_config_hotkey_free(struct _config_section *base)
+{
+ struct _config_hotkey *hotkey = (struct _config_hotkey *) base;
+
+ _config_string_list_free(hotkey->trigger);
+ _config_string_list_free(hotkey->triggers);
+ _config_string_list_free(hotkey->enable_unconditional);
+ _config_string_list_free(hotkey->disable_unconditional);
+ _config_string_list_free(hotkey->next_engine);
+ _config_string_list_free(hotkey->next_engine_in_menu);
+ _config_string_list_free(hotkey->prev_engine);
+ _config_string_list_free(hotkey->previous_engine);
+
+ free(hotkey);
+}
+
+static Eina_Bool
+_config_hotkey_set_value(struct _config_section *base, const char *section, const char *name, Eldbus_Message_Iter *value)
+{
+ return EINA_FALSE;
+}
+
+static void *
+_config_hotkey_get_value(struct _config_section *base, const char *section, const char *name)
+{
+ return NULL;
+}
+
+static void *
+_config_hotkey_get_values(struct _config_section *base, const char *section)
+{
+ return NULL;
+}
+
+static void
+_config_hotkey_section_init(struct _config_section *base)
+{
+ base->id = eina_stringshare_add("hotkey");
+ base->free = _config_hotkey_free;
+ base->set_defaults = _config_hotkey_set_defaults;
+ base->set_value = _config_hotkey_set_value;
+ base->get_value = _config_hotkey_get_value;
+ base->get_values = _config_hotkey_get_values;
+}
+
+static struct _config_section *
+_config_hotkey_new(void)
+{
+ struct _config_hotkey *conf = calloc(1, sizeof(*conf));
+ _config_hotkey_section_init((struct _config_section *) conf);
+ return (struct _config_section *) conf;
+}
+
+/*
+ * <schema path="/desktop/ibus/general/" id="org.freedesktop.ibus.general">
+ * <key type="as" name="preload-engines">
+ * <default>[]</default>
+ * <summary>Preload engines</summary>
+ * <description>Preload engines during ibus starts up</description>
+ * </key>
+ * <key type="as" name="engines-order">
+ * <default>[]</default>
+ * <summary>Engines order</summary>
+ * <description>Saved engines order in input method list</description>
+ * </key>
+ * <key type="i" name="switcher-delay-time">
+ * <default>400</default>
+ * <summary>Popup delay milliseconds for IME switcher window</summary>
+ * <description>Set popup delay milliseconds to show IME switcher window. The default is 400. 0 = Show the window immediately. 0 < Delay milliseconds. 0 > Do not show the
+ * </key>
+ * <key type="s" name="version">
+ * <default>''</default>
+ * <summary>Saved version number</summary>
+ * <description>The saved version number will be used to check the difference between the version of the previous installed ibus and one of the current ibus.</description>
+ * </key>
+ * <key type="b" name="use-system-keyboard-layout">
+ * <default>false</default>
+ * <summary>Use system keyboard layout</summary>
+ * <description>Use system keyboard (XKB) layout</description>
+ * </key>
+ * <key type="b" name="embed-preedit-text">
+ * <default>true</default>
+ * <summary>Embed Preedit Text</summary>
+ * <description>Embed Preedit Text in Application Window</description>
+ * </key>
+ * <key type="b" name="use-global-engine">
+ * <default>false</default>
+ * <summary>Use global input method</summary>
+ * <description>Share the same input method among all applications</description>
+ * </key>
+ * <key type="b" name="enable-by-default">
+ * <default>false</default>
+ * <summary>Enable input method by default</summary>
+ * <description>Enable input method by default when the application gets input focus</description>
+ * </key>
+ * <key type="as" name="dconf-preserve-name-prefixes">
+ * <default>[ '/desktop/ibus/engine/pinyin', '/desktop/ibus/engine/bopomofo', '/desktop/ibus/engine/hangul' ]</default>
+ * <summary>DConf preserve name prefixes</summary>
+ * <description>Prefixes of DConf keys to stop name conversion</description>
+ * </key>
+ * <child schema="org.freedesktop.ibus.general.hotkey" name="hotkey"/>
+ * </schema>
+ */
+struct _config_general
+{
+ struct _config_section base;
+
+ struct _config_section *hotkey;
+
+ Eina_List *preload_engines;
+ Eina_List *engines_order;
+ Eina_List *dconf_preserve_name_prefixes;
+
+ const char *version;
+
+ int switcher_delay_time;
+
+ Eina_Bool use_system_keyboard_layout;
+ Eina_Bool embed_preedit_text;
+ Eina_Bool use_global_engine;
+ Eina_Bool enable_by_default;
+};
+
+static Eet_Data_Descriptor *
+_config_general_edd_new(Eet_Data_Descriptor *hotkey_edd)
+{
+ Eet_Data_Descriptor *edd;
+ Eet_Data_Descriptor_Class eddc;
+
+ EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, struct _config_general);
+ edd = eet_data_descriptor_stream_new(&eddc);
+
+ EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_general, "preload-engines", preload_engines);
+ EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_general, "engines-order", engines_order);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_general, "switcher-delay-time", switcher_delay_time, EET_T_INT);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_general, "version", version, EET_T_STRING);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_general, "use-system-keyboard-layout", use_system_keyboard_layout, EET_T_UCHAR);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_general, "embed-preedit-text", embed_preedit_text, EET_T_UCHAR);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_general, "use-global-engine", use_global_engine, EET_T_UCHAR);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_general, "enable-by-default", enable_by_default, EET_T_UCHAR);
+ EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_general, "dconf-preserve-name-prefixes", dconf_preserve_name_prefixes);
+ EET_DATA_DESCRIPTOR_ADD_SUB(edd, struct _config_general, "hotkey", hotkey, hotkey_edd);
+
+ return edd;
+}
+
+static void
+_config_general_set_defaults(struct _config_section *base)
+{
+ struct _config_general *general = (struct _config_general *) base;
+
+ const char *preload_engines[] = { NULL };
+ const char *engines_order[] = { NULL };
+ const char *dconf_preserve_name_prefixes[] = { "/desktop/ibus/engine/pinyin", "/desktop/ibus/engine/bopomofo", "/desktop/ibus/engine/hangul", NULL };
+
+ _config_section_set_defaults(general->hotkey);
+
+ general->preload_engines = _config_string_list_new(preload_engines);
+ general->engines_order = _config_string_list_new(engines_order);
+ general->switcher_delay_time = 400;
+ general->version = eina_stringshare_add("");
+ general->use_system_keyboard_layout = EINA_FALSE;
+ general->embed_preedit_text = EINA_TRUE;
+ general->use_global_engine = EINA_FALSE;
+ general->enable_by_default = EINA_FALSE;
+ general->dconf_preserve_name_prefixes = _config_string_list_new(dconf_preserve_name_prefixes);
+
+}
+
+static void
+_config_general_free(struct _config_section *base)
+{
+ struct _config_general *general = (struct _config_general *) base;
+
+ _config_section_free(general->hotkey);
+
+ _config_string_list_free(general->preload_engines);
+ _config_string_list_free(general->engines_order);
+ _config_string_list_free(general->dconf_preserve_name_prefixes);
+
+ eina_stringshare_del(general->version);
+ free(general);
+}
+
+static Eina_Bool
+_config_general_set_value(struct _config_section *base, const char *section, const char *name, Eldbus_Message_Iter *value)
+{
+ return EINA_FALSE;
+}
+
+static void *
+_config_general_get_value(struct _config_section *base, const char *section, const char *name)
+{
+ return NULL;
+}
+
+static void *
+_config_general_get_values(struct _config_section *base, const char *section)
+{
+ return NULL;
+}
+
+static void
+_config_general_section_init(struct _config_section *base)
+{
+ struct _config_general *general = (struct _config_general *) base;
+
+ base->id = eina_stringshare_add("general");
+ base->free = _config_general_free;
+ base->set_defaults = _config_general_set_defaults;
+ base->set_value = _config_general_set_value;
+ base->get_value = _config_general_get_value;
+ base->get_values = _config_general_get_values;
+
+ if (general->hotkey)
+ _config_hotkey_section_init(general->hotkey);
+}
+
+static struct _config_section *
+_config_general_new(void)
+{
+ struct _config_general *conf = calloc(1, sizeof(*conf));
+ _config_general_section_init((struct _config_section *) conf);
+ conf->hotkey = _config_hotkey_new();
+ return (struct _config_section *) conf;
+}
+
+/*
+ * <schema path="/desktop/ibus/panel/" id="org.freedesktop.ibus.panel">
+ * <key type="i" name="show">
+ * <default>0</default>
+ * <summary>Auto hide</summary>
+ * <description>The behavior of language panel. 0 = Embedded in menu, 1 = Auto hide, 2 = Always show</description>
+ * </key>
+ * <key type="i" name="x">
+ * <default>-1</default>
+ * <summary>Language panel position</summary>
+ * </key>
+ * <key type="i" name="y">
+ * <default>-1</default>
+ * <summary>Language panel position</summary>
+ * </key>
+ * <key type="i" name="lookup-table-orientation">
+ * <default>1</default>
+ * <summary>Orientation of lookup table</summary>
+ * <description>Orientation of lookup table. 0 = Horizontal, 1 = Vertical</description>
+ * </key>
+ * <key type="b" name="show-icon-on-systray">
+ * <default>true</default>
+ * <summary>Show icon on system tray</summary>
+ * <description>Show icon on system tray</description>
+ * </key>
+ * <key type="b" name="show-im-name">
+ * <default>false</default>
+ * <summary>Show input method name</summary>
+ * <description>Show input method name on language bar</description>
+ * </key>
+ * <key type="b" name="use-custom-font">
+ * <default>false</default>
+ * <summary>Use custom font</summary>
+ * <description>Use custom font name for language panel</description>
+ * </key>
+ * <key type="s" name="custom-font">
+ * <default>'Sans 10'</default>
+ * <summary>Custom font</summary>
+ * <description>Custom font name for language panel</description>
+ * </key>
+ * </schema>
+ */
+struct _config_panel
+{
+ struct _config_section base;
+
+ const char *custom_font;
+ int show;
+ int x;
+ int y;
+ int lookup_table_orientation;
+ Eina_Bool show_icon_in_systray;
+ Eina_Bool show_im_name;
+ Eina_Bool use_custom_font;
+};
+
+static Eet_Data_Descriptor *
+_config_panel_edd_new(void)
+{
+ Eet_Data_Descriptor *edd;
+ Eet_Data_Descriptor_Class eddc;
+
+ EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, struct _config_panel);
+ edd = eet_data_descriptor_stream_new(&eddc);
+
+ EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_panel, "show", show, EET_T_INT);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_panel, "x", x, EET_T_INT);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_panel, "y", y, EET_T_INT);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_panel, "lookup-table-orientation", lookup_table_orientation, EET_T_INT);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_panel, "show-icon-in-systray", show_icon_in_systray, EET_T_UCHAR);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_panel, "show-im-name", show_im_name, EET_T_UCHAR);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_panel, "use-custom-font", use_custom_font, EET_T_UCHAR);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_panel, "custom-font", custom_font, EET_T_STRING);
+
+ return edd;
+}
+
+static void
+_config_panel_set_defaults(struct _config_section *base)
+{
+ struct _config_panel *panel = (struct _config_panel *) base;
+
+ panel->show = 0;
+ panel->x = -1;
+ panel->y = -1;
+ panel->lookup_table_orientation = 1;
+ panel->show_icon_in_systray = EINA_TRUE;
+ panel->show_im_name = EINA_FALSE;
+ panel->use_custom_font = EINA_FALSE;
+ panel->custom_font = eina_stringshare_add("Sans 10");
+}
+
+static void
+_config_panel_free(struct _config_section *base)
+{
+ struct _config_panel *panel = (struct _config_panel *) base;
+
+ eina_stringshare_del(panel->custom_font);
+ free(panel);
+}
+
+static Eina_Bool
+_config_panel_set_value(struct _config_section *base, const char *section, const char *name, Eldbus_Message_Iter *value)
+{
+ return EINA_FALSE;
+}
+
+static void *
+_config_panel_get_value(struct _config_section *base, const char *section, const char *name)
+{
+ return NULL;
+}
+
+static void *
+_config_panel_get_values(struct _config_section *base, const char *section)
+{
+ return NULL;
+}
+
+static void
+_config_panel_section_init(struct _config_section *base)
+{
+ base->id = eina_stringshare_add("panel");
+ base->free = _config_panel_free;
+ base->set_defaults = _config_panel_set_defaults;
+ base->set_value = _config_panel_set_value;
+ base->get_value = _config_panel_get_value;
+ base->get_values = _config_panel_get_values;
+}
+
+static struct _config_section *
+_config_panel_new(void)
+{
+ struct _config_panel *conf = calloc(1, sizeof(*conf));
+ _config_panel_section_init((struct _config_section *) conf);
+ return (struct _config_section *) conf;
+}
+
+/*
+ * NO SCHEMA AVAILABLE. BASED ON THE SOURCE CODE
+ */
+struct _config_hangul
+{
+ struct _config_section base;
+
+ const char *hangul_keyboard;
+ Eina_List *hanja_keys;
+ Eina_Bool word_commit;
+ Eina_Bool auto_reorder;
+};
+
+static Eet_Data_Descriptor *
+_config_hangul_edd_new(void)
+{
+ Eet_Data_Descriptor *edd;
+ Eet_Data_Descriptor_Class eddc;
+
+ EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, struct _config_hangul);
+ edd = eet_data_descriptor_stream_new(&eddc);
+
+ EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_hangul, "HangulKeyboard", hangul_keyboard, EET_T_STRING);
+ EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct _config_hangul, "HanjaKeys", hanja_keys);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_hangul, "WordCommit", word_commit, EET_T_UCHAR);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct _config_hangul, "AutoReorder", auto_reorder, EET_T_UCHAR);
+
+ return edd;
+}
+
+static void
+_config_hangul_set_defaults(struct _config_section *base)
+{
+ struct _config_hangul *hangul = (struct _config_hangul *) base;
+ const char *hanja_keys[] = { "Hangul_Hanja", "F9", NULL };
+
+ hangul->hangul_keyboard = eina_stringshare_add("2");
+ hangul->hanja_keys = _config_string_list_new(hanja_keys);
+ hangul->word_commit = EINA_FALSE;
+ hangul->auto_reorder = EINA_TRUE;
+}
+
+static void
+_config_hangul_free(struct _config_section *base)
+{
+ struct _config_hangul *hangul = (struct _config_hangul *) base;
+
+ eina_stringshare_del(hangul->hangul_keyboard);
+ _config_string_list_free(hangul->hanja_keys);
+ free(hangul);
+}
+
+static Eina_Bool
+_config_hangul_set_value(struct _config_section *base, const char *section, const char *name, Eldbus_Message_Iter *value)
+{
+ return EINA_FALSE;
+}
+
+static void *
+_config_hangul_get_value(struct _config_section *base, const char *section, const char *name)
+{
+ return NULL;
+}
+
+static void *
+_config_hangul_get_values(struct _config_section *base, const char *section)
+{
+ return NULL;
+}
+
+static void
+_config_hangul_section_init(struct _config_section *base)
+{
+ base->id = eina_stringshare_add("hangul");
+ base->free = _config_hangul_free;
+ base->set_defaults = _config_hangul_set_defaults;
+ base->set_value = _config_hangul_set_value;
+ base->get_value = _config_hangul_get_value;
+ base->get_values = _config_hangul_get_values;
+}
+
+static struct _config_section *
+_config_hangul_new(void)
+{
+ struct _config_hangul *conf = calloc(1, sizeof(*conf));
+ _config_hangul_section_init((struct _config_section *) conf);
+ return (struct _config_section *) conf;
+}
+
+/*
+ * NO SCHEMA AVAILABLE. BASED ON THE SOURCE CODE
+ */
+struct _config_engine
+{
+ struct _config_section base;
+
+ struct _config_section *hangul;
+};
+
+static Eet_Data_Descriptor *
+_config_engine_edd_new(Eet_Data_Descriptor *hangul_edd)
+{
+ Eet_Data_Descriptor *edd;
+ Eet_Data_Descriptor_Class eddc;
+
+ EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, struct _config_engine);
+ edd = eet_data_descriptor_stream_new(&eddc);
+
+ EET_DATA_DESCRIPTOR_ADD_SUB(edd, struct _config_engine, "Hangul", hangul, hangul_edd);
+
+ return edd;
+}
+
+static void
+_config_engine_set_defaults(struct _config_section *base)
+{
+ struct _config_engine *engine = (struct _config_engine *) base;
+
+ _config_section_set_defaults(engine->hangul);
+}
+
+static void
+_config_engine_free(struct _config_section *base)
+{
+ struct _config_engine *engine = (struct _config_engine *) base;
+
+ _config_section_free(engine->hangul);
+ free(engine);
+}
+
+static Eina_Bool
+_config_engine_set_value(struct _config_section *base, const char *section, const char *name, Eldbus_Message_Iter *value)
+{
+ return EINA_FALSE;
+}
+
+static void *
+_config_engine_get_value(struct _config_section *base, const char *section, const char *name)
+{
+ return NULL;
+}
+
+static void *
+_config_engine_get_values(struct _config_section *base, const char *section)
+{
+ return NULL;
+}
+
+static void
+_config_engine_section_init(struct _config_section *base)
+{
+ struct _config_engine *engine = (struct _config_engine *) base;
+
+ base->id = eina_stringshare_add("engine");
+ base->free = _config_engine_free;
+ base->set_defaults = _config_engine_set_defaults;
+ base->set_value = _config_engine_set_value;
+ base->get_value = _config_engine_get_value;
+ base->get_values = _config_engine_get_values;
+
+ if (engine->hangul)
+ _config_hangul_section_init(engine->hangul);
+}
+
+static struct _config_section *
+_config_engine_new(void)
+{
+ struct _config_engine *conf = calloc(1, sizeof(*conf));
+ _config_engine_section_init((struct _config_section *) conf);
+ conf->hangul = _config_hangul_new();
+ return (struct _config_section *) conf;
+}
+
+/*
+ * <schema path="/desktop/ibus/" id="org.freedesktop.ibus">
+ * <child schema="org.freedesktop.ibus.general" name="general"/>
+ * <child schema="org.freedesktop.ibus.panel" name="panel"/>
+ * </schema>
+ */
+struct _config_ibus
+{
+ struct _config_section base;
+
+ struct _config_section *general;
+ struct _config_section *panel;
+ struct _config_section *engine;
+};
+
+static Eet_Data_Descriptor *
+_config_ibus_edd_new(Eet_Data_Descriptor *general_edd, Eet_Data_Descriptor *panel_edd, Eet_Data_Descriptor *engine_edd)
+{
+ Eet_Data_Descriptor *edd;
+ Eet_Data_Descriptor_Class eddc;
+
+ EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, struct _config_ibus);
+ edd = eet_data_descriptor_stream_new(&eddc);
+
+ EET_DATA_DESCRIPTOR_ADD_SUB(edd, struct _config_ibus, "general", general, general_edd);
+ EET_DATA_DESCRIPTOR_ADD_SUB(edd, struct _config_ibus, "panel", panel, panel_edd);
+ EET_DATA_DESCRIPTOR_ADD_SUB(edd, struct _config_ibus, "engine", engine, engine_edd);
+
+ return edd;
+}
+
+static void
+_config_ibus_set_defaults(struct _config_section *base)
+{
+ struct _config_ibus *ibus = (struct _config_ibus *) base;
+
+ _config_section_set_defaults(ibus->general);
+ _config_section_set_defaults(ibus->panel);
+ _config_section_set_defaults(ibus->engine);
+}
+
+static void
+_config_ibus_free(struct _config_section *base)
+{
+ struct _config_ibus *ibus = (struct _config_ibus *) base;
+
+ _config_section_free(ibus->general);
+ _config_section_free(ibus->panel);
+ _config_section_free(ibus->engine);
+
+ free(ibus);
+}
+
+static Eina_Bool
+_config_ibus_set_value(struct _config_section *base, const char *section, const char *name, Eldbus_Message_Iter *value)
+{
+ return EINA_FALSE;
+}
+
+static void *
+_config_ibus_get_value(struct _config_section *base, const char *section, const char *name)
+{
+ return NULL;
+}
+
+static void *
+_config_ibus_get_values(struct _config_section *base, const char *section)
+{
+ return NULL;
+}
+
+static void
+_config_ibus_section_init(struct _config_section *base)
+{
+ struct _config_ibus *ibus = (struct _config_ibus *) base;
+ base->id = eina_stringshare_add("ibus");
+ base->free = _config_ibus_free;
+ base->set_defaults = _config_ibus_set_defaults;
+ base->set_value = _config_ibus_set_value;
+ base->get_value = _config_ibus_get_value;
+ base->get_values = _config_ibus_get_values;
+
+ if (ibus->general)
+ _config_general_section_init(ibus->general);
+
+ if (ibus->panel)
+ _config_panel_section_init(ibus->panel);
+
+ if (ibus->engine)
+ _config_engine_section_init(ibus->engine);
+}
+
+static struct _config_section *
+_config_ibus_new(void)
+{
+ struct _config_ibus *conf = calloc(1, sizeof(*conf));
+ _config_ibus_section_init((struct _config_section *) conf);
+ conf->general = _config_general_new();
+ conf->panel = _config_panel_new();
+ conf->engine = _config_engine_new();
+ return (struct _config_section *) conf;
+}
+
+/*
+ * MAIN
+ */
+struct wkb_ibus_config_eet
+{
+ const char *path;
+ struct _config_section *ibus_config;
+
+ Eet_Data_Descriptor *hotkey_edd;
+ Eet_Data_Descriptor *general_edd;
+ Eet_Data_Descriptor *panel_edd;
+ Eet_Data_Descriptor *hangul_edd;
+ Eet_Data_Descriptor *engine_edd;
+ Eet_Data_Descriptor *ibus_edd;
+};
+
+Eina_Bool
+wkb_ibus_config_eet_set_value(struct wkb_ibus_config_eet *config_eet, const char *section, const char *name, Eldbus_Message_Iter *value)
+{
+ return _config_section_set_value(config_eet->ibus_config, section, name, value);
+}
+
+void *
+wkb_ibus_config_eet_get_value(struct wkb_ibus_config_eet *config_eet, const char *section, const char *name)
+{
+ return _config_section_get_value(config_eet->ibus_config, section, name);
+}
+
+void *
+wkb_ibus_config_eet_get_values(struct wkb_ibus_config_eet *config_eet, const char *section)
+{
+ return _config_section_get_values(config_eet->ibus_config, section);
+}
+
+void
+wkb_ibus_config_eet_set_defaults(struct wkb_ibus_config_eet *config_eet)
+{
+
+ if (config_eet->ibus_config)
+ _config_section_free(config_eet->ibus_config);
+
+ config_eet->ibus_config = _config_ibus_new();
+ _config_ibus_set_defaults(config_eet->ibus_config);
+}
+
+static struct wkb_ibus_config_eet *
+_config_eet_section_init(const char *path)
+{
+ struct wkb_ibus_config_eet *eet = calloc(1, sizeof(*eet));
+ eet->path = eina_stringshare_add(path);
+
+ eet->hotkey_edd = _config_hotkey_edd_new();
+ eet->general_edd = _config_general_edd_new(eet->hotkey_edd);
+ eet->panel_edd = _config_panel_edd_new();
+ eet->hangul_edd = _config_hangul_edd_new();
+ eet->engine_edd = _config_engine_edd_new(eet->hangul_edd);
+ eet->ibus_edd = _config_ibus_edd_new(eet->general_edd, eet->panel_edd, eet->engine_edd);
+
+ return eet;
+}
+
+static Eina_Bool
+_config_eet_exists(const char *path)
+{
+ struct stat buf;
+ return stat(path, &buf) == 0;
+}
+
+struct wkb_ibus_config_eet *
+wkb_ibus_config_eet_new(const char *path)
+{
+ struct wkb_ibus_config_eet *eet = _config_eet_section_init(path);
+ Eet_File *ef = NULL;
+ Eet_File_Mode mode = EET_FILE_MODE_READ_WRITE;
+
+ if (_config_eet_exists(path))
+ mode = EET_FILE_MODE_READ;
+
+ if (!(ef = eet_open(path, mode)))
+ {
+ printf("Error opening eet file '%s' for %s\n", path, mode == EET_FILE_MODE_READ ? "read" : "write");
+ wkb_ibus_config_eet_free(eet);
+ return NULL;
+ }
+
+ if (mode == EET_FILE_MODE_READ)
+ {
+ eet->ibus_config = eet_data_read(ef, eet->ibus_edd, "ibus");
+ _config_ibus_section_init(eet->ibus_config);
+ goto end;
+ }
+
+ wkb_ibus_config_eet_set_defaults(eet);
+ if (!eet_data_write(ef, eet->ibus_edd, "ibus", eet->ibus_config, EINA_TRUE))
+ {
+ printf("Error creating eet file '%s'\n", path);
+ wkb_ibus_config_eet_free(eet);
+ eet = NULL;
+ }
+
+end:
+ eet_close(ef);
+ return eet;
+}
+
+void
+wkb_ibus_config_eet_free(struct wkb_ibus_config_eet *config_eet)
+{
+ _config_ibus_free(config_eet->ibus_config);
+ eina_stringshare_del(config_eet->path);
+
+ eet_data_descriptor_free(config_eet->hotkey_edd);
+ eet_data_descriptor_free(config_eet->general_edd);
+ eet_data_descriptor_free(config_eet->panel_edd);
+ eet_data_descriptor_free(config_eet->hangul_edd);
+ eet_data_descriptor_free(config_eet->engine_edd);
+ eet_data_descriptor_free(config_eet->ibus_edd);
+
+ free(config_eet);
+}
--- /dev/null
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _WKB_IBUS_CONFIG_EET_H_
+#define _WKB_IBUS_CONFIG_EET_H_
+
+#include <Eina.h>
+#include <Eldbus.h>
+
+struct wkb_ibus_config_eet;
+
+Eina_Bool wkb_ibus_config_eet_set_value(struct wkb_ibus_config_eet *config_eet, const char *section, const char *name, Eldbus_Message_Iter *value);
+void *wkb_ibus_config_eet_get_value(struct wkb_ibus_config_eet *config_eet, const char *section, const char *name);
+void *wkb_ibus_config_eet_get_values(struct wkb_ibus_config_eet *config_eet, const char *section);
+
+void wkb_ibus_config_eet_set_defaults(struct wkb_ibus_config_eet *config_eet);
+
+struct wkb_ibus_config_eet *wkb_ibus_config_eet_new(const char *path);
+void wkb_ibus_config_eet_free(struct wkb_ibus_config_eet *config_eet);
+
+#endif /* _WKB_IBUS_CONFIG_EET_H_ */
--- /dev/null
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <Eldbus.h>
+
+#include "wkb-ibus.h"
+
+#define CONFIG_CHECK_MESSAGE_ERRORS(_msg) \
+ do \
+ { \
+ const char *error, *error_msg; \
+ if (eldbus_message_error_get(_msg, &error, &error_msg)) \
+ { \
+ ERR("DBus message error: %s: %s", error, error_msg); \
+ return NULL; \
+ } \
+ DBG("Message '%s' with signature '%s'", eldbus_message_member_get(_msg), eldbus_message_signature_get(_msg)); \
+ } while (0);
+
+static Eldbus_Message *
+_config_set_value(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ const char *section, *name;
+ Eldbus_Message_Iter *value;
+
+ CONFIG_CHECK_MESSAGE_ERRORS(msg)
+
+ if (!eldbus_message_arguments_get(msg, "ssv", §ion, &name, &value))
+ {
+ ERR("Error reading message arguments");
+ return NULL;
+ }
+
+ DBG("section: '%s', name: '%s', value: '%p'", section, name, value);
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_config_get_value(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ const char *section, *name;
+
+ CONFIG_CHECK_MESSAGE_ERRORS(msg)
+
+ if (!eldbus_message_arguments_get(msg, "ss", §ion, &name))
+ {
+ ERR("Error reading message arguments");
+ return NULL;
+ }
+
+ DBG("section: '%s', name: '%s'", section, name);
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_config_get_values(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ const char *section;
+
+ CONFIG_CHECK_MESSAGE_ERRORS(msg)
+
+ if (!eldbus_message_arguments_get(msg, "s", §ion))
+ {
+ ERR("Error reading message arguments");
+ return NULL;
+ }
+
+ DBG("section: '%s'", section);
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_config_unset_value(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ const char *section, *name;
+
+ CONFIG_CHECK_MESSAGE_ERRORS(msg)
+
+ if (!eldbus_message_arguments_get(msg, "ss", §ion, &name))
+ {
+ ERR("Error reading message arguments");
+ return NULL;
+ }
+
+ DBG("section: '%s', name: '%s'", section, name);
+
+ return NULL;
+}
+
+static const Eldbus_Method _wkb_ibus_config_methods[] =
+{
+/* typedef struct _Eldbus_Method
+ * {
+ * const char *member;
+ * const Eldbus_Arg_Info *in;
+ * const Eldbus_Arg_Info *out;
+ * Eldbus_Method_Cb cb;
+ * unsigned int flags;
+ * } Eldbus_Method;
+ */
+ { .member = "SetValue",
+ .in = ELDBUS_ARGS({"s", "section"}, {"s", "name"}, {"v", "value"}),
+ .cb = _config_set_value, },
+
+ { .member = "GetValue",
+ .in = ELDBUS_ARGS({"s", "section"}, {"s", "name"}),
+ .out = ELDBUS_ARGS({"v", "value"}),
+ .cb = _config_get_value, },
+
+ { .member = "GetValues",
+ .in = ELDBUS_ARGS({"s", "section"}),
+ .out = ELDBUS_ARGS({"a{sv}", "values"}),
+ .cb = _config_get_values, },
+
+ { .member = "UnsetValue",
+ .in = ELDBUS_ARGS({"s", "section"}, {"s", "name"}),
+ .cb = _config_unset_value, },
+
+ { NULL },
+};
+
+static const Eldbus_Signal _wkb_ibus_config_signals[] =
+{
+/* typedef struct _Eldbus_Signal
+ * {
+ * const char *name;
+ * const Eldbus_Arg_Info *args;
+ * unsigned int flags;
+ * } Eldbus_Signal;
+ */
+ { .name = "ValueChanged",
+ .args = ELDBUS_ARGS({"s", "section"}, {"s", "name"}, {"v", "value"}),
+ .flags = 0, },
+
+ { NULL },
+};
+
+static const Eldbus_Service_Interface_Desc _wkb_ibus_config_interface =
+{
+ .interface = IBUS_INTERFACE_CONFIG,
+ .methods = _wkb_ibus_config_methods,
+ .signals = _wkb_ibus_config_signals,
+};
+
+Eldbus_Service_Interface *
+wkb_ibus_config_register(Eldbus_Connection *conn)
+{
+ return eldbus_service_interface_register(conn, IBUS_PATH_CONFIG, &_wkb_ibus_config_interface);
+}
+
--- /dev/null
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <Eldbus.h>
+
+#include "wkb-ibus.h"
+
+#define PANEL_CHECK_MESSAGE_ERRORS(_msg) \
+ do \
+ { \
+ const char *error, *error_msg; \
+ if (eldbus_message_error_get(_msg, &error, &error_msg)) \
+ { \
+ ERR("DBus message error: %s: %s", error, error_msg); \
+ return NULL; \
+ } \
+ DBG("Message '%s' with signature '%s'", eldbus_message_member_get(_msg), eldbus_message_signature_get(_msg)); \
+ } while (0);
+
+static Eina_Array *_get_properties_from_message_iter(Eldbus_Message_Iter *iter);
+
+struct _ibus_serializable
+{
+ /*
+ * All messages sent by IBus will start with the sa{sv} signature, but
+ * those fields don't seem useful for us, this struct is used to help
+ * on deserializing those fields
+ */
+ char *text;
+ Eldbus_Message_Iter *variant;
+};
+
+struct _ibus_attr
+{
+ unsigned int type;
+ unsigned int value;
+ unsigned int start_idx;
+ unsigned int end_idx;
+};
+
+struct _ibus_text
+{
+ char *text;
+ Eina_Array *attrs;
+};
+
+struct _ibus_lookup_table
+{
+ unsigned int page_size;
+ unsigned int cursor_pos;
+ Eina_Bool cursor_visible;
+ Eina_Bool round;
+ int orientation;
+ Eina_Array *candidates;
+ Eina_Array *labels;
+};
+
+struct _ibus_property
+{
+ char *key;
+ char *icon;
+ struct _ibus_text *label;
+ struct _ibus_text *symbol;
+ struct _ibus_text *tooltip;
+ Eina_Bool sensitive;
+ Eina_Bool visible;
+ unsigned int type;
+ unsigned int state;
+ Eina_Array *sub_properties;
+};
+
+static struct _ibus_attr *
+_get_attr_from_message_iter(Eldbus_Message_Iter *iter)
+{
+ struct _ibus_attr *attr = calloc(1, sizeof(*attr));
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(attr, NULL);
+
+ DBG("Attribute iter signature '%s'", eldbus_message_iter_signature_get(iter));
+
+ if (!eldbus_message_iter_arguments_get(iter, "uuuu", &attr->type,
+ &attr->value, &attr->start_idx,
+ &attr->end_idx))
+ {
+ ERR("Error deserializing IBusAttribute");
+ free(attr);
+ attr = NULL;
+ }
+
+ return attr;
+}
+
+static void
+_free_eina_array(Eina_Array *array, void (* free_func)(void *))
+{
+ if (!array)
+ return;
+
+ while (eina_array_count(array))
+ free_func(eina_array_pop(array));
+
+ eina_array_free(array);
+}
+
+static void
+_free_text(struct _ibus_text *text)
+{
+ if (!text)
+ return;
+
+ _free_eina_array(text->attrs, free);
+ free(text->text);
+ free(text);
+}
+
+static struct _ibus_text *
+_get_text_from_message_iter(Eldbus_Message_Iter *iter)
+{
+ struct _ibus_serializable ignore = { 0 };
+ struct _ibus_text *text = calloc(1, sizeof(*text));
+ struct _ibus_attr *attr = NULL;
+ Eldbus_Message_Iter *attrs = NULL, *a = NULL;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(text, NULL);
+
+ DBG("Text iter signature '%s'", eldbus_message_iter_signature_get(iter));
+
+ if (!eldbus_message_iter_arguments_get(iter, "(sa{sv}sv)", &ignore.text,
+ &ignore.variant, &text->text, &attrs))
+ {
+ ERR("Error deserializing IBusText");
+ free(text);
+ text = NULL;
+ goto end;
+ }
+
+ /* Check for attributes */
+ if (attrs == NULL)
+ {
+ INF("Text has no attributes");
+ goto end;
+ }
+
+ while (eldbus_message_iter_get_and_next(attrs, 'v', &a))
+ {
+ if (!text->attrs)
+ text->attrs = eina_array_new(10);
+
+ if (!(attr = _get_attr_from_message_iter(a)))
+ {
+ _free_text(text);
+ text = NULL;
+ goto end;
+ }
+
+ eina_array_push(text->attrs, attr);
+ }
+
+end:
+ return text;
+}
+
+static void
+_free_lookup_table(struct _ibus_lookup_table *table)
+{
+ if (!table)
+ return;
+
+ _free_eina_array(table->candidates, _free_text);
+ _free_eina_array(table->labels, _free_text);
+ free(table);
+}
+
+static struct _ibus_lookup_table *
+_get_lookup_table_from_message_iter(Eldbus_Message_Iter *iter)
+{
+ struct _ibus_serializable ignore = { 0 };
+ struct _ibus_lookup_table *table = calloc(1, sizeof(*table));
+ struct _ibus_text *text = NULL;
+ Eldbus_Message_Iter *candidates = NULL, *labels = NULL, *t = NULL;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(table, NULL);
+
+ DBG("LookupTable iter signature '%s'", eldbus_message_iter_signature_get(iter));
+
+ if (!eldbus_message_iter_arguments_get(iter, "(sa{sv}uubbiavav)",
+ &ignore.text, &ignore.variant,
+ &table->page_size, &table->cursor_pos,
+ &table->cursor_visible, &table->round,
+ &table->orientation, &candidates,
+ &labels))
+ {
+ ERR("Error deserializing IBusLookupTable");
+ free(table);
+ table = NULL;
+ goto end;
+ }
+
+ DBG("Lookup table:");
+ DBG("\tPage size.......: '%d'", table->page_size);
+ DBG("\tCursor position.: '%d'", table->cursor_pos);
+ DBG("\tCursor visible..: '%d'", table->cursor_visible);
+ DBG("\tRound...........: '%d'", table->round);
+ DBG("\tOrientation.....: '%d'", table->orientation);
+ DBG("\tCandidates......: '%p'", candidates);
+ DBG("\tLabels..........: '%p'", labels);
+
+ if (!candidates)
+ {
+ INF("Lookup table has no candidates");
+ goto labels;
+ }
+
+ while (eldbus_message_iter_get_and_next(candidates, 'v', &t))
+ {
+ if (!table->candidates)
+ table->candidates = eina_array_new(10);
+
+ if (!(text = _get_text_from_message_iter(t)))
+ {
+ _free_lookup_table(table);
+ table = NULL;
+ goto end;
+ }
+
+ DBG("Appending new candidate %s", text->text);
+ eina_array_push(table->candidates, text);
+ }
+
+labels:
+ if (!labels)
+ {
+ INF("Lookup table has no labels");
+ goto end;
+ }
+
+ while (eldbus_message_iter_get_and_next(labels, 'v', &t))
+ {
+ if (!table->labels)
+ table->labels = eina_array_new(10);
+
+ if (!(text = _get_text_from_message_iter(t)))
+ {
+ _free_lookup_table(table);
+ table = NULL;
+ goto end;
+ }
+
+ DBG("Appending new label %s", text->text);
+ eina_array_push(table->labels, text);
+ }
+
+end:
+ return table;
+}
+
+static void
+_free_property(struct _ibus_property *property)
+{
+ if (!property)
+ return;
+
+ free(property->key);
+ free(property->icon);
+ _free_text(property->label);
+ _free_text(property->symbol);
+ _free_text(property->tooltip);
+ _free_eina_array(property->sub_properties, _free_property);
+ free(property);
+}
+
+static struct _ibus_property *
+_get_property_from_message_iter(Eldbus_Message_Iter *iter)
+{
+ struct _ibus_serializable ignore = { 0 };
+ struct _ibus_property *prop = calloc(1, sizeof(*prop));
+ Eldbus_Message_Iter *label = NULL, *symbol = NULL, *tooltip = NULL, *sub_props = NULL;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(prop, NULL);
+
+ DBG("Property iter signature '%s'", eldbus_message_iter_signature_get(iter));
+
+ if (!eldbus_message_iter_arguments_get(iter, "(sa{sv}suvsvbbuvv)",
+ &ignore.text, &ignore.variant,
+ &prop->key, &prop->type,
+ &label, &prop->icon, &tooltip,
+ &prop->sensitive, &prop->visible,
+ &prop->state, &sub_props, &symbol))
+ {
+ ERR("Error deserializing IBusProperty");
+ free(prop);
+ prop = NULL;
+ goto end;
+ }
+
+ DBG("Property :");
+ DBG("\tKey.............: '%s'", prop->key);
+ DBG("\tType............: '%d'", prop->type);
+ DBG("\tLabel...........: '%p'", label);
+ DBG("\tIcon............: '%s'", prop->icon);
+ DBG("\tTooltip.........: '%p'", tooltip);
+ DBG("\tSensitive.......: '%d'", prop->sensitive);
+ DBG("\tVisible.........: '%d'", prop->visible);
+ DBG("\tState...........: '%d'", prop->state);
+ DBG("\tSub Properties..: '%p'", sub_props);
+ DBG("\tSymbol..........: '%p'", symbol);
+
+ if (!label)
+ {
+ INF("Property has no label");
+ goto symbol;
+ }
+
+ if (!(prop->label = _get_text_from_message_iter(label)))
+ {
+ _free_property(prop);
+ prop = NULL;
+ goto end;
+ }
+
+symbol:
+ if (!symbol)
+ {
+ INF("Property has no symbol");
+ goto tooltip;
+ }
+
+ if (!(prop->symbol = _get_text_from_message_iter(symbol)))
+ {
+ _free_property(prop);
+ prop = NULL;
+ goto end;
+ }
+
+tooltip:
+ if (!tooltip)
+ {
+ INF("Property has no tooltip");
+ goto sub_props;
+ }
+
+ if (!(prop->tooltip = _get_text_from_message_iter(tooltip)))
+ {
+ _free_property(prop);
+ prop = NULL;
+ goto end;
+ }
+
+sub_props:
+ if (!sub_props)
+ {
+ INF("Property has no sub properties");
+ goto end;
+ }
+
+ prop->sub_properties = _get_properties_from_message_iter(sub_props);
+
+end:
+ return prop;
+}
+
+static Eina_Array *
+_get_properties_from_message_iter(Eldbus_Message_Iter *iter)
+{
+ Eina_Array *properties = NULL;
+ Eldbus_Message_Iter *props = NULL, *prop = NULL;
+ struct _ibus_serializable ignore = { 0 };
+ struct _ibus_property *property = NULL;
+
+ DBG("PropList iter signature '%s'", eldbus_message_iter_signature_get(iter));
+
+ if (!eldbus_message_iter_arguments_get(iter, "(sa{sv}av)", &ignore.text, &ignore.variant, &props))
+ {
+ ERR("Error deserializing IBusPropList");
+ goto end;
+ }
+
+ if (!props)
+ {
+ INF("PropList has no property");
+ goto end;
+ }
+
+ while (eldbus_message_iter_get_and_next(props, 'v', &prop))
+ {
+ if (!properties)
+ properties = eina_array_new(10);
+
+ if (!(property = _get_property_from_message_iter(prop)))
+ {
+ _free_eina_array(properties, _free_property);
+ properties = NULL;
+ goto end;
+ }
+
+ DBG("Appending new property %p", property);
+ eina_array_push(properties, property);
+ }
+
+end:
+ return properties;
+}
+
+static Eldbus_Message *
+_panel_update_preedit_text(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ Eldbus_Message_Iter *text = NULL;
+ unsigned int cursor_pos = 0;
+ Eina_Bool visible = 0;
+ struct _ibus_text *ibus_text;
+
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ if (!eldbus_message_arguments_get(msg, "vub", &text, &cursor_pos, &visible))
+ {
+ ERR("Error reading message arguments");
+ return NULL;
+ }
+
+ DBG("text: '%p', cursor_pos: '%d', visible: '%d')", text, cursor_pos, visible);
+
+ ibus_text = _get_text_from_message_iter(text);
+ DBG("Preedit text = '%s'", ibus_text->text);
+ _free_text(ibus_text);
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_show_preedit_text(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_hide_preedit_text(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_update_auxiliary_text(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ Eldbus_Message_Iter *text = NULL;
+ Eina_Bool visible = 0;
+ struct _ibus_text *ibus_text;
+
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ if (!eldbus_message_arguments_get(msg, "vb", &text, &visible))
+ {
+ ERR("Error reading message arguments");
+ return NULL;
+ }
+
+ DBG("text: '%p', visible: '%d'", text, visible);
+
+ ibus_text = _get_text_from_message_iter(text);
+ DBG("Auxiliary text = '%s'", ibus_text->text);
+ _free_text(ibus_text);
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_show_auxiliary_text(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_hide_auxiliary_text(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_update_lookup_table(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ Eldbus_Message_Iter *table = NULL;
+ Eina_Bool visible = 0;
+ struct _ibus_lookup_table *ibus_lookup_table;
+
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ if (!eldbus_message_arguments_get(msg, "vb", &table, &visible))
+ {
+ ERR("Error reading message arguments");
+ return NULL;
+ }
+
+ DBG("table: '%p', visible: '%d'", table, visible);
+
+ ibus_lookup_table = _get_lookup_table_from_message_iter(table);
+ _free_lookup_table(ibus_lookup_table);
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_show_lookup_table(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_hide_lookup_table(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ DBG("here");
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_cursor_up_lookup_table(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ DBG("here");
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_cursor_down_lookup_table(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_page_up_lookup_table(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_page_down_lookup_table(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_register_properties(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ Eldbus_Message_Iter *props = NULL;
+ Eina_Array *properties = NULL;
+
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ if (!eldbus_message_arguments_get(msg, "v", &props))
+ {
+ ERR("Error reading message arguments");
+ return NULL;
+ }
+
+ DBG("properties: '%p'", props);
+
+ properties = _get_properties_from_message_iter(props);
+ _free_eina_array(properties, _free_property);
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_update_property(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ Eldbus_Message_Iter *prop = NULL;
+
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ if (!eldbus_message_arguments_get(msg, "v", &prop))
+ {
+ ERR("Error reading message arguments");
+ return NULL;
+ }
+
+ DBG("property : '%p'", prop);
+ DBG("Property iter signature: %s", eldbus_message_iter_signature_get(prop));
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_focus_in(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_focus_out(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_set_cursor_location(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ int x = 0, y = 0, w = 0, h = 0;
+
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ if (!eldbus_message_arguments_get(msg, "iiii", &x, &y, &w, &h))
+ {
+ ERR("Error reading message arguments");
+ return NULL;
+ }
+
+ DBG("x: %d, y: %d, w: %d, h: %d", x, y, w, h);
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_reset(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_start_setup(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_state_changed(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_hide_language_bar(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ return NULL;
+}
+
+static Eldbus_Message *
+_panel_show_language_bar(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ PANEL_CHECK_MESSAGE_ERRORS(msg)
+
+ return NULL;
+}
+
+static const Eldbus_Method _wkb_ibus_panel_methods[] =
+{
+/* typedef struct _Eldbus_Method
+ * {
+ * const char *member;
+ * const Eldbus_Arg_Info *in;
+ * const Eldbus_Arg_Info *out;
+ * Eldbus_Method_Cb cb;
+ * unsigned int flags;
+ * } Eldbus_Method;
+ */
+ { .member = "UpdatePreeditText",
+ .in = ELDBUS_ARGS({"v", "text"}, {"u", "cursor_pos"}, {"b", "visible"}),
+ .cb = _panel_update_preedit_text, },
+
+ { .member = "ShowPreeditText",
+ .cb = _panel_show_preedit_text, },
+
+ { .member = "HidePreeditText",
+ .cb = _panel_hide_preedit_text, },
+
+ { .member = "UpdateAuxiliaryText",
+ .in = ELDBUS_ARGS({"v", "text"}, {"b", "visible"}),
+ .cb = _panel_update_auxiliary_text, },
+
+ { .member = "ShowAuxiliaryText",
+ .cb = _panel_show_auxiliary_text, },
+
+ { .member = "HideAuxiliaryText",
+ .cb = _panel_hide_auxiliary_text, },
+
+ { .member = "UpdateLookupTable",
+ .in = ELDBUS_ARGS({"v", "table"}, {"b", "visible"}),
+ .cb = _panel_update_lookup_table, },
+
+ { .member = "ShowLookupTable",
+ .cb = _panel_show_lookup_table, },
+
+ { .member = "HideLookupTable",
+ .cb = _panel_hide_lookup_table, },
+
+ { .member = "CursorUpLookupTable",
+ .cb = _panel_cursor_up_lookup_table, },
+
+ { .member = "CursorDownLookupTable",
+ .cb = _panel_cursor_down_lookup_table, },
+
+ { .member = "PageUpLookupTable",
+ .cb = _panel_page_up_lookup_table, },
+
+ { .member = "PageDownLookupTable",
+ .cb = _panel_page_down_lookup_table, },
+
+ { .member = "RegisterProperties",
+ .in = ELDBUS_ARGS({"v", "props"}),
+ .cb = _panel_register_properties, },
+
+ { .member = "UpdateProperty",
+ .in = ELDBUS_ARGS({"v", "prop"}),
+ .cb = _panel_update_property, },
+
+ { .member = "FocusIn",
+ .in = ELDBUS_ARGS({"o", "ic"}),
+ .cb = _panel_focus_in, },
+
+ { .member = "FocusOut",
+ .in = ELDBUS_ARGS({"o", "ic"}),
+ .cb = _panel_focus_out, },
+
+ { .member = "SetCursorLocation",
+ .in = ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"i", "w"}, {"i", "h"}),
+ .cb = _panel_set_cursor_location, },
+
+ { .member = "Reset",
+ .cb = _panel_reset, },
+
+ { .member = "StartSetup",
+ .cb = _panel_start_setup, },
+
+ { .member = "StateChanged",
+ .cb = _panel_state_changed, },
+
+ { .member = "HideLanguageBar",
+ .cb = _panel_hide_language_bar, },
+
+ { .member = "ShowLanguageBar",
+ .cb = _panel_show_language_bar, },
+
+ { NULL },
+};
+
+static const Eldbus_Signal _wkb_ibus_panel_signals[] =
+{
+/* typedef struct _Eldbus_Signal
+ * {
+ * const char *name;
+ * const Eldbus_Arg_Info *args;
+ * unsigned int flags;
+ * } Eldbus_Signal;
+ */
+ { .name = "CursorUp", },
+
+ { .name = "CursorDown", },
+
+ { .name = "PageUp", },
+
+ { .name = "PageDown", },
+
+ { .name = "PropertyActivate",
+ .args = ELDBUS_ARGS({"s", "prop_name"}, {"i", "prop_state"}),
+ .flags = 0, },
+
+ { .name = "PropertyShow",
+ .args = ELDBUS_ARGS({"s", "prop_name"}),
+ .flags = 0, },
+
+ { .name = "PropertyHide",
+ .args = ELDBUS_ARGS({"s", "prop_name"}),
+ .flags = 0, },
+
+ { .name = "CandidateClicked",
+ .args = ELDBUS_ARGS({"u", "index"}, {"u", "button"}, {"u", "state"}),
+ .flags = 0, },
+
+ { NULL },
+};
+
+static const Eldbus_Service_Interface_Desc _wkb_ibus_panel_interface =
+{
+ .interface = IBUS_INTERFACE_PANEL,
+ .methods = _wkb_ibus_panel_methods,
+ .signals = _wkb_ibus_panel_signals,
+};
+
+Eldbus_Service_Interface *
+wkb_ibus_panel_register(Eldbus_Connection *conn)
+{
+ return eldbus_service_interface_register(conn, IBUS_PATH_PANEL, &_wkb_ibus_panel_interface);
+}
+
--- /dev/null
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wkb-ibus.h"
+
+#define _GNU_SOURCE
+#include <signal.h>
+
+#include <Ecore.h>
+#include <Eldbus.h>
+
+static void
+_finish(int foo)
+{
+ printf("FINISH\n");
+ wkb_ibus_shutdown();
+}
+
+static Eina_Bool
+_connect_timer(void *data)
+{
+ return !wkb_ibus_connect();
+}
+
+int
+main (int argc, char *argv[])
+{
+ if (!ecore_init())
+ {
+ printf("Error initializing ecore");
+ return 1;
+ }
+
+ if (!eldbus_init())
+ {
+ printf("Error initializing eldbus");
+ return 1;
+ }
+
+ if (!wkb_ibus_init())
+ {
+ printf("Error initializing ibus");
+ return 1;
+ }
+
+ ecore_timer_add(1, _connect_timer, NULL);
+
+ signal(SIGTERM, _finish);
+ signal(SIGINT, _finish);
+
+ ecore_main_loop_begin();
+
+ eldbus_shutdown();
+ ecore_shutdown();
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <Ecore.h>
+#include <Eldbus.h>
+
+#include "wkb-ibus.h"
+
+int _wkb_ibus_log_dom = -1;
+
+#define CHECK_MESSAGE_ERRORS(_msg) \
+ do \
+ { \
+ const char *error, *error_msg; \
+ if (eldbus_message_error_get(_msg, &error, &error_msg)) \
+ { \
+ ERR("Dbus message error: %s: %s", error, error_msg); \
+ return; \
+ } \
+ DBG("Message '%s' with signature '%s'", eldbus_message_member_get(_msg), eldbus_message_signature_get(_msg)); \
+ } while (0);
+
+struct _wkb_ibus_service
+{
+ Eldbus_Service_Interface *interface;
+
+ Eldbus_Signal_Handler *name_acquired;
+ Eldbus_Signal_Handler *name_lost;
+};
+
+struct _wkb_ibus_context
+{
+ char *address;
+ Eldbus_Connection *conn;
+ Ecore_Exe *ibus_daemon;
+#if 0
+ struct _wkb_ibus_service config;
+#else
+ Eldbus_Proxy *config;
+#endif
+ struct _wkb_ibus_service panel;
+ int refcount;
+ Eina_Bool address_pending;
+};
+
+static struct _wkb_ibus_context *ctx = NULL;
+
+static void
+_wkb_config_value_changed_cb(void *data, const Eldbus_Message *msg)
+{
+ const char *section, name;
+ Eldbus_Message_Iter *value;
+
+ CHECK_MESSAGE_ERRORS(msg)
+
+ if (!eldbus_message_arguments_get(msg, "ssv", §ion, &name, &value))
+ {
+ ERR("Error reading message arguments");
+ return;
+ }
+
+ DBG("section: '%s', name: '%s', value: '%p", section, name, value);
+}
+
+static void
+_wkb_name_owner_changed_cb(void *data, const char *bus, const char *old_id, const char *new_id)
+{
+ DBG("NameOwnerChanged Bus=%s | old=%s | new=%s", bus, old_id, new_id);
+
+#if 0
+#else
+ if (strcmp(bus, IBUS_SERVICE_CONFIG) == 0)
+ {
+ if (*new_id)
+ {
+ Eldbus_Object *obj;
+
+ if (ctx->config)
+ return;
+
+ ecore_main_loop_glib_integrate();
+ obj = eldbus_object_get(ctx->conn, IBUS_SERVICE_CONFIG, IBUS_PATH_CONFIG);
+ ctx->config = eldbus_proxy_get(obj, IBUS_INTERFACE_CONFIG);
+ eldbus_proxy_signal_handler_add(ctx->config, "ValueChanged", _wkb_config_value_changed_cb, ctx);
+
+ INF("Got config proxy");
+ }
+ else
+ {
+ if (!ctx->config)
+ return;
+
+ eldbus_proxy_unref(ctx->config);
+ ctx->config = NULL;
+ }
+ }
+#endif
+}
+
+static void
+_wkb_name_acquired_cb(void *data, const Eldbus_Message *msg)
+{
+ const char *name;
+
+ DBG("NameAcquired");
+
+ CHECK_MESSAGE_ERRORS(msg)
+
+ if (!eldbus_message_arguments_get(msg, "s", &name))
+ {
+ ERR("Error reading message arguments");
+ return;
+ }
+
+ if (strcmp(name, IBUS_INTERFACE_PANEL) == 0)
+ {
+ if (!ctx->panel.interface)
+ {
+ ctx->panel.interface = wkb_ibus_panel_register(ctx->conn);
+ INF("Registering Panel Interface: %s", ctx->panel.interface ? "Success" : "Fail");
+ }
+ else
+ {
+ INF("Panel Interface already registered");
+ }
+ }
+#if 0
+ else if (strcmp(name, IBUS_INTERFACE_CONFIG) == 0)
+ {
+ if (!ctx->config.interface)
+ {
+ ctx->config.interface = wkb_ibus_config_register(ctx->conn);
+ INF("Registering Config Interface: %s", ctx->config.interface ? "Success" : "Fail");
+ }
+ else
+ {
+ INF("Config Interface already registered");
+ }
+ }
+#endif
+ else
+ {
+ WRN("Unexpected name %s", name);
+ }
+}
+
+static void
+_wkb_name_lost_cb(void *data, const Eldbus_Message *msg)
+{
+ const char *name;
+
+ DBG("NameLost");
+
+ CHECK_MESSAGE_ERRORS(msg)
+
+ if (!eldbus_message_arguments_get(msg, "s", &name))
+ {
+ ERR("Error reading message arguments");
+ return;
+ }
+
+ DBG("Name = %s", name);
+}
+
+static Eina_Bool
+_wkb_ibus_shutdown_idler(void *data)
+{
+ wkb_ibus_shutdown();
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_wkb_name_request_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
+{
+ const char *error, *error_msg;
+ unsigned int reply;
+
+ DBG("NameRequest callback");
+
+ if (eldbus_message_error_get(msg, &error, &error_msg))
+ {
+ ERR("DBus message error: %s: %s", error, error_msg);
+ goto error;
+ }
+
+ if (!eldbus_message_arguments_get(msg, "u", &reply))
+ {
+ ERR("Error reading message arguments");
+ goto error;
+ }
+
+ if (reply != ELDBUS_NAME_REQUEST_REPLY_PRIMARY_OWNER &&
+ reply != ELDBUS_NAME_REQUEST_REPLY_ALREADY_OWNER)
+ {
+ ERR("Not primary owner: reply=%d", reply);
+ goto error;
+ }
+
+ return;
+
+error:
+ ecore_idler_add(_wkb_ibus_shutdown_idler, NULL);
+}
+
+static void
+_wkb_name_release_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
+{
+ unsigned int reply;
+
+ CHECK_MESSAGE_ERRORS(msg)
+
+ if (!eldbus_message_arguments_get(msg, "u", &reply))
+ {
+ ERR("Error reading message arguments");
+ return;
+ }
+
+ if (reply != ELDBUS_NAME_RELEASE_REPLY_RELEASED)
+ {
+ ERR("Unexpected name release reply: %d", reply);
+ return;
+ }
+}
+
+static void
+_wkb_ibus_launch_daemon(void)
+{
+ DBG("Launching ibus-daemon");
+ ctx->ibus_daemon = ecore_exe_run("ibus-daemon -s", NULL);
+ if (!ctx->ibus_daemon)
+ {
+ ERR("Error launching ibus-daemon process");
+ return;
+ }
+}
+
+static Eina_Bool
+_wkb_ibus_query_address_cb(void *data, int type, void *event)
+{
+ Ecore_Exe_Event_Data *exe_data = (Ecore_Exe_Event_Data *)event;
+
+ if (strncmp(exe_data->data, "(null)", exe_data->size) == 0)
+ {
+ INF("IBus daemon is not running.");
+ _wkb_ibus_launch_daemon();
+ goto end;
+ }
+ else if (strstr(exe_data->data, "unknown command") != NULL)
+ {
+ ERR("ibus command does not support the 'address' argument");
+ goto end;
+ }
+
+ free(ctx->address);
+ ctx->address = strndup(exe_data->data, exe_data->size);
+
+end:
+ ecore_idler_add(ecore_exe_free, exe_data->exe);
+ ctx->address_pending = EINA_FALSE;
+ return ECORE_CALLBACK_DONE;
+}
+
+
+static void
+_wkb_ibus_query_address(void)
+{
+ const char *ibus_addr;
+ Ecore_Exe *ibus_exec = NULL;
+
+ /* Check for IBUS_ADDRESS environment variable */
+ if ((ibus_addr = getenv("IBUS_ADDRESS")) != NULL)
+ {
+ DBG("Got IBus address from IBUS_ADDRESS environment variable %s", ibus_addr);
+ ctx->address = strdup(ibus_addr);
+ return;
+ }
+
+ /* Get IBus address by invoking 'ibus address' from command line */
+ DBG("Querying IBus address from using 'ibus address' command");
+ ibus_exec = ecore_exe_pipe_run("ibus address",
+ ECORE_EXE_PIPE_READ |
+ ECORE_EXE_PIPE_READ_LINE_BUFFERED,
+ NULL);
+ if (!ibus_exec)
+ {
+ ERR("Unable to retrieve IBus address");
+ return;
+ }
+
+ ctx->address_pending = EINA_TRUE;
+ ecore_event_handler_add(ECORE_EXE_EVENT_DATA, _wkb_ibus_query_address_cb, NULL);
+}
+
+Eina_Bool
+wkb_ibus_connect(void)
+{
+ if (ctx->conn)
+ return EINA_TRUE;
+
+ if (!ctx->address)
+ {
+ INF("IBus address is not set.", ctx->address_pending);
+ if (!ctx->address_pending)
+ _wkb_ibus_query_address();
+
+ return EINA_FALSE;
+ }
+
+ INF("Connecting to IBus at address '%s'", ctx->address);
+ ctx->conn = eldbus_address_connection_get(ctx->address);
+
+ if (!ctx->conn)
+ {
+ ERR("Error connecting to IBus");
+ return EINA_FALSE;
+ }
+
+ /* Panel */
+ eldbus_name_owner_changed_callback_add(ctx->conn,
+ IBUS_SERVICE_PANEL,
+ _wkb_name_owner_changed_cb,
+ ctx, EINA_TRUE);
+
+ ctx->panel.name_acquired = eldbus_signal_handler_add(ctx->conn,
+ ELDBUS_FDO_BUS,
+ ELDBUS_FDO_PATH,
+ IBUS_INTERFACE_PANEL,
+ "NameAcquired",
+ _wkb_name_acquired_cb,
+ ctx);
+
+ ctx->panel.name_lost = eldbus_signal_handler_add(ctx->conn,
+ ELDBUS_FDO_BUS,
+ ELDBUS_FDO_PATH,
+ IBUS_INTERFACE_PANEL,
+ "NameLost",
+ _wkb_name_lost_cb,
+ ctx);
+
+ eldbus_name_request(ctx->conn, IBUS_SERVICE_PANEL,
+ ELDBUS_NAME_REQUEST_FLAG_REPLACE_EXISTING | ELDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE,
+ _wkb_name_request_cb, ctx);
+
+ /* Config */
+ eldbus_name_owner_changed_callback_add(ctx->conn,
+ IBUS_SERVICE_CONFIG,
+ _wkb_name_owner_changed_cb,
+ ctx, EINA_TRUE);
+
+#if 0
+ ctx->config.name_acquired = eldbus_signal_handler_add(ctx->conn,
+ ELDBUS_FDO_BUS,
+ ELDBUS_FDO_PATH,
+ IBUS_INTERFACE_CONFIG,
+ "NameAcquired",
+ _wkb_name_acquired_cb,
+ ctx);
+
+ ctx->config.name_lost = eldbus_signal_handler_add(ctx->conn,
+ ELDBUS_FDO_BUS,
+ ELDBUS_FDO_PATH,
+ IBUS_INTERFACE_CONFIG,
+ "NameLost",
+ _wkb_name_lost_cb,
+ ctx);
+
+ eldbus_name_request(ctx->conn, IBUS_SERVICE_CONFIG,
+ ELDBUS_NAME_REQUEST_FLAG_REPLACE_EXISTING | ELDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE,
+ _wkb_name_request_cb, ctx);
+#endif
+ return EINA_TRUE;
+}
+
+
+int
+wkb_ibus_init(void)
+{
+ if (ctx && ctx->refcount > 0)
+ goto end;
+
+ if (!eina_init())
+ {
+ fprintf(stderr, "Error initializing Eina\n");
+ return 0;
+ }
+
+ _wkb_ibus_log_dom = eina_log_domain_register("wkb-ibus", EINA_COLOR_LIGHTCYAN);
+ if (_wkb_ibus_log_dom < 0)
+ {
+ EINA_LOG_ERR("Unable to register 'wkb-ibus' log domain");
+ eina_shutdown();
+ return 0;
+ }
+
+ if (!ctx && !(ctx = calloc(1, sizeof(*ctx))))
+ {
+ ERR("Error calloc\n");
+ eina_shutdown();
+ return 0;
+ }
+
+ _wkb_ibus_query_address();
+
+end:
+ return ++ctx->refcount;
+}
+
+void
+wkb_ibus_shutdown(void)
+{
+ if (!ctx)
+ {
+ fprintf(stderr, "Not initialized\n");
+ return;
+ }
+
+ if (ctx->refcount == 0)
+ {
+ ERR("Refcount already 0");
+ goto end;
+ }
+
+ if (--(ctx->refcount) != 0)
+ return;
+
+ DBG("Shutting down");
+ wkb_ibus_disconnect();
+
+ free(ctx->address);
+
+ if (ctx->ibus_daemon)
+ {
+ DBG("Terminating ibus-daemon");
+ ecore_exe_terminate(ctx->ibus_daemon);
+ ecore_exe_free(ctx->ibus_daemon);
+ }
+
+end:
+ free(ctx);
+ ctx = NULL;
+
+ ecore_main_loop_quit();
+ DBG("Main loop quit");
+}
+
+void
+wkb_ibus_disconnect(void)
+{
+ if (!ctx->conn)
+ {
+ ERR("Not connected");
+ return;
+ }
+
+ DBG("Disconnect");
+
+ if (ctx->panel.interface)
+ {
+ eldbus_name_release(ctx->conn, IBUS_SERVICE_PANEL, _wkb_name_release_cb, ctx);
+ eldbus_signal_handler_del(ctx->panel.name_acquired);
+ eldbus_signal_handler_del(ctx->panel.name_lost);
+ eldbus_service_interface_unregister(ctx->panel.interface);
+ ctx->panel.interface = NULL;
+ }
+
+ if (ctx->config)
+ {
+ eldbus_proxy_unref(ctx->config);
+ ctx->config = NULL;
+ }
+#if 0
+ if (ctx->config.interface)
+ {
+ eldbus_name_release(ctx->conn, IBUS_SERVICE_CONFIG, _wkb_name_release_cb, ctx);
+ eldbus_signal_handler_del(ctx->config.name_acquired);
+ eldbus_signal_handler_del(ctx->config.name_lost);
+ eldbus_service_interface_unregister(ctx->config.interface);
+ ctx->config.interface = NULL;
+ }
+#endif
+
+ eldbus_connection_unref(ctx->conn);
+}
+
+Eina_Bool
+wkb_ibus_is_connected(void)
+{
+ return ctx->conn != NULL;
+}
--- /dev/null
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _WKB_IBUS_H_
+#define _WKB_IBUS_H_
+
+#include <Eina.h>
+#include <Eldbus.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int _wkb_ibus_log_dom;
+#define DBG(...) EINA_LOG_DOM_DBG(_wkb_ibus_log_dom, __VA_ARGS__)
+#define INF(...) EINA_LOG_DOM_INFO(_wkb_ibus_log_dom, __VA_ARGS__)
+#define WRN(...) EINA_LOG_DOM_WARN(_wkb_ibus_log_dom, __VA_ARGS__)
+#define ERR(...) EINA_LOG_DOM_ERR(_wkb_ibus_log_dom, __VA_ARGS__)
+#define CRITICAL(...) EINA_LOG_DOM_CRIT(_wkb_ibus_log_dom, __VA_ARGS__)
+
+
+/* from ibusshare.h */
+#define IBUS_SERVICE_IBUS "org.freedesktop.IBus"
+#define IBUS_SERVICE_PANEL "org.freedesktop.IBus.Panel"
+#define IBUS_SERVICE_CONFIG "org.freedesktop.IBus.Config"
+
+#define IBUS_PATH_IBUS "/org/freedesktop/IBus"
+#define IBUS_PATH_PANEL "/org/freedesktop/IBus/Panel"
+#define IBUS_PATH_CONFIG "/org/freedesktop/IBus/Config"
+
+#define IBUS_INTERFACE_IBUS "org.freedesktop.IBus"
+#define IBUS_INTERFACE_PANEL "org.freedesktop.IBus.Panel"
+#define IBUS_INTERFACE_CONFIG "org.freedesktop.IBus.Config"
+
+
+int wkb_ibus_init(void);
+void wkb_ibus_shutdown(void);
+
+Eina_Bool wkb_ibus_connect(void);
+void wkb_ibus_disconnect(void);
+
+Eina_Bool wkb_ibus_is_connected(void);
+
+/* Panel */
+Eldbus_Service_Interface * wkb_ibus_panel_register(Eldbus_Connection *conn);
+
+/* Config */
+#if 0
+Eldbus_Service_Interface * wkb_ibus_config_register(Eldbus_Connection *conn);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _WKB_IBUS_H_ */
--- /dev/null
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <Eina.h>
+#include <Ecore.h>
+#include <Ecore_Wayland.h>
+#include <Ecore_Evas.h>
+#include <Edje.h>
+
+#include <linux/input.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "input-method-client-protocol.h"
+#include "text-client-protocol.h"
+
+struct weekeyboard
+{
+ Ecore_Evas *ee;
+ Ecore_Wl_Window *win;
+ Evas_Object *edje_obj;
+ const char *ee_engine;
+ char **ignore_keys;
+
+ struct wl_surface *surface;
+ struct wl_input_panel *ip;
+ struct wl_input_method *im;
+ struct wl_output *output;
+ struct wl_input_method_context *im_ctx;
+
+ char *surrounding_text;
+ char *preedit_str;
+ char *language;
+
+ uint32_t text_direction;
+ uint32_t preedit_style;
+ uint32_t content_hint;
+ uint32_t content_purpose;
+ uint32_t serial;
+ uint32_t surrounding_cursor;
+
+ Eina_Bool context_changed;
+};
+
+static void
+_cb_wkb_delete_request(Ecore_Evas *ee EINA_UNUSED)
+{
+ ecore_main_loop_quit();
+}
+
+static char *
+_wkb_insert_text(const char *text, uint32_t offset, const char *insert)
+{
+ char *new_text = malloc(strlen(text) + strlen(insert) + 1);
+
+ strncat(new_text, text, offset);
+ new_text[offset] = '\0';
+ strcat(new_text, insert);
+ strcat(new_text, text + offset);
+
+ return new_text;
+}
+
+static void
+_wkb_commit_preedit_str(struct weekeyboard *wkb)
+{
+ char *surrounding_text;
+
+ if (!wkb->preedit_str || !strlen(wkb->preedit_str) == 0)
+ return;
+
+ wl_input_method_context_cursor_position(wkb->im_ctx, 0, 0);
+ wl_input_method_context_commit_string(wkb->im_ctx, wkb->serial, wkb->preedit_str);
+
+ if (wkb->surrounding_text)
+ {
+ surrounding_text = _wkb_insert_text(wkb->surrounding_text, wkb->surrounding_cursor, wkb->preedit_str);
+ free(wkb->surrounding_text);
+ wkb->surrounding_text = surrounding_text;
+ wkb->surrounding_cursor += strlen(wkb->preedit_str);
+ }
+ else
+ {
+ wkb->surrounding_text = strdup(wkb->preedit_str);
+ wkb->surrounding_cursor = strlen(wkb->preedit_str);
+ }
+
+ free(wkb->preedit_str);
+ wkb->preedit_str = strdup("");
+}
+
+static void
+_wkb_send_preedit_str(struct weekeyboard *wkb, int cursor)
+{
+ unsigned int index = strlen(wkb->preedit_str);
+
+ if (wkb->preedit_style)
+ wl_input_method_context_preedit_styling(wkb->im_ctx, 0, strlen(wkb->preedit_str), wkb->preedit_style);
+
+ if (cursor > 0)
+ index = cursor;
+
+ wl_input_method_context_preedit_cursor(wkb->im_ctx, index);
+ wl_input_method_context_preedit_string(wkb->im_ctx, wkb->serial, wkb->preedit_str, wkb->preedit_str);
+}
+
+static void
+_wkb_update_preedit_str(struct weekeyboard *wkb, const char *key)
+{
+ char *tmp;
+
+ if (!wkb->preedit_str)
+ wkb->preedit_str = strdup("");
+
+ tmp = calloc(1, strlen(wkb->preedit_str) + strlen(key) + 1);
+ sprintf(tmp, "%s%s", wkb->preedit_str, key);
+ free(wkb->preedit_str);
+ wkb->preedit_str = tmp;
+
+ if (strcmp(key, " ") == 0)
+ _wkb_commit_preedit_str(wkb);
+ else
+ _wkb_send_preedit_str(wkb, -1);
+}
+
+static Eina_Bool
+_wkb_ignore_key(struct weekeyboard *wkb, const char *key)
+{
+ int i;
+
+ if (!wkb->ignore_keys)
+ return EINA_FALSE;
+
+ for (i = 0; wkb->ignore_keys[i] != NULL; i++)
+ if (!strcmp(key, wkb->ignore_keys[i]))
+ return EINA_TRUE;
+
+ return EINA_FALSE;
+}
+
+static void
+_cb_wkb_on_key_down(void *data, Evas_Object *obj, const char *emission EINA_UNUSED, const char *source)
+{
+ struct weekeyboard *wkb = data;
+ char *src;
+ const char *key;
+
+ src = strdup(source);
+ key = strtok(src, ":"); /* ignore group */
+ key = strtok(NULL, ":");
+ if (key == NULL)
+ key = ":";
+
+ if (_wkb_ignore_key(wkb, key))
+ {
+ printf("Ignoring key '%s'\n", key);
+ goto end;
+ }
+ else if (strcmp(key, "backspace") == 0)
+ {
+ if (strlen(wkb->preedit_str) == 0)
+ wl_input_method_context_delete_surrounding_text(wkb->im_ctx, -1, 1);
+ else
+ {
+ wkb->preedit_str[strlen(wkb->preedit_str) - 1] = '\0';
+ _wkb_send_preedit_str(wkb, -1);
+ }
+
+ goto end;
+ }
+ else if (strcmp(key, "enter") == 0)
+ {
+ _wkb_commit_preedit_str(wkb);
+ /* wl_input_method_context_keysym(wkb->im_ctx, wkb->serial, time, XKB_KEY_Return, key_state, mod_mask); */
+ goto end;
+ }
+ else if (strcmp(key, "space") == 0)
+ {
+ key = " ";
+ }
+
+ printf("KEY = '%s'\n", key);
+
+ _wkb_update_preedit_str(wkb, key);
+
+end:
+ free(src);
+}
+
+static void
+_wkb_im_ctx_surrounding_text(void *data, struct wl_input_method_context *im_ctx, const char *text, uint32_t cursor, uint32_t anchor)
+{
+ struct weekeyboard *wkb = data;
+
+ printf("%s()\n", __FUNCTION__);
+ free(wkb->surrounding_text);
+ wkb->surrounding_text = strdup(text);
+ wkb->surrounding_cursor = cursor;
+}
+
+static void
+_wkb_im_ctx_reset(void *data, struct wl_input_method_context *im_ctx)
+{
+ struct weekeyboard *wkb = data;
+
+ printf("%s()\n", __FUNCTION__);
+
+ if (strlen(wkb->preedit_str))
+ {
+ free(wkb->preedit_str);
+ wkb->preedit_str = strdup("");
+ }
+}
+
+static void
+_wkb_im_ctx_content_type(void *data, struct wl_input_method_context *im_ctx, uint32_t hint, uint32_t purpose)
+{
+ struct weekeyboard *wkb = data;
+
+ printf("%s(): im_context = %p hint = %d purpose = %d\n", __FUNCTION__, im_ctx, hint, purpose);
+
+ if (!wkb->context_changed)
+ return;
+
+ switch (purpose)
+ {
+ case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
+ case WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER:
+ {
+ edje_object_signal_emit(wkb->edje_obj, "show,numeric", "");
+ break;
+ }
+ default:
+ {
+ edje_object_signal_emit(wkb->edje_obj, "show,alphanumeric", "");
+ break;
+ }
+ }
+
+ wkb->content_hint = hint;
+ wkb->content_purpose = purpose;
+
+ wkb->context_changed = EINA_FALSE;
+}
+
+static void
+_wkb_im_ctx_invoke_action(void *data, struct wl_input_method_context *im_ctx, uint32_t button, uint32_t index)
+{
+ struct weekeyboard *wkb = data;
+
+ printf("%s()\n", __FUNCTION__);
+ if (button != BTN_LEFT)
+ return;
+
+ _wkb_send_preedit_str(wkb, index);
+}
+
+static void
+_wkb_im_ctx_commit_state(void *data, struct wl_input_method_context *im_ctx, uint32_t serial)
+{
+ struct weekeyboard *wkb = data;
+
+ printf("%s()\n", __FUNCTION__);
+ if (wkb->surrounding_text)
+ fprintf(stderr, "Surrounding text updated: %s\n", wkb->surrounding_text);
+
+ wkb->serial = serial;
+ /* FIXME */
+ wl_input_method_context_language(im_ctx, wkb->serial, "en");//wkb->language);
+ wl_input_method_context_text_direction(im_ctx, wkb->serial, WL_TEXT_INPUT_TEXT_DIRECTION_LTR);//wkb->text_direction);
+}
+
+static void
+_wkb_im_ctx_preferred_language(void *data, struct wl_input_method_context *im_ctx, const char *language)
+{
+ struct weekeyboard *wkb = data;
+
+ if (language && wkb->language && !strcmp(language, wkb->language))
+ return;
+
+ if (wkb->language)
+ {
+ free(wkb->language);
+ wkb->language = NULL;
+ }
+
+ if (language)
+ {
+ wkb->language = strdup(language);
+ printf("Language changed, new: '%s\n", language);
+ }
+}
+
+static const struct wl_input_method_context_listener wkb_im_context_listener = {
+ _wkb_im_ctx_surrounding_text,
+ _wkb_im_ctx_reset,
+ _wkb_im_ctx_content_type,
+ _wkb_im_ctx_invoke_action,
+ _wkb_im_ctx_commit_state,
+ _wkb_im_ctx_preferred_language,
+};
+
+static void
+_wkb_im_activate(void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx)
+{
+ struct weekeyboard *wkb = data;
+ struct wl_array modifiers_map;
+
+ if (wkb->im_ctx)
+ wl_input_method_context_destroy(wkb->im_ctx);
+
+ if (wkb->preedit_str)
+ free(wkb->preedit_str);
+
+ wkb->preedit_str = strdup("");
+ wkb->content_hint = WL_TEXT_INPUT_CONTENT_HINT_NONE;
+ wkb->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
+ free(wkb->language);
+ wkb->language = NULL;
+ free(wkb->surrounding_text);
+ wkb->surrounding_text = NULL;
+ wkb->serial = 0;
+
+ wkb->im_ctx = im_ctx;
+ wl_input_method_context_add_listener(im_ctx, &wkb_im_context_listener, wkb);
+
+ /*
+ wl_array_init(&modifiers_map);
+
+ keysym_modifiers_add(&modifiers_map, "Shift");
+ keysym_modifiers_add(&modifiers_map, "Control");
+ keysym_modifiers_add(&modifiers_map, "Mod1");
+
+ wl_input_method_context_modifiers_map(im_ctx, &modifiers_map);
+
+ wkb->keysym.shift_mask = keysym_modifiers_get_mask(&modifiers_map, "Shift");
+
+ wl_array_release(&modifiers_map);
+ */
+
+ /* FIXME */
+ wl_input_method_context_language(im_ctx, wkb->serial, "en");//wkb->language);
+ wl_input_method_context_text_direction(im_ctx, wkb->serial, WL_TEXT_INPUT_TEXT_DIRECTION_LTR);//wkb->text_direction);
+
+ wkb->context_changed = EINA_TRUE;
+ evas_object_show(wkb->edje_obj);
+}
+
+static void
+_wkb_im_deactivate(void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx)
+{
+ struct weekeyboard *wkb = data;
+
+ if (!wkb->im_ctx)
+ return;
+
+ wl_input_method_context_destroy(wkb->im_ctx);
+ wkb->im_ctx = NULL;
+ evas_object_hide(wkb->edje_obj);
+}
+
+static const struct wl_input_method_listener wkb_im_listener = {
+ _wkb_im_activate,
+ _wkb_im_deactivate
+};
+
+
+static Eina_Bool
+_wkb_ui_setup(struct weekeyboard *wkb)
+{
+ char path[PATH_MAX];
+ Evas *evas;
+ Evas_Coord w, h;
+ char *ignore_keys;
+
+ ecore_evas_alpha_set(wkb->ee, EINA_TRUE);
+ ecore_evas_title_set(wkb->ee, "EFL virtual keyboard");
+
+ evas = ecore_evas_get(wkb->ee);
+ wkb->edje_obj = edje_object_add(evas);
+ /*ecore_evas_object_associate(wkb->ee, edje_obj, ECORE_EVAS_OBJECT_ASSOCIATE_BASE);*/
+
+ /* Check which theme we should use according to the screen width */
+ ecore_wl_screen_size_get(&w, &h);
+ if (w >= 720)
+ w = 720;
+ else
+ w = 600;
+
+ sprintf(path, PKGDATADIR"/default_%d.edj", w);
+ printf("Loading edje file: '%s'\n", path);
+
+ if (!edje_object_file_set(wkb->edje_obj, path, "main"))
+ {
+ int err = edje_object_load_error_get(wkb->edje_obj);
+ fprintf(stderr, "error loading the edje file:%s\n", edje_load_error_str(err));
+ return EINA_FALSE;
+ }
+
+ edje_object_size_min_get(wkb->edje_obj, &w, &h);
+ if (w == 0 || h == 0)
+ {
+ edje_object_size_min_restricted_calc(wkb->edje_obj, &w, &h, w, h);
+ if (w == 0 || h == 0)
+ edje_object_parts_extends_calc(wkb->edje_obj, NULL, NULL, &w, &h);
+ }
+
+ ecore_evas_move_resize(wkb->ee, 0, 0, w, h);
+ evas_object_move(wkb->edje_obj, 0, 0);
+ evas_object_resize(wkb->edje_obj, w, h);
+ evas_object_size_hint_min_set(wkb->edje_obj, w, h);
+ evas_object_size_hint_max_set(wkb->edje_obj, w, h);
+
+ edje_object_signal_callback_add(wkb->edje_obj, "key_down", "*", _cb_wkb_on_key_down, wkb);
+ ecore_evas_callback_delete_request_set(wkb->ee, _cb_wkb_delete_request);
+
+ /*
+ * The keyboard surface is bigger than it appears so that we can show the
+ * key pressed animation without requiring the use of subsurfaces. Here we
+ * resize the input region of the surface to match the keyboard background
+ * image, so that we can pass mouse events to the surfaces that may be
+ * located below the keyboard.
+ */
+ if (wkb->win)
+ {
+ int x, y, w, h;
+ struct wl_region *input = wl_compositor_create_region(wkb->win->display->wl.compositor);
+
+ edje_object_part_geometry_get(wkb->edje_obj, "background", &x, &y, &w, &h);
+ wl_region_add(input, x, y, w, h);
+ wl_surface_set_input_region(wkb->surface, input);
+ wl_region_destroy(input);
+ }
+
+ /* special keys */
+ ignore_keys = edje_file_data_get(path, "ignore-keys");
+ if (!ignore_keys)
+ {
+ printf("Special keys file not found in '%s'\n", path);
+ goto end;
+ }
+
+ printf("Got ignore keys = %s\n", ignore_keys);
+ wkb->ignore_keys = eina_str_split(ignore_keys, "\n", 0);
+ free(ignore_keys);
+
+end:
+ ecore_evas_show(wkb->ee);
+ return EINA_TRUE;
+}
+
+static void
+_wkb_setup(struct weekeyboard *wkb)
+{
+ struct wl_list *globals;
+ struct wl_registry *registry;
+ Ecore_Wl_Global *global;
+
+ struct wl_input_panel_surface *ips;
+
+ globals = ecore_wl_globals_get();
+ registry = ecore_wl_registry_get();
+ wl_list_for_each(global, globals, link)
+ {
+ if (strcmp(global->interface, "wl_input_panel") == 0)
+ wkb->ip = wl_registry_bind(registry, global->id, &wl_input_panel_interface, 1);
+ else if (strcmp(global->interface, "wl_input_method") == 0)
+ wkb->im = wl_registry_bind(registry, global->id, &wl_input_method_interface, 1);
+ else if (strcmp(global->interface, "wl_output") == 0)
+ wkb->output = wl_registry_bind(registry, global->id, &wl_output_interface, 1);
+ }
+
+ /* Set input panel surface */
+ wkb->win = ecore_evas_wayland_window_get(wkb->ee);
+ ecore_wl_window_type_set(wkb->win, ECORE_WL_WINDOW_TYPE_NONE);
+ wkb->surface = ecore_wl_window_surface_create(wkb->win);
+ ips = wl_input_panel_get_input_panel_surface(wkb->ip, wkb->surface);
+ wl_input_panel_surface_set_toplevel(ips, wkb->output, WL_INPUT_PANEL_SURFACE_POSITION_CENTER_BOTTOM);
+
+ /* Input method listener */
+ wl_input_method_add_listener(wkb->im, &wkb_im_listener, wkb);
+}
+
+static void
+_wkb_free(struct weekeyboard *wkb)
+{
+ if (wkb->im_ctx)
+ wl_input_method_context_destroy(wkb->im_ctx);
+
+ if (wkb->ignore_keys)
+ {
+ free(*wkb->ignore_keys);
+ free(wkb->ignore_keys);
+ }
+
+ evas_object_del(wkb->edje_obj);
+ free(wkb->preedit_str);
+ free(wkb->surrounding_text);
+}
+
+static Eina_Bool
+_wkb_check_evas_engine(struct weekeyboard *wkb)
+{
+ Eina_Bool ret = EINA_FALSE;
+ char *env = getenv("ECORE_EVAS_ENGINE");
+
+ if (!env)
+ {
+ if (ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_WAYLAND_SHM))
+ env = "wayland_shm";
+ else if (ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_WAYLAND_EGL))
+ env = "wayland_egl";
+ else
+ {
+ printf("ERROR: Ecore_Evas does must be compiled with support for Wayland engines\n");
+ goto err;
+ }
+ }
+ else if (strcmp(env, "wayland_shm") != 0 && strcmp(env, "wayland_egl") != 0)
+ {
+ printf("ERROR: ECORE_EVAS_ENGINE must be set to either 'wayland_shm' or 'wayland_egl'\n");
+ goto err;
+ }
+
+ wkb->ee_engine = env;
+ ret = EINA_TRUE;
+
+err:
+ return ret;
+}
+
+int
+main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
+{
+ struct weekeyboard wkb = {0};
+ int ret = EXIT_FAILURE;
+
+ if (!ecore_init())
+ return ret;
+
+ if (!ecore_evas_init())
+ goto ecore_err;
+
+ if (!edje_init())
+ goto ee_err;
+
+ if (!_wkb_check_evas_engine(&wkb))
+ goto edj_err;
+
+ printf("SELECTED ENGINE = %s\n", wkb.ee_engine);
+ wkb.ee = ecore_evas_new(wkb.ee_engine, 0, 0, 1, 1, "frame=0");
+
+ if (!wkb.ee)
+ {
+ printf("ERROR: Unable to create Ecore_Evas object\n");
+ goto edj_err;
+ }
+
+ _wkb_setup(&wkb);
+
+ if (!_wkb_ui_setup(&wkb))
+ goto end;
+
+ ecore_main_loop_begin();
+
+ ret = EXIT_SUCCESS;
+
+ _wkb_free(&wkb);
+
+end:
+ ecore_evas_free(wkb.ee);
+
+edj_err:
+ edje_shutdown();
+
+ee_err:
+ ecore_evas_shutdown();
+
+ecore_err:
+ ecore_shutdown();
+
+ return ret;
+}