fi
# Check EFL library
-PKG_CHECK_MODULES(EFL, [elementary ecore-x evas ecore ecore-evas ecore-file edje ecore-input ecore-ipc ecore-imf],
+PKG_CHECK_MODULES(EFL, [elementary evas ecore ecore-evas ecore-file edje ecore-input ecore-ipc ecore-imf],
[ISF_HAS_EFL=yes],
[ISF_HAS_EFL=no])
+PKG_CHECK_MODULES(ECOREX, [ecore-x],
+ [ISF_HAS_ECOREX=yes],
+ [ISF_HAS_ECOREX=no])
+
+PKG_CHECK_MODULES(WAYLAND, [ecore-wayland wayland-client >= 1.2.0 xkbcommon],
+ [ISF_HAS_ECOREWL=yes],
+ [ISF_HAS_ECOREWL=no])
+
if test "$ISF_HAS_EFL" = "yes"; then
EFL_LIBDIR=`$PKG_CONFIG --variable=libdir ecore-imf`
if test -z "$EFL_LIBDIR)"; then
PKG_CHECK_MODULES(EFL_ASSIST, [efl-assist])
# Check x11 library
-PKG_CHECK_MODULES(X11, [x11])
+PKG_CHECK_MODULES(X11, [x11],
+ [ISF_HAS_X11=yes],
+ [ISF_HAS_X11=no])
# Check ui-gadget library
PKG_CHECK_MODULES(UIGADGET, [ui-gadget-1],
[ISF_HAS_UIGADGET=no])
# Check utilX library
-PKG_CHECK_MODULES(UTILX, [utilX])
+PKG_CHECK_MODULES(UTILX, [utilX],
+ [ISF_HAS_UTILX=yes],
+ [ISF_HAS_UTILX=no])
# Check appcore-efl library
PKG_CHECK_MODULES(APPCORE_EFL, [appcore-efl])
enable_panel_efl=no,
enable_panel_efl=check)
+AC_ARG_ENABLE(wsm-efl,
+ [ --disable-wsm-efl Do not build EFL Wsm],
+ enable_wsm_efl=no,
+ enable_wsm_efl=check)
+
+AC_ARG_ENABLE(wsc-efl,
+ [ --disable-wsc-efl Do not build EFL Wsc],
+ enable_wsc_efl=no,
+ enable_wsc_efl=yes)
+
AC_ARG_ENABLE(setting-efl,
[ --disable-setting-efl Do not build EFL Setting],
enable_setting_efl=no,
enable_efl_immodule=no
fi
+if test "$enable_wsc_efl" = "yes" -a "$ISF_HAS_EFL" = "yes"; then
+ ISF_BUILD_WSC_EFL=1
+else
+ ISF_BUILD_WSC_EFL=0
+ enable_wsc_efl=no
+fi
+
ISF_BUILD_PANEL_EFL=0
if test "$enable_panel_efl" != "no"; then
enable_panel_efl=no
fi
fi
+ISF_BUILD_WSM_EFL=0
+if test "$enable_wsm_efl" != "no"; then
+ enable_wsm_efl=no
+ if test "$ISF_HAS_EFL" = "yes"; then
+ ISF_BUILD_WSM_EFL=1
+ enable_wsm_efl=yes
+ fi
+fi
+
ISF_BUILD_SETTING_EFL=0
if test "$enable_setting_efl" != "no"; then
enable_setting_efl=no
SCIM_BUILD_GTK_UTILS=0
fi
+AM_CONDITIONAL(HAVE_X,
+ [test "$have_x" = "yes"])
+
AM_CONDITIONAL(SCIM_LD_VERSION_SCRIPT,
[test "$enable_ld_version_script" = "yes"])
AM_CONDITIONAL(ISF_BUILD_EFL_IMMODULE,
[test "$enable_efl_immodule" = "yes"])
+AM_CONDITIONAL(ISF_BUILD_WSC_EFL,
+ [test "$enable_wsc_efl" = "yes"])
+
AM_CONDITIONAL(ISF_BUILD_PANEL_EFL,
[test "$enable_panel_efl" = "yes"])
+AM_CONDITIONAL(ISF_BUILD_WSM_EFL,
+ [test "$enable_wsm_efl" = "yes"])
+
AM_CONDITIONAL(ISF_BUILD_SETTING_EFL,
[test "$enable_setting_efl" = "yes"])
ism/extras/gtk2_immodule/Makefile
ism/extras/efl_immodule/Makefile
ism/extras/efl_panel/Makefile
+ ism/extras/efl_wsm/Makefile
+ ism/extras/efl_wsc/Makefile
ism/demos/Makefile
intltool-extract
intltool-merge
EFL IMModule $enable_efl_immodule
EFL IMModule dir $EFL_IM_MODULEDIR
EFL Panel GUI $enable_panel_efl
+ EFL Wsm GUI $enable_wsm_efl
+ EFL Wsc GUI $enable_wsc_efl
EFL Setting $enable_setting_efl
Enable TrayIcon $enable_tray_icon
/SupportedUnicodeLocales = en_US.UTF-8
/DefaultPanelProgram = isf-panel-efl
+/DefaultPanelProgram2 = isf-wsm-efl
/DefaultConfigModule = simple
/DefaultSocketFrontEndAddress = local:/tmp/scim-socket-frontend
/DefaultSocketIMEngineAddress = local:/tmp/scim-socket-frontend
isf_ondemand_efl.cpp
isf_demo_efl_CXXFLAGS = @EFL_CFLAGS@ \
+ @ECOREX_CFLAGS@ \
@APPCORE_EFL_CFLAGS@ \
@UIGADGET_CFLAGS@ \
@VCONF_CFLAGS@ \
@EFL_ASSIST_CFLAGS@
isf_demo_efl_LDFLAGS = @EFL_LIBS@ @LTLIBINTL@ -rpath $(libdir) \
+ @ECOREX_LIBS@ \
@VCONF_LIBS@ \
@APPCORE_EFL_LIBS@ \
@UIGADGET_LIBS@ \
MAINTAINERCLEANFILES = Makefile.in
CLEANFILES = *.bak
-SUBDIRS = gtk2_immodule efl_panel efl_immodule
+SUBDIRS = gtk2_immodule efl_panel efl_immodule efl_wsm efl_wsc
isf_imf_control.cpp
libisf_imf_module_la_CXXFLAGS = @EFL_CFLAGS@ \
+ @ECOREX_CFLAGS@ \
@UTILX_CFLAGS@ \
@VCONF_CFLAGS@ \
@DLOG_CFLAGS@
libisf_imf_module_la_LIBADD = -lstdc++ \
$(LD_VERSION_SCRIPT_OPTION) \
@EFL_LIBS@ \
+ @ECOREX_LIBS@ \
@UTILX_LIBS@ \
@VCONF_LIBS@ \
@DLOG_LIBS@ \
isf_panel_efl_SOURCES += minicontrol.cpp
endif
-isf_panel_efl_CXXFLAGS = @EFL_CFLAGS@ @EFL_ASSIST_CFLAGS@ @VCONF_CFLAGS@ @X11_CFLAGS@ @PRIVILEGE_CONTROL_CFLAGS@ @DLOG_CFLAGS@ \
+isf_panel_efl_CXXFLAGS = @EFL_CFLAGS@ @ECOREX_CFLAGS@ @EFL_ASSIST_CFLAGS@ @VCONF_CFLAGS@ @X11_CFLAGS@ @PRIVILEGE_CONTROL_CFLAGS@ @DLOG_CFLAGS@ \
@MINICONTROL_PROVIDER_CFLAGS@ @NOTIFICATION_CFLAGS@ @TTS_CFLAGS@ @EDBUS_CFLAGS@ @BLUETOOTH_CFLAGS@ @FEEDBACK_CFLAGS@
isf_panel_efl_LDFLAGS = @EFL_LIBS@ @LTLIBINTL@ -rpath $(libdir) \
+ @ECOREX_LIBS@ \
@EFL_ASSIST_LIBS@ \
@VCONF_LIBS@ \
@X11_LIBS@ \
--- /dev/null
+MAINTAINERCLEANFILES = Makefile.in
+CLEANFILES = *.bak *.edj
+
+INCLUDES = -I$(top_builddir) \
+ -I$(top_builddir)/ism/src \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/ism/src \
+ -I$(top_srcdir)/ism/intl \
+ -I$(top_srcdir)/ism/data \
+ -I$(top_srcdir)/ism/utils \
+ -I$(includedir) \
+ -DSCIM_DATADIR=\"@SCIM_DATADIR@\" \
+ -DSCIM_LOCALEDIR=\"@SCIM_LOCALEDIR@\" \
+ -DSCIM_SYSCONFDIR=\"@SCIM_SYSCONFDIR@\" \
+ -DSCIM_LIBEXECDIR=\"@SCIM_LIBEXECDIR@\" \
+ -DSCIM_ICONDIR=\"@SCIM_ICONDIR@\" \
+ -DSCIM_MODULE_PATH=\"@SCIM_MODULE_PATH@\" \
+ -DSCIM_TEMPDIR=\"@SCIM_TEMPDIR@\"
+
+noinst_HEADERS = input-method-client-protocol.h \
+ text-client-protocol.h \
+ isf_wsc_context.h \
+ isf_wsc_control.h \
+ isf_wsc_control_ui.h
+
+if ISF_BUILD_WSC_EFL
+CONFIG_WSC_EFL = isf-wsc-efl
+endif
+
+bin_PROGRAMS = $(CONFIG_WSC_EFL)
+
+isf_wsc_efl_SOURCES = isf_wsc_efl.cpp \
+ input-method-protocol.c \
+ text-protocol.c \
+ isf_wsc_context.cpp \
+ isf_wsc_control.cpp \
+ isf_wsc_control_ui.cpp
+
+isf_wsc_efl_CXXFLAGS = @EFL_CFLAGS@ @VCONF_CFLAGS@ @DLOG_CFLAGS@ @TTS_CFLAGS@ @FEEDBACK_CFLAGS@
+
+isf_wsc_efl_LDFLAGS = @EFL_LIBS@ @LTLIBINTL@ -rpath $(libdir) \
+ @VCONF_LIBS@ \
+ @WAYLAND_LIBS@ \
+ @DLOG_LIBS@ \
+ @TTS_LIBS@ \
+ @FEEDBACK_LIBS@
+
+isf_wsc_efl_LDADD = $(top_builddir)/ism/src/libscim@SCIM_EPOCH@.la
+
--- /dev/null
+/*
+ * 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.
+ */
+
+#ifndef INPUT_METHOD_CLIENT_PROTOCOL_H
+#define INPUT_METHOD_CLIENT_PROTOCOL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+#include "wayland-client.h"
+
+struct wl_client;
+struct wl_resource;
+
+struct wl_input_method_context;
+struct wl_input_method;
+struct wl_input_panel;
+struct wl_input_panel_surface;
+
+extern const struct wl_interface wl_input_method_context_interface;
+extern const struct wl_interface wl_input_method_interface;
+extern const struct wl_interface wl_input_panel_interface;
+extern const struct wl_interface wl_input_panel_surface_interface;
+
+/**
+ * wl_input_method_context - input method context
+ * @surrounding_text: surrounding text event
+ * @reset: (none)
+ * @content_type: (none)
+ * @invoke_action: (none)
+ * @commit_state: (none)
+ * @preferred_language: (none)
+ *
+ * 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).
+ */
+struct wl_input_method_context_listener {
+ /**
+ * surrounding_text - surrounding text event
+ * @text: (none)
+ * @cursor: (none)
+ * @anchor: (none)
+ *
+ * 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.
+ */
+ void (*surrounding_text)(void *data,
+ struct wl_input_method_context *wl_input_method_context,
+ const char *text,
+ uint32_t cursor,
+ uint32_t anchor);
+ /**
+ * reset - (none)
+ */
+ void (*reset)(void *data,
+ struct wl_input_method_context *wl_input_method_context);
+ /**
+ * content_type - (none)
+ * @hint: (none)
+ * @purpose: (none)
+ */
+ void (*content_type)(void *data,
+ struct wl_input_method_context *wl_input_method_context,
+ uint32_t hint,
+ uint32_t purpose);
+ /**
+ * invoke_action - (none)
+ * @button: (none)
+ * @index: (none)
+ */
+ void (*invoke_action)(void *data,
+ struct wl_input_method_context *wl_input_method_context,
+ uint32_t button,
+ uint32_t index);
+ /**
+ * commit_state - (none)
+ * @serial: serial of text input state
+ */
+ void (*commit_state)(void *data,
+ struct wl_input_method_context *wl_input_method_context,
+ uint32_t serial);
+ /**
+ * preferred_language - (none)
+ * @language: (none)
+ */
+ void (*preferred_language)(void *data,
+ struct wl_input_method_context *wl_input_method_context,
+ const char *language);
+};
+
+static inline int
+wl_input_method_context_add_listener(struct wl_input_method_context *wl_input_method_context,
+ const struct wl_input_method_context_listener *listener, void *data)
+{
+ return wl_proxy_add_listener((struct wl_proxy *) wl_input_method_context,
+ (void (**)(void)) listener, data);
+}
+
+#define WL_INPUT_METHOD_CONTEXT_DESTROY 0
+#define WL_INPUT_METHOD_CONTEXT_COMMIT_STRING 1
+#define WL_INPUT_METHOD_CONTEXT_PREEDIT_STRING 2
+#define WL_INPUT_METHOD_CONTEXT_PREEDIT_STYLING 3
+#define WL_INPUT_METHOD_CONTEXT_PREEDIT_CURSOR 4
+#define WL_INPUT_METHOD_CONTEXT_DELETE_SURROUNDING_TEXT 5
+#define WL_INPUT_METHOD_CONTEXT_CURSOR_POSITION 6
+#define WL_INPUT_METHOD_CONTEXT_MODIFIERS_MAP 7
+#define WL_INPUT_METHOD_CONTEXT_KEYSYM 8
+#define WL_INPUT_METHOD_CONTEXT_GRAB_KEYBOARD 9
+#define WL_INPUT_METHOD_CONTEXT_KEY 10
+#define WL_INPUT_METHOD_CONTEXT_MODIFIERS 11
+#define WL_INPUT_METHOD_CONTEXT_LANGUAGE 12
+#define WL_INPUT_METHOD_CONTEXT_TEXT_DIRECTION 13
+
+static inline void
+wl_input_method_context_set_user_data(struct wl_input_method_context *wl_input_method_context, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) wl_input_method_context, user_data);
+}
+
+static inline void *
+wl_input_method_context_get_user_data(struct wl_input_method_context *wl_input_method_context)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) wl_input_method_context);
+}
+
+static inline void
+wl_input_method_context_destroy(struct wl_input_method_context *wl_input_method_context)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+ WL_INPUT_METHOD_CONTEXT_DESTROY);
+
+ wl_proxy_destroy((struct wl_proxy *) wl_input_method_context);
+}
+
+static inline void
+wl_input_method_context_commit_string(struct wl_input_method_context *wl_input_method_context, uint32_t serial, const char *text)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+ WL_INPUT_METHOD_CONTEXT_COMMIT_STRING, serial, text);
+}
+
+static inline void
+wl_input_method_context_preedit_string(struct wl_input_method_context *wl_input_method_context, uint32_t serial, const char *text, const char *commit)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+ WL_INPUT_METHOD_CONTEXT_PREEDIT_STRING, serial, text, commit);
+}
+
+static inline void
+wl_input_method_context_preedit_styling(struct wl_input_method_context *wl_input_method_context, uint32_t index, uint32_t length, uint32_t style)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+ WL_INPUT_METHOD_CONTEXT_PREEDIT_STYLING, index, length, style);
+}
+
+static inline void
+wl_input_method_context_preedit_cursor(struct wl_input_method_context *wl_input_method_context, int32_t index)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+ WL_INPUT_METHOD_CONTEXT_PREEDIT_CURSOR, index);
+}
+
+static inline void
+wl_input_method_context_delete_surrounding_text(struct wl_input_method_context *wl_input_method_context, int32_t index, uint32_t length)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+ WL_INPUT_METHOD_CONTEXT_DELETE_SURROUNDING_TEXT, index, length);
+}
+
+static inline void
+wl_input_method_context_cursor_position(struct wl_input_method_context *wl_input_method_context, int32_t index, int32_t anchor)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+ WL_INPUT_METHOD_CONTEXT_CURSOR_POSITION, index, anchor);
+}
+
+static inline void
+wl_input_method_context_modifiers_map(struct wl_input_method_context *wl_input_method_context, struct wl_array *map)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+ WL_INPUT_METHOD_CONTEXT_MODIFIERS_MAP, map);
+}
+
+static inline void
+wl_input_method_context_keysym(struct wl_input_method_context *wl_input_method_context, uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+ WL_INPUT_METHOD_CONTEXT_KEYSYM, serial, time, sym, state, modifiers);
+}
+
+static inline struct wl_keyboard *
+wl_input_method_context_grab_keyboard(struct wl_input_method_context *wl_input_method_context)
+{
+ struct wl_proxy *keyboard;
+
+ keyboard = wl_proxy_create((struct wl_proxy *) wl_input_method_context,
+ &wl_keyboard_interface);
+ if (!keyboard)
+ return NULL;
+
+ wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+ WL_INPUT_METHOD_CONTEXT_GRAB_KEYBOARD, keyboard);
+
+ return (struct wl_keyboard *) keyboard;
+}
+
+static inline void
+wl_input_method_context_key(struct wl_input_method_context *wl_input_method_context, uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+ WL_INPUT_METHOD_CONTEXT_KEY, serial, time, key, state);
+}
+
+static inline void
+wl_input_method_context_modifiers(struct wl_input_method_context *wl_input_method_context, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+ WL_INPUT_METHOD_CONTEXT_MODIFIERS, serial, mods_depressed, mods_latched, mods_locked, group);
+}
+
+static inline void
+wl_input_method_context_language(struct wl_input_method_context *wl_input_method_context, uint32_t serial, const char *language)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+ WL_INPUT_METHOD_CONTEXT_LANGUAGE, serial, language);
+}
+
+static inline void
+wl_input_method_context_text_direction(struct wl_input_method_context *wl_input_method_context, uint32_t serial, uint32_t direction)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+ WL_INPUT_METHOD_CONTEXT_TEXT_DIRECTION, serial, direction);
+}
+
+/**
+ * wl_input_method - input method
+ * @activate: activate event
+ * @deactivate: activate event
+ *
+ * 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.
+ */
+struct wl_input_method_listener {
+ /**
+ * activate - activate event
+ * @id: (none)
+ *
+ * A text model was activated. Creates an input method context
+ * object which allows communication with the text model.
+ */
+ void (*activate)(void *data,
+ struct wl_input_method *wl_input_method,
+ struct wl_input_method_context *id);
+ /**
+ * deactivate - activate event
+ * @context: (none)
+ *
+ * The text model corresponding to the context argument was
+ * deactivated. The input method context should be destroyed after
+ * deactivation is handled.
+ */
+ void (*deactivate)(void *data,
+ struct wl_input_method *wl_input_method,
+ struct wl_input_method_context *context);
+};
+
+static inline int
+wl_input_method_add_listener(struct wl_input_method *wl_input_method,
+ const struct wl_input_method_listener *listener, void *data)
+{
+ return wl_proxy_add_listener((struct wl_proxy *) wl_input_method,
+ (void (**)(void)) listener, data);
+}
+
+static inline void
+wl_input_method_set_user_data(struct wl_input_method *wl_input_method, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) wl_input_method, user_data);
+}
+
+static inline void *
+wl_input_method_get_user_data(struct wl_input_method *wl_input_method)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) wl_input_method);
+}
+
+static inline void
+wl_input_method_destroy(struct wl_input_method *wl_input_method)
+{
+ wl_proxy_destroy((struct wl_proxy *) wl_input_method);
+}
+
+#define WL_INPUT_PANEL_GET_INPUT_PANEL_SURFACE 0
+
+static inline void
+wl_input_panel_set_user_data(struct wl_input_panel *wl_input_panel, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) wl_input_panel, user_data);
+}
+
+static inline void *
+wl_input_panel_get_user_data(struct wl_input_panel *wl_input_panel)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) wl_input_panel);
+}
+
+static inline void
+wl_input_panel_destroy(struct wl_input_panel *wl_input_panel)
+{
+ wl_proxy_destroy((struct wl_proxy *) wl_input_panel);
+}
+
+static inline struct wl_input_panel_surface *
+wl_input_panel_get_input_panel_surface(struct wl_input_panel *wl_input_panel, struct wl_surface *surface)
+{
+ struct wl_proxy *id;
+
+ id = wl_proxy_create((struct wl_proxy *) wl_input_panel,
+ &wl_input_panel_surface_interface);
+ if (!id)
+ return NULL;
+
+ wl_proxy_marshal((struct wl_proxy *) wl_input_panel,
+ WL_INPUT_PANEL_GET_INPUT_PANEL_SURFACE, id, surface);
+
+ return (struct wl_input_panel_surface *) id;
+}
+
+#ifndef WL_INPUT_PANEL_SURFACE_POSITION_ENUM
+#define WL_INPUT_PANEL_SURFACE_POSITION_ENUM
+enum wl_input_panel_surface_position {
+ WL_INPUT_PANEL_SURFACE_POSITION_CENTER_BOTTOM = 0,
+};
+#endif /* WL_INPUT_PANEL_SURFACE_POSITION_ENUM */
+
+struct wl_input_panel_surface_listener {
+ /**
+ * cursor_rectangle - cursor rectangle
+ * @x: (none)
+ * @y: (none)
+ * @width: (none)
+ * @height: (none)
+ *
+ * Notify when the cursor rectangle relative to the input panel
+ * surface change.
+ */
+ void (*cursor_rectangle)(void *data,
+ struct wl_input_panel_surface *wl_input_panel_surface,
+ int32_t x,
+ int32_t y,
+ int32_t width,
+ int32_t height);
+};
+
+static inline int
+wl_input_panel_surface_add_listener(struct wl_input_panel_surface *wl_input_panel_surface,
+ const struct wl_input_panel_surface_listener *listener, void *data)
+{
+ return wl_proxy_add_listener((struct wl_proxy *) wl_input_panel_surface,
+ (void (**)(void)) listener, data);
+}
+
+#define WL_INPUT_PANEL_SURFACE_SET_TOPLEVEL 0
+#define WL_INPUT_PANEL_SURFACE_SET_OVERLAY_PANEL 1
+
+static inline void
+wl_input_panel_surface_set_user_data(struct wl_input_panel_surface *wl_input_panel_surface, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) wl_input_panel_surface, user_data);
+}
+
+static inline void *
+wl_input_panel_surface_get_user_data(struct wl_input_panel_surface *wl_input_panel_surface)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) wl_input_panel_surface);
+}
+
+static inline void
+wl_input_panel_surface_destroy(struct wl_input_panel_surface *wl_input_panel_surface)
+{
+ wl_proxy_destroy((struct wl_proxy *) wl_input_panel_surface);
+}
+
+static inline void
+wl_input_panel_surface_set_toplevel(struct wl_input_panel_surface *wl_input_panel_surface, struct wl_output *output, uint32_t position)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_input_panel_surface,
+ WL_INPUT_PANEL_SURFACE_SET_TOPLEVEL, output, position);
+}
+
+static inline void
+wl_input_panel_surface_set_overlay_panel(struct wl_input_panel_surface *wl_input_panel_surface)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_input_panel_surface,
+ WL_INPUT_PANEL_SURFACE_SET_OVERLAY_PANEL);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/*
+ * 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.
+ */
+#include <stdlib.h>
+#include <stdint.h>
+#include "wayland-util.h"
+
+extern const struct wl_interface wl_keyboard_interface;
+extern const struct wl_interface wl_input_method_context_interface;
+extern const struct wl_interface wl_input_method_context_interface;
+extern const struct wl_interface wl_input_panel_surface_interface;
+extern const struct wl_interface wl_surface_interface;
+extern const struct wl_interface wl_output_interface;
+
+static const struct wl_interface *types[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &wl_keyboard_interface,
+ &wl_input_method_context_interface,
+ &wl_input_method_context_interface,
+ &wl_input_panel_surface_interface,
+ &wl_surface_interface,
+ &wl_output_interface,
+ NULL,
+};
+
+static const struct wl_message wl_input_method_context_requests[] = {
+ { "destroy", "", types + 0 },
+ { "commit_string", "us", types + 0 },
+ { "preedit_string", "uss", types + 0 },
+ { "preedit_styling", "uuu", types + 0 },
+ { "preedit_cursor", "i", types + 0 },
+ { "delete_surrounding_text", "iu", types + 0 },
+ { "cursor_position", "ii", types + 0 },
+ { "modifiers_map", "a", types + 0 },
+ { "keysym", "uuuuu", types + 0 },
+ { "grab_keyboard", "n", types + 5 },
+ { "key", "uuuu", types + 0 },
+ { "modifiers", "uuuuu", types + 0 },
+ { "language", "us", types + 0 },
+ { "text_direction", "uu", types + 0 },
+};
+
+static const struct wl_message wl_input_method_context_events[] = {
+ { "surrounding_text", "suu", types + 0 },
+ { "reset", "", types + 0 },
+ { "content_type", "uu", types + 0 },
+ { "invoke_action", "uu", types + 0 },
+ { "commit_state", "u", types + 0 },
+ { "preferred_language", "s", types + 0 },
+};
+
+WL_EXPORT const struct wl_interface wl_input_method_context_interface = {
+ "wl_input_method_context", 1,
+ 14, wl_input_method_context_requests,
+ 6, wl_input_method_context_events,
+};
+
+static const struct wl_message wl_input_method_events[] = {
+ { "activate", "n", types + 6 },
+ { "deactivate", "o", types + 7 },
+};
+
+WL_EXPORT const struct wl_interface wl_input_method_interface = {
+ "wl_input_method", 1,
+ 0, NULL,
+ 2, wl_input_method_events,
+};
+
+static const struct wl_message wl_input_panel_requests[] = {
+ { "get_input_panel_surface", "no", types + 8 },
+};
+
+WL_EXPORT const struct wl_interface wl_input_panel_interface = {
+ "wl_input_panel", 1,
+ 1, wl_input_panel_requests,
+ 0, NULL,
+};
+
+static const struct wl_message wl_input_panel_surface_requests[] = {
+ { "set_toplevel", "ou", types + 10 },
+ { "set_overlay_panel", "", types + 0 },
+};
+
+static const struct wl_message wl_input_panel_surface_events[] = {
+ { "cursor_rectangle", "iiii", types + 0 },
+};
+
+WL_EXPORT const struct wl_interface wl_input_panel_surface_interface = {
+ "wl_input_panel_surface", 1,
+ 2, wl_input_panel_surface_requests,
+ 1, wl_input_panel_surface_events,
+};
--- /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 Uses_SCIM_BACKEND
+#define Uses_SCIM_IMENGINE_MODULE
+#define Uses_SCIM_HELPER_MODULE
+#define Uses_SCIM_HOTKEY
+#define Uses_SCIM_PANEL_CLIENT
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <pthread.h>
+#include <langinfo.h>
+#include <unistd.h>
+
+#include <Evas.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Ecore_Wayland.h>
+#include <glib.h>
+#include <vconf.h>
+#include <vconf-keys.h>
+
+#include "scim_private.h"
+#include "scim.h"
+#include "isf_wsc_context.h"
+#include "isf_wsc_control_ui.h"
+
+#define ENABLE_BACKKEY 1
+
+using namespace scim;
+
+struct _WSCContextISFImpl {
+ WSCContextISF *parent;
+ IMEngineInstancePointer si;
+ Ecore_Wl_Window *client_window;
+ Evas *client_canvas;
+ Ecore_IMF_Input_Mode input_mode;
+ WideString preedit_string;
+ AttributeList preedit_attrlist;
+ Ecore_IMF_Autocapital_Type autocapital_type;
+ void *imdata;
+ int imdata_size;
+ int preedit_caret;
+ int cursor_x;
+ int cursor_y;
+ int cursor_top_y;
+ int cursor_pos;
+ bool use_preedit;
+ bool is_on;
+ bool shared_si;
+ bool preedit_started;
+ bool preedit_updating;
+ bool need_commit_preedit;
+ bool prediction_allow;
+ int next_shift_status;
+ int shift_mode_enabled;
+
+ WSCContextISFImpl *next;
+};
+
+/* private functions */
+static void panel_slot_reload_config (int context);
+static void panel_slot_exit (int context);
+static void panel_slot_update_candidate_item_layout (int context,
+ const std::vector<uint32> &row_items);
+static void panel_slot_update_lookup_table_page_size(int context,
+ int page_size);
+static void panel_slot_lookup_table_page_up (int context);
+static void panel_slot_lookup_table_page_down (int context);
+static void panel_slot_trigger_property (int context,
+ const String &property);
+static void panel_slot_process_helper_event (int context,
+ const String &target_uuid,
+ const String &helper_uuid,
+ const Transaction &trans);
+static void panel_slot_move_preedit_caret (int context,
+ int caret_pos);
+static void panel_slot_update_preedit_caret (int context,
+ int caret);
+static void panel_slot_select_aux (int context,
+ int aux_index);
+static void panel_slot_select_candidate (int context,
+ int cand_index);
+static void panel_slot_process_key_event (int context,
+ const KeyEvent &key);
+static void panel_slot_commit_string (int context,
+ const WideString &wstr);
+static void panel_slot_forward_key_event (int context,
+ const KeyEvent &key);
+static void panel_slot_request_help (int context);
+static void panel_slot_request_factory_menu (int context);
+static void panel_slot_change_factory (int context,
+ const String &uuid);
+static void panel_slot_reset_keyboard_ise (int context);
+static void panel_slot_update_keyboard_ise (int context);
+static void panel_slot_show_preedit_string (int context);
+static void panel_slot_hide_preedit_string (int context);
+static void panel_slot_update_preedit_string (int context,
+ const WideString &str,
+ const AttributeList &attrs,
+ int caret);
+static void panel_slot_get_surrounding_text (int context,
+ int maxlen_before,
+ int maxlen_after);
+static void panel_slot_delete_surrounding_text (int context,
+ int offset,
+ int len);
+
+static void panel_req_focus_in (WSCContextISF *ic);
+static void panel_req_update_factory_info (WSCContextISF *ic);
+static void panel_req_update_spot_location (WSCContextISF *ic);
+static void panel_req_update_cursor_position (WSCContextISF *ic, int cursor_pos);
+static void panel_req_show_help (WSCContextISF *ic);
+static void panel_req_show_factory_menu (WSCContextISF *ic);
+
+/* Panel iochannel handler*/
+static bool panel_initialize (void);
+static void panel_finalize (void);
+static Eina_Bool panel_iochannel_handler (void *data,
+ Ecore_Fd_Handler *fd_handler);
+
+/* utility functions */
+static bool filter_hotkeys (WSCContextISF *ic,
+ const KeyEvent &key);
+static void turn_on_ic (WSCContextISF *ic);
+static void turn_off_ic (WSCContextISF *ic);
+static void set_ic_capabilities (WSCContextISF *ic);
+
+static void initialize (void);
+static void finalize (void);
+
+static void open_next_factory (WSCContextISF *ic);
+static void open_previous_factory (WSCContextISF *ic);
+static void open_specific_factory (WSCContextISF *ic,
+ const String &uuid);
+static void send_wl_key_event (WSCContextISF *ic, const KeyEvent &key, bool fake);
+static void _hide_preedit_string (int context, bool update_preedit);
+
+static void attach_instance (const IMEngineInstancePointer &si);
+
+/* slot functions */
+static void slot_show_preedit_string (IMEngineInstanceBase *si);
+static void slot_show_aux_string (IMEngineInstanceBase *si);
+static void slot_show_lookup_table (IMEngineInstanceBase *si);
+
+static void slot_hide_preedit_string (IMEngineInstanceBase *si);
+static void slot_hide_aux_string (IMEngineInstanceBase *si);
+static void slot_hide_lookup_table (IMEngineInstanceBase *si);
+
+static void slot_update_preedit_caret (IMEngineInstanceBase *si,
+ int caret);
+static void slot_update_preedit_string (IMEngineInstanceBase *si,
+ const WideString &str,
+ const AttributeList &attrs,
+ int caret);
+static void slot_update_aux_string (IMEngineInstanceBase *si,
+ const WideString &str,
+ const AttributeList &attrs);
+static void slot_commit_string (IMEngineInstanceBase *si,
+ const WideString &str);
+static void slot_forward_key_event (IMEngineInstanceBase *si,
+ const KeyEvent &key);
+static void slot_update_lookup_table (IMEngineInstanceBase *si,
+ const LookupTable &table);
+
+static void slot_register_properties (IMEngineInstanceBase *si,
+ const PropertyList &properties);
+static void slot_update_property (IMEngineInstanceBase *si,
+ const Property &property);
+static void slot_beep (IMEngineInstanceBase *si);
+static void slot_start_helper (IMEngineInstanceBase *si,
+ const String &helper_uuid);
+static void slot_stop_helper (IMEngineInstanceBase *si,
+ const String &helper_uuid);
+static void slot_send_helper_event (IMEngineInstanceBase *si,
+ const String &helper_uuid,
+ const Transaction &trans);
+static bool slot_get_surrounding_text (IMEngineInstanceBase *si,
+ WideString &text,
+ int &cursor,
+ int maxlen_before,
+ int maxlen_after);
+static bool slot_delete_surrounding_text (IMEngineInstanceBase *si,
+ int offset,
+ int len);
+
+static void slot_expand_candidate (IMEngineInstanceBase *si);
+static void slot_contract_candidate (IMEngineInstanceBase *si);
+
+static void slot_set_candidate_style (IMEngineInstanceBase *si,
+ ISF_CANDIDATE_PORTRAIT_LINE_T portrait_line,
+ ISF_CANDIDATE_MODE_T mode);
+
+static void reload_config_callback (const ConfigPointer &config);
+
+static void fallback_commit_string_cb (IMEngineInstanceBase *si,
+ const WideString &str);
+static void _display_input_language (WSCContextISF *ic);
+
+/* Local variables declaration */
+static String _language;
+static WSCContextISFImpl *_used_ic_impl_list = 0;
+static WSCContextISFImpl *_free_ic_impl_list = 0;
+static WSCContextISF *_ic_list = 0;
+
+static KeyboardLayout _keyboard_layout = SCIM_KEYBOARD_Default;
+static int _valid_key_mask = SCIM_KEY_AllMasks;
+
+static FrontEndHotkeyMatcher _frontend_hotkey_matcher;
+static IMEngineHotkeyMatcher _imengine_hotkey_matcher;
+
+static IMEngineInstancePointer _default_instance;
+
+static ConfigPointer _config;
+static Connection _config_connection;
+static BackEndPointer _backend;
+
+static WSCContextISF *_focused_ic = 0;
+
+static bool _scim_initialized = false;
+
+static int _instance_count = 0;
+static int _context_count = 0;
+
+static IMEngineFactoryPointer _fallback_factory;
+static IMEngineInstancePointer _fallback_instance;
+PanelClient _panel_client;
+static int _panel_client_id = 0;
+
+static Ecore_Fd_Handler *_panel_iochannel_read_handler = 0;
+static Ecore_Fd_Handler *_panel_iochannel_err_handler = 0;
+
+static Ecore_Wl_Window *_client_window = 0;
+static Ecore_Event_Handler *_key_down_handler = 0;
+static Ecore_Event_Handler *_key_up_handler = 0;
+
+static bool _on_the_spot = true;
+static bool _shared_input_method = false;
+static double space_key_time = 0.0;
+
+static Eina_Bool autoperiod_allow = EINA_FALSE;
+static Eina_Bool autocap_allow = EINA_FALSE;
+static Eina_Bool desktop_mode = EINA_FALSE;
+
+static bool _x_key_event_is_valid = false;
+
+typedef enum {
+ INPUT_LANG_JAPANESE,
+ INPUT_LANG_OTHER
+} Input_Language;
+
+static Input_Language input_lang = INPUT_LANG_OTHER;
+
+#define SHIFT_MODE_OFF 0xffe1
+#define SHIFT_MODE_ON 0xffe2
+#define SHIFT_MODE_LOCK 0xffe6
+#define SHIFT_MODE_ENABLE 0x9fe7
+#define SHIFT_MODE_DISABLE 0x9fe8
+
+EAPI WSCContextISF *
+get_focused_ic ()
+{
+ return _focused_ic;
+}
+
+EAPI int
+get_panel_client_id (void)
+{
+ return _panel_client_id;
+}
+
+EAPI Eina_Bool
+get_desktop_mode ()
+{
+ return desktop_mode;
+}
+
+EAPI void
+get_language(char **language)
+{
+ *language = strdup(_language.c_str());
+}
+
+static unsigned int
+get_time (void)
+{
+ unsigned int tint;
+ struct timeval tv;
+ struct timezone tz; /* is not used since ages */
+ gettimeofday (&tv, &tz);
+ tint = tv.tv_sec * 1000;
+ tint = tint / 1000 * 1000;
+ tint = tint + tv.tv_usec / 1000;
+ return tint;
+}
+
+/* Function Implementations */
+static WSCContextISFImpl *
+new_ic_impl (WSCContextISF *parent)
+{
+ WSCContextISFImpl *impl = NULL;
+
+ if (_free_ic_impl_list != NULL) {
+ impl = _free_ic_impl_list;
+ _free_ic_impl_list = _free_ic_impl_list->next;
+ } else {
+ impl = new WSCContextISFImpl;
+ if (impl == NULL)
+ return NULL;
+ }
+
+ impl->autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
+ impl->next_shift_status = 0;
+ impl->shift_mode_enabled = 1;
+ impl->next = _used_ic_impl_list;
+ _used_ic_impl_list = impl;
+
+ impl->parent = parent;
+ impl->imdata = NULL;
+ impl->imdata_size = 0;
+
+ return impl;
+}
+
+static void
+delete_ic_impl (WSCContextISFImpl *impl)
+{
+ WSCContextISFImpl *rec = _used_ic_impl_list, *last = 0;
+
+ for (; rec != 0; last = rec, rec = rec->next) {
+ if (rec == impl) {
+ if (last != 0)
+ last->next = rec->next;
+ else
+ _used_ic_impl_list = rec->next;
+
+ rec->next = _free_ic_impl_list;
+ _free_ic_impl_list = rec;
+
+ if (rec->imdata) {
+ free (rec->imdata);
+ rec->imdata = NULL;
+ }
+
+ rec->imdata_size = 0;
+ rec->parent = 0;
+ rec->si.reset ();
+ rec->client_window = 0;
+ rec->preedit_string = WideString ();
+ rec->preedit_attrlist.clear ();
+
+ return;
+ }
+ }
+}
+
+static void
+delete_all_ic_impl (void)
+{
+ WSCContextISFImpl *it = _used_ic_impl_list;
+
+ while (it != 0) {
+ _used_ic_impl_list = it->next;
+ delete it;
+ it = _used_ic_impl_list;
+ }
+
+ it = _free_ic_impl_list;
+ while (it != 0) {
+ _free_ic_impl_list = it->next;
+ delete it;
+ it = _free_ic_impl_list;
+ }
+}
+
+static WSCContextISF *
+find_ic (int id)
+{
+ WSCContextISFImpl *rec = _used_ic_impl_list;
+
+ while (rec != 0) {
+ if (rec->parent && rec->parent->id == id)
+ return rec->parent;
+ rec = rec->next;
+ }
+
+ return 0;
+}
+
+static bool
+check_valid_ic (WSCContextISF * ic)
+{
+ if (ic && ic->impl && ic->ctx)
+ return true;
+ else
+ return false;
+}
+
+static void
+set_prediction_allow (WSCContextISF *ctx, bool prediction)
+{
+ WSCContextISF *context_scim = ctx;
+
+ if (context_scim && context_scim->impl && context_scim == _focused_ic) {
+ _panel_client.prepare (context_scim->id);
+ context_scim->impl->si->set_prediction_allow (prediction);
+ _panel_client.send ();
+ }
+}
+
+static Eina_Bool
+check_symbol (Eina_Unicode ucode, Eina_Unicode symbols[], int symbol_num)
+{
+ for (int i = 0; i < symbol_num; i++) {
+ // Check symbol
+ if (ucode == symbols[i])
+ return EINA_TRUE;
+ }
+
+ return EINA_FALSE;
+}
+
+static void
+autoperiod_insert (WSCContextISF *ctx)
+{
+ char *plain_str = NULL;
+ char *markup_str = NULL;
+ int cursor_pos = 0;
+ Eina_Unicode *ustr = NULL;
+ Eina_Unicode space_symbols[] = {' ', 0x00A0 /* no-break space */, 0x3000 /* ideographic space */};
+ Eina_Unicode symbols[] = {' ', 0x00A0 /* no-break space */, 0x3000 /* ideographic space */,
+ ':', ';', '.', '!', '?', 0x00BF /* ¿ */, 0x00A1 /* ¡ */, 0x3002 /* 。 */};
+ const int symbol_num = sizeof (symbols) / sizeof (symbols[0]);
+ char *fullstop_mark = NULL;
+
+ if (autoperiod_allow == EINA_FALSE)
+ return;
+
+ if (!ctx) return;
+
+ Ecore_IMF_Input_Panel_Layout layout = wsc_context_input_panel_layout_get (ctx->ctx);
+ if (layout != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
+ return;
+
+ if ((ecore_time_get () - space_key_time) > DOUBLE_SPACE_INTERVAL)
+ goto done;
+
+ wsc_context_surrounding_get (ctx->ctx, &markup_str, &cursor_pos);
+ if (!markup_str) goto done;
+
+ // Convert into plain string
+ plain_str = evas_textblock_text_markup_to_utf8 (NULL, markup_str);
+ if (!plain_str) goto done;
+
+ // Convert string from UTF-8 to unicode
+ ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
+ if (!ustr) goto done;
+
+ if (cursor_pos < 2) goto done;
+
+ if (check_symbol (ustr[cursor_pos-1], space_symbols, (sizeof (space_symbols) / sizeof (space_symbols[0]))) &&
+ (!check_symbol (ustr[cursor_pos-2], symbols, symbol_num))) {
+ wsc_context_delete_surrounding(ctx->ctx, -1, 1);
+
+ if (input_lang == INPUT_LANG_JAPANESE) {
+ fullstop_mark = strdup ("。");
+ }
+ else {
+ fullstop_mark = strdup (".");
+ }
+
+ wsc_context_commit_string(ctx->ctx, fullstop_mark);
+
+ if (fullstop_mark) {
+ free (fullstop_mark);
+ }
+ }
+
+done:
+ if (markup_str) free (markup_str);
+ if (plain_str) free (plain_str);
+ if (ustr) free (ustr);
+ space_key_time = ecore_time_get ();
+}
+
+static Eina_Bool
+analyze_surrounding_text (WSCContextISF *ctx)
+{
+ char *plain_str = NULL;
+ char *markup_str = NULL;
+ Eina_Unicode puncs[] = {'\n','.', '!', '?', 0x00BF /* ¿ */, 0x00A1 /* ¡ */, 0x3002 /* 。 */};
+ Eina_Unicode space_symbols[] = {' ', 0x00A0 /* no-break space */, 0x3000 /* ideographic space */};
+ Eina_Unicode *ustr = NULL;
+ Eina_Bool ret = EINA_FALSE;
+ Eina_Bool detect_space = EINA_FALSE;
+ int cursor_pos = 0;
+ int i = 0;
+ const int punc_num = sizeof (puncs) / sizeof (puncs[0]);
+ WSCContextISF *context_scim;
+
+ if (!ctx) return EINA_FALSE;
+ context_scim = ctx;
+ if (!context_scim || !context_scim->impl) return EINA_FALSE;
+
+ switch (context_scim->impl->autocapital_type) {
+ case ECORE_IMF_AUTOCAPITAL_TYPE_NONE:
+ return EINA_FALSE;
+ case ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER:
+ return EINA_TRUE;
+ default:
+ break;
+ }
+
+ if (context_scim->impl->cursor_pos == 0)
+ return EINA_TRUE;
+
+ wsc_context_surrounding_get (ctx->ctx, &markup_str, &cursor_pos);
+ if (!markup_str) goto done;
+
+ if (cursor_pos == 0) {
+ ret = EINA_TRUE;
+ goto done;
+ }
+
+ // Convert into plain string
+ plain_str = evas_textblock_text_markup_to_utf8 (NULL, markup_str);
+ if (!plain_str) goto done;
+
+ // Convert string from UTF-8 to unicode
+ ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
+ if (!ustr) goto done;
+
+ if (eina_unicode_strlen (ustr) < (size_t)cursor_pos) goto done;
+
+ if (cursor_pos >= 1) {
+ if (context_scim->impl->autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_WORD) {
+ // Check space or no-break space
+ if (check_symbol (ustr[cursor_pos-1], space_symbols, (sizeof (space_symbols) / sizeof (space_symbols[0])))) {
+ ret = EINA_TRUE;
+ goto done;
+ }
+ }
+
+ // Check paragraph separator <PS> or carriage return <br>
+ if ((ustr[cursor_pos-1] == 0x2029) || (ustr[cursor_pos-1] == '\n')) {
+ ret = EINA_TRUE;
+ goto done;
+ }
+
+ for (i = cursor_pos; i > 0; i--) {
+ // Check space or no-break space
+ if (check_symbol (ustr[i-1], space_symbols, (sizeof (space_symbols) / sizeof (space_symbols[0])))) {
+ detect_space = EINA_TRUE;
+ continue;
+ }
+
+ // Check punctuation and following the continuous space(s)
+ if (detect_space && check_symbol (ustr[i-1], puncs, punc_num)) {
+ ret = EINA_TRUE;
+ goto done;
+ }
+ else {
+ ret = EINA_FALSE;
+ goto done;
+ }
+ }
+
+ if ((i == 0) && (detect_space == EINA_TRUE)) {
+ // continuous space(s) without any character
+ ret = EINA_TRUE;
+ goto done;
+ }
+ }
+
+done:
+ if (ustr) free (ustr);
+ if (markup_str) free (markup_str);
+ if (plain_str) free (plain_str);
+
+ return ret;
+}
+
+EAPI Eina_Bool
+caps_mode_check (WSCContextISF *ctx, Eina_Bool force, Eina_Bool noti)
+{
+ Eina_Bool uppercase;
+ WSCContextISF *context_scim;
+
+ if (hw_keyboard_num_get () > 0) return EINA_FALSE;
+
+ if (!ctx) return EINA_FALSE;
+ context_scim = ctx;
+
+ if (!context_scim || !context_scim->impl)
+ return EINA_FALSE;
+
+ if (context_scim->impl->next_shift_status == SHIFT_MODE_LOCK) return EINA_TRUE;
+
+ Ecore_IMF_Input_Panel_Layout layout = wsc_context_input_panel_layout_get (ctx->ctx);
+ if (layout != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
+ return EINA_FALSE;
+
+ // Check autocapital type
+ if (wsc_context_input_panel_caps_lock_mode_get (ctx->ctx)) {
+ uppercase = EINA_TRUE;
+ } else {
+ if (autocap_allow == EINA_FALSE)
+ return EINA_FALSE;
+
+ if (analyze_surrounding_text (ctx)) {
+ uppercase = EINA_TRUE;
+ } else {
+ uppercase = EINA_FALSE;
+ }
+ }
+
+ if (force) {
+ context_scim->impl->next_shift_status = uppercase ? SHIFT_MODE_ON : SHIFT_MODE_OFF;
+ if (noti)
+ isf_wsc_context_input_panel_caps_mode_set (ctx, uppercase);
+ } else {
+ if (context_scim->impl->next_shift_status != (uppercase ? SHIFT_MODE_ON : SHIFT_MODE_OFF)) {
+ context_scim->impl->next_shift_status = uppercase ? SHIFT_MODE_ON : SHIFT_MODE_OFF;
+ if (noti)
+ isf_wsc_context_input_panel_caps_mode_set (ctx, uppercase);
+ }
+ }
+
+ return uppercase;
+}
+
+static void
+get_input_language ()
+{
+ char *input_lang_str = vconf_get_str (VCONFKEY_ISF_INPUT_LANGUAGE);
+ if (!input_lang_str) return;
+
+ if (strcmp (input_lang_str, "ja_JP") == 0)
+ input_lang = INPUT_LANG_JAPANESE;
+ else
+ input_lang = INPUT_LANG_OTHER;
+
+ free (input_lang_str);
+}
+
+static void autoperiod_allow_changed_cb (keynode_t *key, void* data)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ autoperiod_allow = vconf_keynode_get_bool (key);
+}
+
+static void autocapital_allow_changed_cb (keynode_t *key, void* data)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ autocap_allow = vconf_keynode_get_bool (key);
+}
+
+static void input_language_changed_cb (keynode_t *key, void* data)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ get_input_language ();
+}
+
+EAPI void context_scim_imdata_get (WSCContextISF *ctx, void* data, int* length)
+{
+ WSCContextISF *context_scim = ctx;
+
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (context_scim && context_scim->impl) {
+ if (data && context_scim->impl->imdata)
+ memcpy (data, context_scim->impl->imdata, context_scim->impl->imdata_size);
+
+ if (length)
+ *length = context_scim->impl->imdata_size;
+ }
+}
+
+EAPI void
+imengine_layout_set (WSCContextISF *ctx, Ecore_IMF_Input_Panel_Layout layout)
+{
+ WSCContextISF *context_scim = ctx;
+
+ if (context_scim && context_scim->impl && context_scim == _focused_ic) {
+ _panel_client.prepare (context_scim->id);
+ context_scim->impl->si->set_layout (layout);
+ _panel_client.send ();
+ }
+}
+
+/* Public functions */
+EAPI WSCContextISF *
+isf_wsc_context_new (void)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ int val;
+
+ WSCContextISF *context_scim = new WSCContextISF;
+ if (context_scim == NULL) {
+ std::cerr << "memory allocation failed in " << __FUNCTION__ << "\n";
+ return NULL;
+ }
+
+ if (_context_count == 0) {
+ _context_count = getpid () % 50000;
+ }
+ context_scim->id = _context_count++;
+
+ if (!_scim_initialized) {
+ ecore_wl_init (NULL);
+ initialize ();
+ _scim_initialized = true;
+ isf_wsc_input_panel_init ();
+ //isf_wsc_context_set_hardware_keyboard_mode(context_scim);
+
+ /* get autoperiod allow vconf value */
+ if (vconf_get_bool (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, &val) == 0) {
+ if (val == EINA_TRUE)
+ autoperiod_allow = EINA_TRUE;
+ }
+
+ vconf_notify_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb, NULL);
+
+ /* get autocapital allow vconf value */
+ if (vconf_get_bool (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, &val) == 0) {
+ if (val == EINA_TRUE)
+ autocap_allow = EINA_TRUE;
+ }
+
+ vconf_notify_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb, NULL);
+
+ /* get input language vconf value */
+ get_input_language ();
+
+ vconf_notify_key_changed (VCONFKEY_ISF_INPUT_LANGUAGE, input_language_changed_cb, NULL);
+ }
+
+ return context_scim;
+}
+
+EAPI void
+isf_wsc_context_shutdown (void)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+ ConfigBase::set (0);
+ if (_scim_initialized) {
+ _scim_initialized = false;
+
+ vconf_ignore_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb);
+ vconf_ignore_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb);
+ vconf_ignore_key_changed (VCONFKEY_ISF_INPUT_LANGUAGE, input_language_changed_cb);
+
+ isf_wsc_input_panel_shutdown ();
+ finalize ();
+ ecore_wl_shutdown ();
+ }
+}
+
+EAPI void
+isf_wsc_context_add (WSCContextISF *ctx)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *context_scim = ctx;
+
+ if (!context_scim) return;
+
+ context_scim->impl = NULL;
+
+ if (_backend.null ())
+ return;
+
+ IMEngineInstancePointer si;
+
+ // Use the default instance if "shared input method" mode is enabled.
+ if (_shared_input_method && !_default_instance.null ()) {
+ si = _default_instance;
+ SCIM_DEBUG_FRONTEND(2) << "use default instance: " << si->get_id () << " " << si->get_factory_uuid () << "\n";
+ }
+
+ // Not in "shared input method" mode, or no default instance, create an instance.
+ if (si.null ()) {
+ IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
+ if (factory.null ()) return;
+ si = factory->create_instance ("UTF-8", _instance_count++);
+ if (si.null ()) return;
+ attach_instance (si);
+ SCIM_DEBUG_FRONTEND(2) << "create new instance: " << si->get_id () << " " << si->get_factory_uuid () << "\n";
+ }
+
+ // If "shared input method" mode is enabled, and there is no default instance,
+ // then store this instance as default one.
+ if (_shared_input_method && _default_instance.null ()) {
+ SCIM_DEBUG_FRONTEND(2) << "update default instance.\n";
+ _default_instance = si;
+ }
+
+ context_scim->impl = new_ic_impl (context_scim);
+ if (context_scim->impl == NULL) {
+ std::cerr << "memory allocation failed in " << __FUNCTION__ << "\n";
+ return;
+ }
+
+ context_scim->impl->si = si;
+ context_scim->impl->client_window = 0;
+ context_scim->impl->client_canvas = NULL;
+ context_scim->impl->preedit_caret = 0;
+ context_scim->impl->cursor_x = 0;
+ context_scim->impl->cursor_y = 0;
+ context_scim->impl->cursor_pos = -1;
+ context_scim->impl->cursor_top_y = 0;
+ context_scim->impl->is_on = true;
+ context_scim->impl->shared_si = _shared_input_method;
+ context_scim->impl->use_preedit = _on_the_spot;
+ context_scim->impl->preedit_started = false;
+ context_scim->impl->preedit_updating = false;
+ context_scim->impl->need_commit_preedit = false;
+ context_scim->impl->prediction_allow = true;
+
+ if (!_ic_list)
+ context_scim->next = NULL;
+ else
+ context_scim->next = _ic_list;
+ _ic_list = context_scim;
+
+ if (_shared_input_method)
+ context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
+
+ _panel_client.prepare (context_scim->id);
+ _panel_client.register_input_context (context_scim->id, si->get_factory_uuid ());
+ set_ic_capabilities (context_scim);
+ _panel_client.send ();
+
+ SCIM_DEBUG_FRONTEND(2) << "input context created: id = " << context_scim->id << "\n";
+}
+
+EAPI void
+isf_wsc_context_del (WSCContextISF *ctx)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (!_ic_list) return;
+
+ WSCContextISF *context_scim = ctx;
+
+ if (context_scim) {
+ if (context_scim->id != _ic_list->id) {
+ WSCContextISF * pre = _ic_list;
+ WSCContextISF * cur = _ic_list->next;
+ while (cur != NULL) {
+ if (cur->id == context_scim->id) {
+ pre->next = cur->next;
+ break;
+ }
+ pre = cur;
+ cur = cur->next;
+ }
+ } else {
+ _ic_list = _ic_list->next;
+ }
+ }
+
+ if (context_scim && context_scim->impl) {
+ _panel_client.prepare (context_scim->id);
+
+ if (context_scim == _focused_ic)
+ context_scim->impl->si->focus_out ();
+
+ // Delete the instance.
+ // FIXME:
+ // In case the instance send out some helper event,
+ // and this context has been focused out,
+ // we need set the focused_ic to this context temporary.
+ WSCContextISF *old_focused = _focused_ic;
+ _focused_ic = context_scim;
+ context_scim->impl->si.reset ();
+ _focused_ic = old_focused;
+
+ if (context_scim == _focused_ic) {
+ _panel_client.turn_off (context_scim->id);
+ _panel_client.focus_out (context_scim->id);
+ }
+
+ _panel_client.remove_input_context (context_scim->id);
+ _panel_client.send ();
+
+ if (context_scim->impl) {
+ delete_ic_impl (context_scim->impl);
+ context_scim->impl = 0;
+ }
+ }
+
+ if (context_scim == _focused_ic)
+ _focused_ic = 0;
+
+ if (context_scim) {
+ delete context_scim;
+ context_scim = 0;
+ }
+}
+
+EAPI void
+isf_wsc_context_focus_in (WSCContextISF *ctx)
+{
+ WSCContextISF *context_scim = ctx;
+
+ if (!context_scim)
+ return;
+
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__<< "(" << context_scim->id << ")...\n";
+
+ if (_focused_ic) {
+ if (_focused_ic == context_scim) {
+ SCIM_DEBUG_FRONTEND(1) << "It's already focused.\n";
+ return;
+ }
+ SCIM_DEBUG_FRONTEND(1) << "Focus out previous IC first: " << _focused_ic->id << "\n";
+ if (_focused_ic->ctx)
+ isf_wsc_context_focus_out (_focused_ic);
+ }
+
+ bool need_cap = false;
+ bool need_reset = false;
+ bool need_reg = false;
+
+ if (context_scim && context_scim->impl) {
+ _focused_ic = context_scim;
+
+ _panel_client.send ();
+
+ _panel_client.prepare (context_scim->id);
+
+ // Handle the "Shared Input Method" mode.
+ if (_shared_input_method) {
+ SCIM_DEBUG_FRONTEND(2) << "shared input method.\n";
+ IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
+ if (!factory.null ()) {
+ if (_default_instance.null () || _default_instance->get_factory_uuid () != factory->get_uuid ()) {
+ _default_instance = factory->create_instance ("UTF-8", _default_instance.null () ? _instance_count++ : _default_instance->get_id ());
+ attach_instance (_default_instance);
+ SCIM_DEBUG_FRONTEND(2) << "create new default instance: " << _default_instance->get_id () << " " << _default_instance->get_factory_uuid () << "\n";
+ }
+
+ context_scim->impl->shared_si = true;
+ context_scim->impl->si = _default_instance;
+
+ context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
+ context_scim->impl->preedit_string.clear ();
+ context_scim->impl->preedit_attrlist.clear ();
+ context_scim->impl->preedit_caret = 0;
+ context_scim->impl->preedit_started = false;
+ need_cap = true;
+ need_reset = true;
+ need_reg = true;
+ }
+ } else if (context_scim->impl->shared_si) {
+ SCIM_DEBUG_FRONTEND(2) << "exit shared input method.\n";
+ IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
+ if (!factory.null ()) {
+ context_scim->impl->si = factory->create_instance ("UTF-8", _instance_count++);
+ context_scim->impl->preedit_string.clear ();
+ context_scim->impl->preedit_attrlist.clear ();
+ context_scim->impl->preedit_caret = 0;
+ context_scim->impl->preedit_started = false;
+ attach_instance (context_scim->impl->si);
+ need_cap = true;
+ need_reg = true;
+ context_scim->impl->shared_si = false;
+ SCIM_DEBUG_FRONTEND(2) << "create new instance: " << context_scim->impl->si->get_id () << " " << context_scim->impl->si->get_factory_uuid () << "\n";
+ }
+ }
+
+ context_scim->impl->si->set_frontend_data (static_cast <void*> (context_scim));
+
+ if (need_reg) _panel_client.register_input_context (context_scim->id, context_scim->impl->si->get_factory_uuid ());
+ if (need_cap) set_ic_capabilities (context_scim);
+
+ panel_req_focus_in (context_scim);
+// panel_req_update_spot_location (context_scim);
+// panel_req_update_factory_info (context_scim);
+
+ if (need_reset) context_scim->impl->si->reset ();
+ if (context_scim->impl->is_on) {
+ _panel_client.turn_on (context_scim->id);
+// _panel_client.hide_preedit_string (context_scim->id);
+// _panel_client.hide_aux_string (context_scim->id);
+// _panel_client.hide_lookup_table (context_scim->id);
+ context_scim->impl->si->focus_in ();
+ context_scim->impl->si->set_layout (wsc_context_input_panel_layout_get (ctx->ctx));
+ context_scim->impl->si->set_prediction_allow (context_scim->impl->prediction_allow);
+ if (context_scim->impl->imdata)
+ context_scim->impl->si->set_imdata ((const char *)context_scim->impl->imdata, context_scim->impl->imdata_size);
+ } else {
+ _panel_client.turn_off (context_scim->id);
+ }
+
+ _panel_client.send ();
+ if (caps_mode_check (ctx, EINA_FALSE, EINA_TRUE) == EINA_FALSE) {
+ context_scim->impl->next_shift_status = 0;
+ }
+ }
+
+ LOGD ("ctx : %p\n", ctx);
+}
+
+EAPI void
+isf_wsc_context_focus_out (WSCContextISF *ctx)
+{
+ WSCContextISF *context_scim = ctx;
+
+ if (!context_scim) return;
+
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "(" << context_scim->id << ")...\n";
+
+ if (context_scim && context_scim->impl && context_scim == _focused_ic) {
+
+ LOGD ("ctx : %p\n", ctx);
+
+ if (context_scim->impl->need_commit_preedit) {
+ _hide_preedit_string (context_scim->id, false);
+
+ wsc_context_commit_preedit_string(context_scim->ctx);
+ _panel_client.prepare (context_scim->id);
+ _panel_client.reset_input_context (context_scim->id);
+ _panel_client.send ();
+ }
+
+ _panel_client.prepare (context_scim->id);
+
+ context_scim->impl->si->focus_out ();
+ context_scim->impl->si->reset ();
+ context_scim->impl->cursor_pos = -1;
+
+// if (context_scim->impl->shared_si) context_scim->impl->si->reset ();
+
+ _panel_client.focus_out (context_scim->id);
+ _panel_client.send ();
+ _focused_ic = 0;
+ }
+ _x_key_event_is_valid = false;
+}
+
+EAPI void
+isf_wsc_context_reset (WSCContextISF *ctx)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *context_scim = ctx;
+
+ if (context_scim && context_scim->impl && context_scim == _focused_ic) {
+ _panel_client.prepare (context_scim->id);
+ context_scim->impl->si->reset ();
+ _panel_client.reset_input_context (context_scim->id);
+ _panel_client.send ();
+
+ if (context_scim->impl->need_commit_preedit) {
+ _hide_preedit_string (context_scim->id, false);
+ wsc_context_commit_preedit_string(context_scim->ctx);
+ }
+ }
+}
+
+EAPI void
+isf_wsc_context_preedit_string_get (WSCContextISF *ctx, char** str, int *cursor_pos)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *context_scim = ctx;
+
+ if (context_scim && context_scim->impl && context_scim->impl->is_on) {
+ String mbs = utf8_wcstombs (context_scim->impl->preedit_string);
+
+ if (str) {
+ if (mbs.length ())
+ *str = strdup (mbs.c_str ());
+ else
+ *str = strdup ("");
+ }
+
+ if (cursor_pos) {
+ //*cursor_pos = context_scim->impl->preedit_caret;
+ mbs = utf8_wcstombs (
+ context_scim->impl->preedit_string.substr(0, context_scim->impl->preedit_caret));
+ *cursor_pos = mbs.length();
+ }
+ } else {
+ if (str)
+ *str = strdup ("");
+
+ if (cursor_pos)
+ *cursor_pos = 0;
+ }
+}
+
+EAPI void
+isf_wsc_context_prediction_allow_set (WSCContextISF* ctx, Eina_Bool prediction)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << (prediction == EINA_TRUE ? "true" : "false") << "...\n";
+
+ WSCContextISF *context_scim = ctx;
+
+ if (context_scim && context_scim->impl && context_scim->impl->prediction_allow != prediction) {
+ context_scim->impl->prediction_allow = prediction;
+ set_prediction_allow (ctx, prediction);
+ }
+}
+
+EAPI Eina_Bool
+isf_wsc_context_prediction_allow_get (WSCContextISF* ctx)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *context_scim = ctx;
+
+ Eina_Bool ret = EINA_FALSE;
+ if (context_scim && context_scim->impl) {
+ ret = context_scim->impl->prediction_allow;
+ } else {
+ std::cerr << __FUNCTION__ << " failed!!!\n";
+ }
+ return ret;
+}
+
+static void
+turn_on_ic (WSCContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (ic && ic->impl && !ic->impl->is_on) {
+ ic->impl->is_on = true;
+
+ if (ic == _focused_ic) {
+ panel_req_focus_in (ic);
+// panel_req_update_spot_location (ic);
+ panel_req_update_factory_info (ic);
+ _panel_client.turn_on (ic->id);
+// _panel_client.hide_preedit_string (ic->id);
+// _panel_client.hide_aux_string (ic->id);
+// _panel_client.hide_lookup_table (ic->id);
+ ic->impl->si->focus_in ();
+ ic->impl->si->set_layout (ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL);
+ ic->impl->si->set_prediction_allow (ic->impl->prediction_allow);
+ }
+
+ //Record the IC on/off status
+ if (_shared_input_method) {
+ _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), true);
+ _config->flush ();
+ }
+
+ if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
+ if (!check_valid_ic (ic))
+ return;
+
+ if (check_valid_ic (ic))
+ ic->impl->preedit_started = true;
+ }
+ }
+}
+
+static void
+turn_off_ic (WSCContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (ic && ic->impl && ic->impl->is_on) {
+ ic->impl->is_on = false;
+
+ if (ic == _focused_ic) {
+ ic->impl->si->focus_out ();
+
+// panel_req_update_factory_info (ic);
+ _panel_client.turn_off (ic->id);
+ }
+
+ //Record the IC on/off status
+ if (_shared_input_method) {
+ _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
+ _config->flush ();
+ }
+
+ if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
+ if (!check_valid_ic (ic))
+ return;
+
+ if (check_valid_ic (ic))
+ ic->impl->preedit_started = false;
+ }
+ }
+}
+
+static void
+set_ic_capabilities (WSCContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (ic && ic->impl) {
+ unsigned int cap = SCIM_CLIENT_CAP_ALL_CAPABILITIES;
+
+ if (!_on_the_spot || !ic->impl->use_preedit)
+ cap -= SCIM_CLIENT_CAP_ONTHESPOT_PREEDIT;
+
+ ic->impl->si->update_client_capabilities (cap);
+ }
+}
+
+static bool
+check_socket_frontend (void)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ SocketAddress address;
+ SocketClient client;
+
+ uint32 magic;
+
+ address.set_address (scim_get_default_socket_frontend_address ());
+
+ if (!client.connect (address))
+ return false;
+
+ if (!scim_socket_open_connection (magic,
+ String ("ConnectionTester"),
+ String ("SocketFrontEnd"),
+ client,
+ 1000)) {
+ return false;
+ }
+
+ return true;
+}
+
+/* Panel Requestion functions. */
+static void
+panel_req_show_help (WSCContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ String help;
+
+ help = String (_("Smart Common Input Method platform ")) +
+ String (SCIM_VERSION) +
+ String (_("\n(C) 2002-2005 James Su <suzhe@tsinghua.org.cn>\n\n"));
+
+ if (ic && ic->impl) {
+ IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
+ if (sf) {
+ help += utf8_wcstombs (sf->get_name ());
+ help += String (_(":\n\n"));
+
+ help += utf8_wcstombs (sf->get_help ());
+ help += String (_("\n\n"));
+
+ help += utf8_wcstombs (sf->get_credits ());
+ }
+ _panel_client.show_help (ic->id, help);
+ }
+}
+
+static void
+panel_req_show_factory_menu (WSCContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ std::vector<IMEngineFactoryPointer> factories;
+ std::vector <PanelFactoryInfo> menu;
+
+ _backend->get_factories_for_encoding (factories, "UTF-8");
+
+ for (size_t i = 0; i < factories.size (); ++ i) {
+ menu.push_back (PanelFactoryInfo (
+ factories [i]->get_uuid (),
+ utf8_wcstombs (factories [i]->get_name ()),
+ factories [i]->get_language (),
+ factories [i]->get_icon_file ()));
+ }
+
+ if (menu.size ())
+ _panel_client.show_factory_menu (ic->id, menu);
+}
+
+static void
+panel_req_update_factory_info (WSCContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (ic && ic->impl && ic == _focused_ic) {
+ PanelFactoryInfo info;
+ if (ic->impl->is_on) {
+ IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
+ if (sf)
+ info = PanelFactoryInfo (sf->get_uuid (), utf8_wcstombs (sf->get_name ()), sf->get_language (), sf->get_icon_file ());
+ } else {
+ info = PanelFactoryInfo (String (""), String (_("English Keyboard")), String ("C"), String (SCIM_KEYBOARD_ICON_FILE));
+ }
+ _panel_client.update_factory_info (ic->id, info);
+ }
+}
+
+static void
+panel_req_focus_in (WSCContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (ic && ic->impl && ic->impl->si)
+ _panel_client.focus_in (ic->id, ic->impl->si->get_factory_uuid ());
+}
+
+static void
+panel_req_update_spot_location (WSCContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (ic && ic->impl)
+ _panel_client.update_spot_location (ic->id, ic->impl->cursor_x, ic->impl->cursor_y, ic->impl->cursor_top_y);
+}
+
+static void
+panel_req_update_cursor_position (WSCContextISF *ic, int cursor_pos)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (ic)
+ _panel_client.update_cursor_position (ic->id, cursor_pos);
+}
+
+static bool
+filter_hotkeys (WSCContextISF *ic, const KeyEvent &key)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ bool ret = false;
+
+ if (!check_valid_ic (ic))
+ return ret;
+
+ _frontend_hotkey_matcher.push_key_event (key);
+ _imengine_hotkey_matcher.push_key_event (key);
+
+ FrontEndHotkeyAction hotkey_action = _frontend_hotkey_matcher.get_match_result ();
+
+ if (hotkey_action == SCIM_FRONTEND_HOTKEY_TRIGGER) {
+ IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
+ if (sf && (sf->get_option () & SCIM_IME_SUPPORT_LANGUAGE_TOGGLE_KEY)) {
+ ret = false;
+ } else {
+ if (!ic->impl->is_on) {
+ turn_on_ic (ic);
+ } else {
+ turn_off_ic (ic);
+ _panel_client.hide_aux_string (ic->id);
+ _panel_client.hide_lookup_table (ic->id);
+ }
+
+ _display_input_language (ic);
+ ret = true;
+ }
+ } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_ON) {
+ if (!ic->impl->is_on) {
+ turn_on_ic (ic);
+ _display_input_language (ic);
+ }
+ ret = true;
+ } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_OFF) {
+ if (ic->impl->is_on) {
+ turn_off_ic (ic);
+ _display_input_language (ic);
+ }
+ ret = true;
+ } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_NEXT_FACTORY) {
+ open_next_factory (ic);
+ ret = true;
+ } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_PREVIOUS_FACTORY) {
+ open_previous_factory (ic);
+ ret = true;
+ } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_SHOW_FACTORY_MENU) {
+ panel_req_show_factory_menu (ic);
+ ret = true;
+ } else if (_imengine_hotkey_matcher.is_matched ()) {
+ ISEInfo info = _imengine_hotkey_matcher.get_match_result ();
+ ISE_TYPE type = info.type;
+ if (type == IMENGINE_T)
+ open_specific_factory (ic, info.uuid);
+ else if (type == HELPER_T)
+ _panel_client.start_helper (ic->id, info.uuid);
+ ret = true;
+ }
+ return ret;
+}
+
+static bool
+panel_initialize (void)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ String display_name;
+ {
+ const char *p = getenv ("DISPLAY");
+ if (p) display_name = String (p);
+ }
+
+ if (_panel_client.open_connection (_config->get_name (), display_name) >= 0) {
+ if (_panel_client.get_client_id (_panel_client_id)) {
+ _panel_client.prepare (0);
+ _panel_client.register_client (_panel_client_id);
+ _panel_client.send ();
+ }
+
+ int fd = _panel_client.get_connection_number ();
+
+ _panel_iochannel_read_handler = ecore_main_fd_handler_add (fd, ECORE_FD_READ, panel_iochannel_handler, NULL, NULL, NULL);
+// _panel_iochannel_err_handler = ecore_main_fd_handler_add (fd, ECORE_FD_ERROR, panel_iochannel_handler, NULL, NULL, NULL);
+
+ SCIM_DEBUG_FRONTEND(2) << " Panel FD= " << fd << "\n";
+
+ WSCContextISF *context_scim = _ic_list;
+ while (context_scim != NULL) {
+ if (context_scim->impl && context_scim->impl->si) {
+ _panel_client.prepare (context_scim->id);
+ _panel_client.register_input_context (context_scim->id, context_scim->impl->si->get_factory_uuid ());
+ _panel_client.send ();
+ }
+ context_scim = context_scim->next;
+ }
+
+ if (_focused_ic) {
+ _focused_ic = 0;
+ }
+
+ return true;
+ }
+ std::cerr << "panel_initialize () failed!!!\n";
+ return false;
+}
+
+static void
+panel_finalize (void)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ _panel_client.close_connection ();
+
+ if (_panel_iochannel_read_handler) {
+ ecore_main_fd_handler_del (_panel_iochannel_read_handler);
+ _panel_iochannel_read_handler = 0;
+ }
+ if (_panel_iochannel_err_handler) {
+ ecore_main_fd_handler_del (_panel_iochannel_err_handler);
+ _panel_iochannel_err_handler = 0;
+ }
+}
+
+static Eina_Bool
+panel_iochannel_handler (void *data, Ecore_Fd_Handler *fd_handler)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (fd_handler == _panel_iochannel_read_handler) {
+ if (_panel_client.has_pending_event () && !_panel_client.filter_event ()) {
+ panel_finalize ();
+ panel_initialize ();
+ return ECORE_CALLBACK_CANCEL;
+ }
+ } else if (fd_handler == _panel_iochannel_err_handler) {
+ panel_finalize ();
+ panel_initialize ();
+ return ECORE_CALLBACK_CANCEL;
+ }
+ return ECORE_CALLBACK_RENEW;
+}
+
+/* Panel Slot functions */
+static void
+panel_slot_reload_config (int context)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+}
+
+static void
+panel_slot_exit (int /* context */)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ finalize ();
+}
+
+static void
+panel_slot_update_candidate_item_layout (int context, const std::vector<uint32> &row_items)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " row size=" << row_items.size () << " ic=" << ic << "\n";
+ if (ic && ic->impl) {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->update_candidate_item_layout (row_items);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_update_lookup_table_page_size (int context, int page_size)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " page_size=" << page_size << " ic=" << ic << "\n";
+ if (ic && ic->impl) {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->update_lookup_table_page_size (page_size);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_lookup_table_page_up (int context)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
+ if (ic && ic->impl) {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->lookup_table_page_up ();
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_lookup_table_page_down (int context)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
+ if (ic && ic->impl) {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->lookup_table_page_down ();
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_trigger_property (int context, const String &property)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " property=" << property << " ic=" << ic << "\n";
+ if (ic && ic->impl) {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->trigger_property (property);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_process_helper_event (int context, const String &target_uuid, const String &helper_uuid, const Transaction &trans)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " target=" << target_uuid
+ << " helper=" << helper_uuid << " ic=" << ic << " ic->impl=" << (ic != NULL ? ic->impl : 0) << " ic-uuid="
+ << ((ic && ic->impl) ? ic->impl->si->get_factory_uuid () : "" ) << "\n";
+ if (ic && ic->impl && ic->impl->si->get_factory_uuid () == target_uuid) {
+ _panel_client.prepare (ic->id);
+ SCIM_DEBUG_FRONTEND(2) << "call process_helper_event\n";
+ ic->impl->si->process_helper_event (helper_uuid, trans);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_move_preedit_caret (int context, int caret_pos)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " caret=" << caret_pos << " ic=" << ic << "\n";
+ if (ic && ic->impl) {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->move_preedit_caret (caret_pos);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_update_preedit_caret (int context, int caret)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " caret=" << caret << " ic=" << ic << "\n";
+
+ if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret) {
+ ic->impl->preedit_caret = caret;
+ if (ic->impl->use_preedit) {
+ if (!ic->impl->preedit_started) {
+ if (check_valid_ic (ic))
+ ic->impl->preedit_started = true;
+ }
+ } else {
+ _panel_client.prepare (ic->id);
+ _panel_client.update_preedit_caret (ic->id, caret);
+ _panel_client.send ();
+ }
+ }
+}
+
+static void
+panel_slot_select_aux (int context, int aux_index)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " aux=" << aux_index << " ic=" << ic << "\n";
+ if (ic && ic->impl) {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->select_aux (aux_index);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_select_candidate (int context, int cand_index)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " candidate=" << cand_index << " ic=" << ic << "\n";
+ if (ic && ic->impl) {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->select_candidate (cand_index);
+ _panel_client.send ();
+ }
+}
+
+static Eina_Bool
+feed_key_event (WSCContextISF *ic, const KeyEvent &key, bool fake)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (key.code <= 0x7F ||
+ (key.code >= SCIM_KEY_BackSpace && key.code <= SCIM_KEY_Delete) ||
+ (key.code >= SCIM_KEY_Home && key.code <= SCIM_KEY_Hyper_R)) {
+ // ascii code and function keys
+ send_wl_key_event(ic, key, fake);
+ return EINA_TRUE;
+ } else {
+ return EINA_FALSE;
+ }
+}
+
+static void
+panel_slot_process_key_event (int context, const KeyEvent &key)
+{
+ WSCContextISF *ic = find_ic (context);
+ Eina_Bool process_key = EINA_TRUE;
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
+
+ if (!(ic && ic->impl))
+ return;
+
+ if ((_focused_ic != NULL) && (_focused_ic != ic))
+ return;
+
+ KeyEvent _key = key;
+ if (key.is_key_press () &&
+ wsc_context_input_panel_layout_get (ic->ctx) == ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL) {
+ if (key.code == SHIFT_MODE_OFF ||
+ key.code == SHIFT_MODE_ON ||
+ key.code == SHIFT_MODE_LOCK) {
+ ic->impl->next_shift_status = _key.code;
+ } else if (key.code == SHIFT_MODE_ENABLE ) {
+ ic->impl->shift_mode_enabled = true;
+ caps_mode_check (ic, EINA_TRUE, EINA_TRUE);
+ } else if (key.code == SHIFT_MODE_DISABLE ) {
+ ic->impl->shift_mode_enabled = false;
+ }
+ }
+
+ if (key.code != SHIFT_MODE_OFF &&
+ key.code != SHIFT_MODE_ON &&
+ key.code != SHIFT_MODE_LOCK &&
+ key.code != SHIFT_MODE_ENABLE &&
+ key.code != SHIFT_MODE_DISABLE) {
+ if (ic->impl->preedit_string.length() < 1) {
+ if (!((key.code >= 'a' && key.code <= 'z') ||
+ (key.code >= 'A' && key.code <= 'Z'))) {
+ if (feed_key_event (ic, _key, false)) return;
+ }
+ }
+ }
+
+ if (key.code == SHIFT_MODE_ENABLE ||
+ key.code == SHIFT_MODE_DISABLE) {
+ process_key = EINA_FALSE;
+ }
+
+ _panel_client.prepare (ic->id);
+
+ if (!filter_hotkeys (ic, _key)) {
+ if (process_key) {
+ if (!_focused_ic || !_focused_ic->impl->is_on ||
+ !_focused_ic->impl->si->process_key_event (_key)) {
+ _fallback_instance->process_key_event (_key);
+ }
+ }
+ }
+
+ _panel_client.send ();
+}
+
+static void
+panel_slot_commit_string (int context, const WideString &wstr)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " str=" << utf8_wcstombs (wstr) << " ic=" << ic << "\n";
+
+ if (ic && ic->impl) {
+ if (_focused_ic != ic)
+ return;
+
+ if (utf8_wcstombs (wstr) == String (" ") || utf8_wcstombs (wstr) == String (" "))
+ autoperiod_insert (ic);
+
+ if (ic->impl->need_commit_preedit)
+ _hide_preedit_string (ic->id, false);
+ wsc_context_commit_string (ic->ctx, utf8_wcstombs (wstr).c_str ());
+ }
+}
+
+static void
+panel_slot_forward_key_event (int context, const KeyEvent &key)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
+
+ if (!(ic && ic->impl))
+ return;
+
+ if ((_focused_ic != NULL) && (_focused_ic != ic))
+ return;
+
+ if (strlen (key.get_key_string ().c_str ()) >= 116)
+ return;
+
+ feed_key_event (ic, key, true);
+}
+
+static void
+panel_slot_request_help (int context)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
+ if (ic && ic->impl) {
+ _panel_client.prepare (ic->id);
+ panel_req_show_help (ic);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_request_factory_menu (int context)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
+ if (ic && ic->impl) {
+ _panel_client.prepare (ic->id);
+ panel_req_show_factory_menu (ic);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_change_factory (int context, const String &uuid)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " factory=" << uuid << " ic=" << ic << "\n";
+ if (ic && ic->impl) {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->reset ();
+ open_specific_factory (ic, uuid);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_reset_keyboard_ise (int context)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
+ if (ic && ic->impl) {
+ WideString wstr = ic->impl->preedit_string;
+ if (ic->impl->need_commit_preedit) {
+ _hide_preedit_string (ic->id, false);
+
+ if (wstr.length ()) {
+ wsc_context_commit_string (ic->ctx, utf8_wcstombs (wstr).c_str ());
+ if (!check_valid_ic (ic))
+ return;
+ }
+ }
+ _panel_client.prepare (ic->id);
+ ic->impl->si->reset ();
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_update_keyboard_ise (int context)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
+
+ _backend->add_module (_config, "socket", false);
+}
+
+static void
+panel_slot_show_preedit_string (int context)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << "\n";
+
+ if (ic && ic->impl && _focused_ic == ic) {
+ if (!ic->impl->is_on)
+ ic->impl->is_on = true;
+
+ if (ic->impl->use_preedit) {
+ if (!ic->impl->preedit_started) {
+ if (check_valid_ic (ic)) {
+ ic->impl->preedit_started = true;
+ ic->impl->need_commit_preedit = true;
+ }
+ }
+ } else {
+ _panel_client.prepare (ic->id);
+ _panel_client.show_preedit_string (ic->id);
+ _panel_client.send ();
+ }
+ }
+}
+
+static void
+_hide_preedit_string (int context, bool update_preedit)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = find_ic (context);
+
+ if (ic && ic->impl && _focused_ic == ic) {
+ if (!ic->impl->is_on)
+ ic->impl->is_on = true;
+
+ bool emit = false;
+ if (ic->impl->preedit_string.length ()) {
+ ic->impl->preedit_string = WideString ();
+ ic->impl->preedit_caret = 0;
+ ic->impl->preedit_attrlist.clear ();
+ emit = true;
+ }
+ if (ic->impl->use_preedit) {
+ if (update_preedit && emit) {
+ if (!check_valid_ic (ic))
+ return;
+ }
+ if (ic->impl->preedit_started) {
+ if (check_valid_ic (ic)) {
+ ic->impl->preedit_started = false;
+ ic->impl->need_commit_preedit = false;
+ }
+ }
+ wsc_context_send_preedit_string(ic->ctx);
+ } else {
+ _panel_client.prepare (ic->id);
+ _panel_client.hide_preedit_string (ic->id);
+ _panel_client.send ();
+ }
+ }
+}
+
+static void
+panel_slot_hide_preedit_string (int context)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ _hide_preedit_string (context, true);
+}
+
+static void
+panel_slot_update_preedit_string (int context,
+ const WideString &str,
+ const AttributeList &attrs,
+ int caret)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = find_ic (context);
+
+ if (ic && ic->impl && _focused_ic == ic) {
+ if (!ic->impl->is_on)
+ ic->impl->is_on = true;
+
+ if (ic->impl->preedit_string != str || str.length ()) {
+ ic->impl->preedit_string = str;
+ ic->impl->preedit_attrlist = attrs;
+
+ if (ic->impl->use_preedit) {
+ if (!ic->impl->preedit_started) {
+ if (!check_valid_ic (ic))
+ return;
+
+ ic->impl->preedit_started = true;
+ ic->impl->need_commit_preedit = true;
+ }
+ if (caret >= 0 && caret <= (int)str.length ())
+ ic->impl->preedit_caret = caret;
+ else
+ ic->impl->preedit_caret = str.length ();
+ ic->impl->preedit_updating = true;
+ if (check_valid_ic (ic))
+ ic->impl->preedit_updating = false;
+ wsc_context_send_preedit_string(ic->ctx);
+ } else {
+ _panel_client.prepare (ic->id);
+ _panel_client.update_preedit_string (ic->id, str, attrs, caret);
+ _panel_client.send ();
+ }
+ }
+ }
+}
+
+static void
+panel_slot_get_surrounding_text (int context, int maxlen_before, int maxlen_after)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = find_ic (context);
+
+ if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
+ int cursor = 0;
+ WideString text = WideString ();
+ slot_get_surrounding_text (ic->impl->si, text, cursor, maxlen_before, maxlen_after);
+ _panel_client.prepare (ic->id);
+ _panel_client.update_surrounding_text (ic->id, text, cursor);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_delete_surrounding_text (int context, int offset, int len)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = find_ic (context);
+
+ if (ic && ic->impl && _focused_ic == ic && ic->impl->si)
+ slot_delete_surrounding_text (ic->impl->si, offset, len);
+}
+
+static void
+panel_slot_update_displayed_candidate_number (int context, int number)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " number=" << number << " ic=" << ic << "\n";
+ if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->update_displayed_candidate_number (number);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_candidate_more_window_show (int context)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
+ if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->candidate_more_window_show ();
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_candidate_more_window_hide (int context)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
+ if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->candidate_more_window_hide ();
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_longpress_candidate (int context, int index)
+{
+ WSCContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " index=" << index << " ic=" << ic << "\n";
+ if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->longpress_candidate (index);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_update_ise_input_context (int context, int type, int value)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+}
+
+static void
+panel_slot_update_isf_candidate_panel (int context, int type, int value)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+}
+
+void
+initialize (void)
+{
+ std::vector<String> config_list;
+ std::vector<String> engine_list;
+ std::vector<String> helper_list;
+ std::vector<String> load_engine_list;
+
+ std::vector<String>::iterator it;
+
+ bool manual = false;
+ bool socket = true;
+ String config_module_name = "simple";
+
+ LOGD ("Initializing Ecore ISF IMModule...\n");
+
+ // Get system language.
+ _language = scim_get_locale_language (scim_get_current_locale ());
+
+ if (socket) {
+ // If no Socket FrontEnd is running, then launch one.
+ // And set manual to false.
+ bool check_result = check_socket_frontend ();
+ if (!check_result) {
+ std::cerr << "Launching a ISF daemon with Socket FrontEnd...\n";
+ //get modules list
+ scim_get_imengine_module_list (engine_list);
+ scim_get_helper_module_list (helper_list);
+
+ for (it = engine_list.begin (); it != engine_list.end (); it++) {
+ if (*it != "socket")
+ load_engine_list.push_back (*it);
+ }
+ for (it = helper_list.begin (); it != helper_list.end (); it++)
+ load_engine_list.push_back (*it);
+ const char *new_argv [] = { "--no-stay", 0 };
+ scim_launch (true,
+ config_module_name,
+ (load_engine_list.size () > 0 ? scim_combine_string_list (load_engine_list, ',') : "none"),
+ "socket",
+ (char **)new_argv);
+ manual = false;
+ }
+
+ // If there is one Socket FrontEnd running and it's not manual mode,
+ // then just use this Socket Frontend.
+ if (!manual) {
+ for (int i = 0; i < 200; ++i) {
+ if (check_result) {
+ config_module_name = "socket";
+ load_engine_list.clear ();
+ load_engine_list.push_back ("socket");
+ break;
+ }
+ scim_usleep (50000);
+ check_result = check_socket_frontend ();
+ }
+ }
+ }
+
+ if (config_module_name != "dummy") {
+ _config = ConfigBase::get (true, config_module_name);
+ }
+
+ if (_config.null ()) {
+ LOGD ("Config module cannot be loaded, using dummy Config.\n");
+ _config = new DummyConfig ();
+ config_module_name = "dummy";
+ }
+
+ reload_config_callback (_config);
+ _config_connection = _config->signal_connect_reload (slot (reload_config_callback));
+
+ // create backend
+ _backend = new CommonBackEnd (_config, load_engine_list.size () > 0 ? load_engine_list : engine_list);
+
+ if (_backend.null ()) {
+ std::cerr << "Cannot create BackEnd Object!\n";
+ } else {
+ _backend->initialize (_config, load_engine_list.size () > 0 ? load_engine_list : engine_list, false, false);
+ _fallback_factory = _backend->get_factory (SCIM_COMPOSE_KEY_FACTORY_UUID);
+ }
+
+ if (_fallback_factory.null ())
+ _fallback_factory = new DummyIMEngineFactory ();
+
+ _fallback_instance = _fallback_factory->create_instance (String ("UTF-8"), 0);
+ _fallback_instance->signal_connect_commit_string (slot (fallback_commit_string_cb));
+
+ // Attach Panel Client signal.
+ _panel_client.signal_connect_reload_config (slot (panel_slot_reload_config));
+ _panel_client.signal_connect_exit (slot (panel_slot_exit));
+ _panel_client.signal_connect_update_candidate_item_layout (slot (panel_slot_update_candidate_item_layout));
+ _panel_client.signal_connect_update_lookup_table_page_size (slot (panel_slot_update_lookup_table_page_size));
+ _panel_client.signal_connect_lookup_table_page_up (slot (panel_slot_lookup_table_page_up));
+ _panel_client.signal_connect_lookup_table_page_down (slot (panel_slot_lookup_table_page_down));
+ _panel_client.signal_connect_trigger_property (slot (panel_slot_trigger_property));
+ _panel_client.signal_connect_process_helper_event (slot (panel_slot_process_helper_event));
+ _panel_client.signal_connect_move_preedit_caret (slot (panel_slot_move_preedit_caret));
+ _panel_client.signal_connect_update_preedit_caret (slot (panel_slot_update_preedit_caret));
+ _panel_client.signal_connect_select_aux (slot (panel_slot_select_aux));
+ _panel_client.signal_connect_select_candidate (slot (panel_slot_select_candidate));
+ _panel_client.signal_connect_process_key_event (slot (panel_slot_process_key_event));
+ _panel_client.signal_connect_commit_string (slot (panel_slot_commit_string));
+ _panel_client.signal_connect_forward_key_event (slot (panel_slot_forward_key_event));
+ _panel_client.signal_connect_request_help (slot (panel_slot_request_help));
+ _panel_client.signal_connect_request_factory_menu (slot (panel_slot_request_factory_menu));
+ _panel_client.signal_connect_change_factory (slot (panel_slot_change_factory));
+ _panel_client.signal_connect_reset_keyboard_ise (slot (panel_slot_reset_keyboard_ise));
+ _panel_client.signal_connect_update_keyboard_ise (slot (panel_slot_update_keyboard_ise));
+ _panel_client.signal_connect_show_preedit_string (slot (panel_slot_show_preedit_string));
+ _panel_client.signal_connect_hide_preedit_string (slot (panel_slot_hide_preedit_string));
+ _panel_client.signal_connect_update_preedit_string (slot (panel_slot_update_preedit_string));
+ _panel_client.signal_connect_get_surrounding_text (slot (panel_slot_get_surrounding_text));
+ _panel_client.signal_connect_delete_surrounding_text (slot (panel_slot_delete_surrounding_text));
+ _panel_client.signal_connect_update_displayed_candidate_number (slot (panel_slot_update_displayed_candidate_number));
+ _panel_client.signal_connect_candidate_more_window_show (slot (panel_slot_candidate_more_window_show));
+ _panel_client.signal_connect_candidate_more_window_hide (slot (panel_slot_candidate_more_window_hide));
+ _panel_client.signal_connect_longpress_candidate (slot (panel_slot_longpress_candidate));
+ _panel_client.signal_connect_update_ise_input_context (slot (panel_slot_update_ise_input_context));
+ _panel_client.signal_connect_update_isf_candidate_panel (slot (panel_slot_update_isf_candidate_panel));
+
+ if (!panel_initialize ()) {
+ std::cerr << "Ecore IM Module: Cannot connect to Panel!\n";
+ }
+}
+
+static void
+finalize (void)
+{
+ LOGD ("Finalizing Ecore ISF IMModule...\n");
+
+ // Reset this first so that the shared instance could be released correctly afterwards.
+ _default_instance.reset ();
+
+ SCIM_DEBUG_FRONTEND(2) << "Finalize all IC partially.\n";
+ while (_used_ic_impl_list) {
+ // In case in "shared input method" mode,
+ // all contexts share only one instance,
+ // so we need point the reference pointer correctly before finalizing.
+ _used_ic_impl_list->si->set_frontend_data (static_cast <void*> (_used_ic_impl_list->parent));
+ isf_wsc_context_del (_used_ic_impl_list->parent);
+ }
+
+ delete_all_ic_impl ();
+
+ _fallback_instance.reset ();
+ _fallback_factory.reset ();
+
+ SCIM_DEBUG_FRONTEND(2) << " Releasing BackEnd...\n";
+ _backend.reset ();
+
+ SCIM_DEBUG_FRONTEND(2) << " Releasing Config...\n";
+ _config.reset ();
+ _config_connection.disconnect ();
+
+ _focused_ic = NULL;
+ _ic_list = NULL;
+
+ _scim_initialized = false;
+
+ _panel_client.reset_signal_handler ();
+ panel_finalize ();
+}
+
+static void
+_display_input_language (WSCContextISF *ic)
+{
+}
+
+static void
+open_next_factory (WSCContextISF *ic)
+{
+ if (!check_valid_ic (ic))
+ return;
+
+ SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
+ IMEngineFactoryPointer sf = _backend->get_next_factory ("", "UTF-8", ic->impl->si->get_factory_uuid ());
+
+ if (!sf.null ()) {
+ turn_off_ic (ic);
+ ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
+ ic->impl->si->set_frontend_data (static_cast <void*> (ic));
+ ic->impl->preedit_string = WideString ();
+ ic->impl->preedit_caret = 0;
+ attach_instance (ic->impl->si);
+ _backend->set_default_factory (_language, sf->get_uuid ());
+ _panel_client.register_input_context (ic->id, sf->get_uuid ());
+ _panel_client.set_candidate_style (ic->id, ONE_LINE_CANDIDATE, FIXED_CANDIDATE_WINDOW);
+ set_ic_capabilities (ic);
+ turn_on_ic (ic);
+
+ if (_shared_input_method) {
+ _default_instance = ic->impl->si;
+ ic->impl->shared_si = true;
+ }
+ //_popup_message (utf8_wcstombs (sf->get_name ()).c_str ());
+ }
+}
+
+static void
+open_previous_factory (WSCContextISF *ic)
+{
+ if (!check_valid_ic (ic))
+ return;
+
+ SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
+ IMEngineFactoryPointer sf = _backend->get_previous_factory ("", "UTF-8", ic->impl->si->get_factory_uuid ());
+
+ if (!sf.null ()) {
+ turn_off_ic (ic);
+ ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
+ ic->impl->si->set_frontend_data (static_cast <void*> (ic));
+ ic->impl->preedit_string = WideString ();
+ ic->impl->preedit_caret = 0;
+ attach_instance (ic->impl->si);
+ _backend->set_default_factory (_language, sf->get_uuid ());
+ _panel_client.register_input_context (ic->id, sf->get_uuid ());
+ _panel_client.set_candidate_style (ic->id, ONE_LINE_CANDIDATE, FIXED_CANDIDATE_WINDOW);
+ set_ic_capabilities (ic);
+ turn_on_ic (ic);
+
+ if (_shared_input_method) {
+ _default_instance = ic->impl->si;
+ ic->impl->shared_si = true;
+ }
+ //_popup_message (utf8_wcstombs (sf->get_name ()).c_str ());
+ }
+}
+
+static void
+open_specific_factory (WSCContextISF *ic,
+ const String &uuid)
+{
+ if (!check_valid_ic (ic))
+ return;
+
+ SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
+
+ // The same input method is selected, just turn on the IC.
+ if (ic->impl->si->get_factory_uuid () == uuid) {
+ turn_on_ic (ic);
+ return;
+ }
+
+ IMEngineFactoryPointer sf = _backend->get_factory (uuid);
+
+ if (uuid.length () && !sf.null ()) {
+ turn_off_ic (ic);
+ ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
+ ic->impl->si->set_frontend_data (static_cast <void*> (ic));
+ ic->impl->preedit_string = WideString ();
+ ic->impl->preedit_caret = 0;
+ attach_instance (ic->impl->si);
+ _backend->set_default_factory (_language, sf->get_uuid ());
+ _panel_client.register_input_context (ic->id, sf->get_uuid ());
+ set_ic_capabilities (ic);
+ turn_on_ic (ic);
+
+ if (_shared_input_method) {
+ _default_instance = ic->impl->si;
+ ic->impl->shared_si = true;
+ }
+ } else {
+ std::cerr << "open_specific_factory () is failed!!!!!!\n";
+ LOGE ("open_specific_factory () is failed. ic : %x uuid : %s", ic->id, uuid.c_str ());
+
+ // turn_off_ic comment out panel_req_update_factory_info ()
+ //turn_off_ic (ic);
+ if (ic && ic->impl->is_on) {
+ ic->impl->is_on = false;
+
+ if (ic == _focused_ic) {
+ ic->impl->si->focus_out ();
+
+ panel_req_update_factory_info (ic);
+ _panel_client.turn_off (ic->id);
+ }
+
+ //Record the IC on/off status
+ if (_shared_input_method) {
+ _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
+ _config->flush ();
+ }
+
+ if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
+ if (!check_valid_ic (ic))
+ return;
+
+ if (check_valid_ic (ic))
+ ic->impl->preedit_started = false;
+ }
+ }
+ }
+}
+
+#define MOD_SHIFT_MASK 0x01
+#define MOD_ALT_MASK 0x02
+#define MOD_CONTROL_MASK 0x04
+
+static uint32_t _keyname_to_keysym(uint32_t keyname, uint32_t *modifiers)
+{
+ if (!modifiers)
+ return keyname;
+
+ if ((keyname >= '0' && keyname <= '9') ||
+ (keyname >= 'a' && keyname <= 'z')) {
+ return keyname;
+ }
+ else if (keyname >= 'A' && keyname <= 'Z') {
+ *modifiers |= MOD_SHIFT_MASK;
+ return keyname + 32;
+ }
+
+ switch (keyname) {
+ case '!':
+ *modifiers |= MOD_SHIFT_MASK;
+ return '1';
+ case '@':
+ *modifiers |= MOD_SHIFT_MASK;
+ return '2';
+ case '#':
+ *modifiers |= MOD_SHIFT_MASK;
+ return '3';
+ case '$':
+ *modifiers |= MOD_SHIFT_MASK;
+ return '4';
+ case '%':
+ *modifiers |= MOD_SHIFT_MASK;
+ return '5';
+ case '^':
+ *modifiers |= MOD_SHIFT_MASK;
+ return '6';
+ case '&':
+ *modifiers |= MOD_SHIFT_MASK;
+ return '7';
+ case '*':
+ *modifiers |= MOD_SHIFT_MASK;
+ return '8';
+ case '(':
+ *modifiers |= MOD_SHIFT_MASK;
+ return '9';
+ case ')':
+ *modifiers |= MOD_SHIFT_MASK;
+ return '0';
+ case '_':
+ *modifiers |= MOD_SHIFT_MASK;
+ return '-';
+ case '+':
+ *modifiers |= MOD_SHIFT_MASK;
+ return '=';
+ case '{':
+ *modifiers |= MOD_SHIFT_MASK;
+ return '[';
+ case '}':
+ *modifiers |= MOD_SHIFT_MASK;
+ return ']';
+ case '|':
+ *modifiers |= MOD_SHIFT_MASK;
+ return '\\';
+ case '\:':
+ *modifiers |= MOD_SHIFT_MASK;
+ return ';';
+ case '\"':
+ *modifiers |= MOD_SHIFT_MASK;
+ return '\'';
+ case '<':
+ *modifiers |= MOD_SHIFT_MASK;
+ return ',';
+ case '>':
+ *modifiers |= MOD_SHIFT_MASK;
+ return '.';
+ case '?':
+ *modifiers |= MOD_SHIFT_MASK;
+ return '/';
+ default:
+ return keyname;
+ }
+}
+
+static void send_wl_key_event (WSCContextISF *ic, const KeyEvent &key, bool fake)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ uint32_t time = 0;
+ uint32_t sym = 0;
+
+ if (!fake)
+ time = get_time ();
+
+ uint32_t modifiers = 0;
+ if (key.is_shift_down ())
+ modifiers |= MOD_SHIFT_MASK;
+ if (key.is_alt_down ())
+ modifiers |= MOD_ALT_MASK;
+ if (key.is_control_down ())
+ modifiers |= MOD_CONTROL_MASK;
+
+ sym = _keyname_to_keysym(key.code, &modifiers);
+ wsc_context_send_key(ic->ctx, sym, modifiers, time, key.is_key_press());
+}
+
+static void
+attach_instance (const IMEngineInstancePointer &si)
+{
+ si->signal_connect_show_preedit_string (
+ slot (slot_show_preedit_string));
+ si->signal_connect_show_aux_string (
+ slot (slot_show_aux_string));
+ si->signal_connect_show_lookup_table (
+ slot (slot_show_lookup_table));
+
+ si->signal_connect_hide_preedit_string (
+ slot (slot_hide_preedit_string));
+ si->signal_connect_hide_aux_string (
+ slot (slot_hide_aux_string));
+ si->signal_connect_hide_lookup_table (
+ slot (slot_hide_lookup_table));
+
+ si->signal_connect_update_preedit_caret (
+ slot (slot_update_preedit_caret));
+ si->signal_connect_update_preedit_string (
+ slot (slot_update_preedit_string));
+ si->signal_connect_update_aux_string (
+ slot (slot_update_aux_string));
+ si->signal_connect_update_lookup_table (
+ slot (slot_update_lookup_table));
+
+ si->signal_connect_commit_string (
+ slot (slot_commit_string));
+
+ si->signal_connect_forward_key_event (
+ slot (slot_forward_key_event));
+
+ si->signal_connect_register_properties (
+ slot (slot_register_properties));
+
+ si->signal_connect_update_property (
+ slot (slot_update_property));
+
+ si->signal_connect_beep (
+ slot (slot_beep));
+
+ si->signal_connect_start_helper (
+ slot (slot_start_helper));
+
+ si->signal_connect_stop_helper (
+ slot (slot_stop_helper));
+
+ si->signal_connect_send_helper_event (
+ slot (slot_send_helper_event));
+
+ si->signal_connect_get_surrounding_text (
+ slot (slot_get_surrounding_text));
+
+ si->signal_connect_delete_surrounding_text (
+ slot (slot_delete_surrounding_text));
+
+ si->signal_connect_expand_candidate (
+ slot (slot_expand_candidate));
+ si->signal_connect_contract_candidate (
+ slot (slot_contract_candidate));
+
+ si->signal_connect_set_candidate_style (
+ slot (slot_set_candidate_style));
+}
+
+// Implementation of slot functions
+static void
+slot_show_preedit_string (IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic) {
+ if (ic->impl->use_preedit) {
+ if (!ic->impl->preedit_started) {
+ if (check_valid_ic (ic))
+ ic->impl->preedit_started = true;
+ }
+ } else {
+ _panel_client.show_preedit_string (ic->id);
+ }
+ }
+}
+
+static void
+slot_show_aux_string (IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.show_aux_string (ic->id);
+}
+
+static void
+slot_show_lookup_table (IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.show_lookup_table (ic->id);
+}
+
+static void
+slot_hide_preedit_string (IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic) {
+ bool emit = false;
+ if (ic->impl->preedit_string.length ()) {
+ ic->impl->preedit_string = WideString ();
+ ic->impl->preedit_caret = 0;
+ ic->impl->preedit_attrlist.clear ();
+ emit = true;
+ }
+ if (ic->impl->use_preedit) {
+ if (check_valid_ic (ic) && ic->impl->preedit_started) {
+ if (check_valid_ic (ic))
+ ic->impl->preedit_started = false;
+ }
+ wsc_context_send_preedit_string(ic->ctx);
+ } else {
+ _panel_client.hide_preedit_string (ic->id);
+ }
+ }
+}
+
+static void
+slot_hide_aux_string (IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.hide_aux_string (ic->id);
+}
+
+static void
+slot_hide_lookup_table (IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.hide_lookup_table (ic->id);
+}
+
+static void
+slot_update_preedit_caret (IMEngineInstanceBase *si, int caret)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret) {
+ ic->impl->preedit_caret = caret;
+ if (ic->impl->use_preedit) {
+ if (!ic->impl->preedit_started) {
+ if (!check_valid_ic (ic))
+ return;
+
+ ic->impl->preedit_started = true;
+ }
+ } else {
+ _panel_client.update_preedit_caret (ic->id, caret);
+ }
+ }
+}
+
+static void
+slot_update_preedit_string (IMEngineInstanceBase *si,
+ const WideString & str,
+ const AttributeList & attrs,
+ int caret)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic && (ic->impl->preedit_string != str || str.length ())) {
+ ic->impl->preedit_string = str;
+ ic->impl->preedit_attrlist = attrs;
+ if (ic->impl->use_preedit) {
+ if (!ic->impl->preedit_started) {
+ if (!check_valid_ic (ic))
+ return;
+
+ ic->impl->preedit_started = true;
+ }
+ if (caret >= 0 && caret <= (int)str.length ())
+ ic->impl->preedit_caret = caret;
+ else
+ ic->impl->preedit_caret = str.length ();
+ ic->impl->preedit_updating = true;
+ if (check_valid_ic (ic))
+ ic->impl->preedit_updating = false;
+ wsc_context_send_preedit_string(ic->ctx);
+ } else {
+ _panel_client.update_preedit_string (ic->id, str, attrs, caret);
+ }
+ }
+}
+
+static void
+slot_update_aux_string (IMEngineInstanceBase *si,
+ const WideString & str,
+ const AttributeList & attrs)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.update_aux_string (ic->id, str, attrs);
+}
+
+static void
+slot_commit_string (IMEngineInstanceBase *si,
+ const WideString & str)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->ctx) {
+ if (utf8_wcstombs (str) == String (" ") || utf8_wcstombs (str) == String (" "))
+ autoperiod_insert (ic);
+
+ Eina_Bool auto_capitalized = EINA_FALSE;
+
+ if (ic->impl) {
+ if (wsc_context_input_panel_layout_get (ic->ctx) == ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL &&
+ ic->impl->shift_mode_enabled &&
+ ic->impl->autocapital_type != ECORE_IMF_AUTOCAPITAL_TYPE_NONE &&
+ hw_keyboard_num_get () == 0) {
+ char converted[2] = {'\0'};
+ if (utf8_wcstombs (str).length () == 1) {
+ Eina_Bool uppercase;
+ switch (ic->impl->next_shift_status) {
+ case 0:
+ uppercase = caps_mode_check (ic, EINA_FALSE, EINA_FALSE);
+ break;
+ case SHIFT_MODE_OFF:
+ uppercase = EINA_FALSE;
+ ic->impl->next_shift_status = 0;
+ break;
+ case SHIFT_MODE_ON:
+ uppercase = EINA_TRUE;
+ ic->impl->next_shift_status = 0;
+ break;
+ case SHIFT_MODE_LOCK:
+ uppercase = EINA_TRUE;
+ break;
+ default:
+ uppercase = EINA_FALSE;
+ }
+ converted[0] = utf8_wcstombs (str).at (0);
+ if (uppercase) {
+ if (converted[0] >= 'a' && converted[0] <= 'z')
+ converted[0] -= 32;
+ } else {
+ if (converted[0] >= 'A' && converted[0] <= 'Z')
+ converted[0] += 32;
+ }
+
+ wsc_context_commit_string (ic->ctx, converted);
+ auto_capitalized = EINA_TRUE;
+ }
+ }
+ }
+
+ if (!auto_capitalized) {
+ wsc_context_commit_string (ic->ctx, utf8_wcstombs (str).c_str ());
+ }
+ }
+}
+
+static void
+slot_forward_key_event (IMEngineInstanceBase *si,
+ const KeyEvent & key)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && _focused_ic == ic) {
+ if (!_fallback_instance->process_key_event (key)) {
+ feed_key_event (ic, key, true);
+ }
+ }
+}
+
+static void
+slot_update_lookup_table (IMEngineInstanceBase *si,
+ const LookupTable & table)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.update_lookup_table (ic->id, table);
+}
+
+static void
+slot_register_properties (IMEngineInstanceBase *si,
+ const PropertyList & properties)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.register_properties (ic->id, properties);
+}
+
+static void
+slot_update_property (IMEngineInstanceBase *si,
+ const Property & property)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.update_property (ic->id, property);
+}
+
+static void
+slot_beep (IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+}
+
+static void
+slot_start_helper (IMEngineInstanceBase *si,
+ const String &helper_uuid)
+{
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context="
+ << (ic != NULL ? ic->id : -1) << " ic=" << ic
+ << " ic-uuid=" << ((ic != NULL && ic->impl != NULL) ? ic->impl->si->get_factory_uuid () : "") << "...\n";
+
+ if (ic && ic->impl)
+ _panel_client.start_helper (ic->id, helper_uuid);
+}
+
+static void
+slot_stop_helper (IMEngineInstanceBase *si,
+ const String &helper_uuid)
+{
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context=" << (ic != NULL ? ic->id : -1) << " ic=" << ic << "...\n";
+
+ if (ic && ic->impl)
+ _panel_client.stop_helper (ic->id, helper_uuid);
+}
+
+static void
+slot_send_helper_event (IMEngineInstanceBase *si,
+ const String &helper_uuid,
+ const Transaction &trans)
+{
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context="
+ << (ic != NULL ? ic->id : -1) << " ic=" << ic
+ << " ic-uuid=" << ((ic != NULL && ic->impl != NULL) ? ic->impl->si->get_factory_uuid () : "") << "...\n";
+
+ if (ic && ic->impl)
+ _panel_client.send_helper_event (ic->id, helper_uuid, trans);
+}
+
+static bool
+slot_get_surrounding_text (IMEngineInstanceBase *si,
+ WideString &text,
+ int &cursor,
+ int maxlen_before,
+ int maxlen_after)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic) {
+ char *surrounding = NULL;
+ int cursor_index;
+ if (wsc_context_surrounding_get (_focused_ic->ctx, &surrounding, &cursor_index)) {
+ SCIM_DEBUG_FRONTEND(2) << "Surrounding text: " << surrounding <<"\n";
+ SCIM_DEBUG_FRONTEND(2) << "Cursor Index : " << cursor_index <<"\n";
+
+ if (!surrounding)
+ return false;
+
+ if (cursor_index < 0) {
+ free (surrounding);
+ surrounding = NULL;
+ return false;
+ }
+
+ WideString before = utf8_mbstowcs (String (surrounding));
+ free (surrounding);
+ surrounding = NULL;
+
+ if (cursor_index > (int)before.length ())
+ return false;
+ WideString after = before;
+ before = before.substr (0, cursor_index);
+ after = after.substr (cursor_index, after.length () - cursor_index);
+ if (maxlen_before > 0 && ((unsigned int)maxlen_before) < before.length ())
+ before = WideString (before.begin () + (before.length () - maxlen_before), before.end ());
+ else if (maxlen_before == 0)
+ before = WideString ();
+ if (maxlen_after > 0 && ((unsigned int)maxlen_after) < after.length ())
+ after = WideString (after.begin (), after.begin () + maxlen_after);
+ else if (maxlen_after == 0)
+ after = WideString ();
+ text = before + after;
+ cursor = before.length ();
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool
+slot_delete_surrounding_text (IMEngineInstanceBase *si,
+ int offset,
+ int len)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic) {
+ wsc_context_delete_surrounding(_focused_ic->ctx, offset, len);
+ return true;
+ }
+ return false;
+}
+
+static void
+slot_expand_candidate (IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.expand_candidate (ic->id);
+}
+
+static void
+slot_contract_candidate (IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.contract_candidate (ic->id);
+}
+
+static void
+slot_set_candidate_style (IMEngineInstanceBase *si, ISF_CANDIDATE_PORTRAIT_LINE_T portrait_line, ISF_CANDIDATE_MODE_T mode)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ WSCContextISF *ic = static_cast<WSCContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.set_candidate_style (ic->id, portrait_line, mode);
+}
+
+static void
+reload_config_callback (const ConfigPointer &config)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ _frontend_hotkey_matcher.load_hotkeys (config);
+ _imengine_hotkey_matcher.load_hotkeys (config);
+
+ KeyEvent key;
+ scim_string_to_key (key,
+ config->read (String (SCIM_CONFIG_HOTKEYS_FRONTEND_VALID_KEY_MASK),
+ String ("Shift+Control+Alt+Lock")));
+
+ _valid_key_mask = (key.mask > 0) ? (key.mask) : 0xFFFF;
+ _valid_key_mask |= SCIM_KEY_ReleaseMask;
+ // Special treatment for two backslash keys on jp106 keyboard.
+ _valid_key_mask |= SCIM_KEY_QuirkKanaRoMask;
+
+ _on_the_spot = config->read (String (SCIM_CONFIG_FRONTEND_ON_THE_SPOT), _on_the_spot);
+ _shared_input_method = config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), _shared_input_method);
+
+ // Get keyboard layout setting
+ // Flush the global config first, in order to load the new configs from disk.
+ scim_global_config_flush ();
+
+ _keyboard_layout = scim_get_default_keyboard_layout ();
+}
+
+static void
+fallback_commit_string_cb (IMEngineInstanceBase *si,
+ const WideString &str)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (_focused_ic && _focused_ic->impl) {
+ wsc_context_commit_string (_focused_ic->ctx, utf8_wcstombs (str).c_str ());
+ }
+}
+
--- /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 __ISF_WSC_CONTEXT_H_
+#define __ISF_WSC_CONTEXT_H_
+
+#include <Ecore.h>
+#include <Ecore_IMF.h>
+#include <dlog.h>
+
+struct weescim;
+
+const double DOUBLE_SPACE_INTERVAL = 1.0;
+const double HIDE_TIMER_INTERVAL = 0.05;
+const double WILL_SHOW_TIMER_INTERVAL = 5.0;
+
+typedef struct _WSCContextISF WSCContextISF;
+typedef struct _WSCContextISFImpl WSCContextISFImpl;
+
+struct _WSCContextISF {
+ weescim *ctx;
+
+ WSCContextISFImpl *impl;
+
+ int id; /* Input Context id*/
+ _WSCContextISF *next;
+};
+
+EAPI void get_language(char **language);
+EAPI int get_panel_client_id ();
+EAPI Eina_Bool caps_mode_check (WSCContextISF *ctx, Eina_Bool force, Eina_Bool noti);
+
+EAPI WSCContextISF *get_focused_ic ();
+
+EAPI void context_scim_imdata_get (WSCContextISF *ctx, void* data, int* length);
+EAPI void imengine_layout_set (WSCContextISF *ctx, Ecore_IMF_Input_Panel_Layout layout);
+
+EAPI void isf_wsc_context_add (WSCContextISF *ctx);
+EAPI void isf_wsc_context_del (WSCContextISF *ctx);
+EAPI void isf_wsc_context_focus_in (WSCContextISF *ctx);
+EAPI void isf_wsc_context_focus_out (WSCContextISF *ctx);
+EAPI void isf_wsc_context_reset (WSCContextISF *ctx);
+EAPI void isf_wsc_context_preedit_string_get (WSCContextISF *ctx, char** str, int *cursor_pos);
+EAPI void isf_wsc_context_prediction_allow_set (WSCContextISF* ctx, Eina_Bool prediction);
+
+EAPI WSCContextISF* isf_wsc_context_new (void);
+EAPI void isf_wsc_context_shutdown (void);
+
+bool wsc_context_surrounding_get (weescim *ctx, char **text, int *cursor_pos);
+Ecore_IMF_Input_Panel_Layout wsc_context_input_panel_layout_get(weescim *ctx);
+bool wsc_context_input_panel_caps_lock_mode_get(weescim *ctx);
+void wsc_context_delete_surrounding (weescim *ctx, int offset, int len);
+void wsc_context_commit_preedit_string(weescim *ctx);
+void wsc_context_commit_string(weescim *ctx, const char *str);
+void wsc_context_send_preedit_string(weescim *ctx);
+void wsc_context_send_key(weescim *ctx, uint32_t keysym, uint32_t modifiers, uint32_t time, bool press);
+
+#endif /* __ISF_WSC_CONTEXT_H_ */
--- /dev/null
+/*
+ * ISF(Input Service Framework)
+ *
+ * ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable.
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * Contact: Jihoon Kim <jihoon48.kim@samsung.com>, Haifeng Deng <haifeng.deng@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#define Uses_SCIM_TRANSACTION
+#define Uses_ISF_IMCONTROL_CLIENT
+#define Uses_SCIM_PANEL_CLIENT
+
+#include <stdio.h>
+#include <Ecore.h>
+#include <errno.h>
+#include "isf_wsc_control.h"
+#include "scim.h"
+
+
+using namespace scim;
+
+
+//#define IMFCONTROLDBG(str...) printf(str)
+#define IMFCONTROLDBG(str...)
+#define IMFCONTROLERR(str...) printf(str)
+
+
+extern PanelClient _panel_client;
+
+
+int _isf_wsc_context_input_panel_show (int client_id, int context, void *data, int length, bool &input_panel_show)
+{
+ int temp = 0;
+ _panel_client.prepare (context);
+ _panel_client.show_ise (client_id, context, data, length, &temp);
+ input_panel_show = (bool)temp;
+ return 0;
+}
+
+int _isf_wsc_context_input_panel_hide (int client_id, int context)
+{
+ _panel_client.prepare (context);
+ _panel_client.hide_ise (client_id, context);
+ _panel_client.send ();
+ return 0;
+}
+
+int _isf_wsc_context_control_panel_show (int context)
+{
+ _panel_client.prepare (context);
+ _panel_client.show_control_panel ();
+ _panel_client.send ();
+ return 0;
+}
+
+int _isf_wsc_context_control_panel_hide (int context)
+{
+ _panel_client.prepare (context);
+ _panel_client.hide_control_panel ();
+ _panel_client.send ();
+ return 0;
+}
+
+int _isf_wsc_context_input_panel_language_set (int context, Ecore_IMF_Input_Panel_Lang lang)
+{
+ _panel_client.prepare (context);
+ _panel_client.set_ise_language (lang);
+ _panel_client.send ();
+ return 0;
+}
+
+int _isf_wsc_context_input_panel_language_locale_get (int context, char **locale)
+{
+ _panel_client.prepare (context);
+ _panel_client.get_ise_language_locale (locale);
+ return 0;
+}
+
+int _isf_wsc_context_input_panel_imdata_set (int context, const void *data, int len)
+{
+ _panel_client.prepare (context);
+ _panel_client.set_imdata ((const char *)data, len);
+ _panel_client.send ();
+ return 0;
+}
+
+int _isf_wsc_context_input_panel_imdata_get (int context, void *data, int *len)
+{
+ _panel_client.prepare (context);
+ _panel_client.get_imdata ((char *)data, len);
+ return 0;
+}
+
+int _isf_wsc_context_input_panel_geometry_get (int context, int *x, int *y, int *w, int *h)
+{
+ _panel_client.prepare (context);
+ _panel_client.get_ise_window_geometry (x, y, w, h);
+ return 0;
+}
+
+int _isf_wsc_context_input_panel_return_key_type_set (int context, Ecore_IMF_Input_Panel_Return_Key_Type type)
+{
+ _panel_client.prepare (context);
+ _panel_client.set_return_key_type ((int)type);
+ _panel_client.send ();
+ return 0;
+}
+
+int _isf_wsc_context_input_panel_return_key_type_get (int context, Ecore_IMF_Input_Panel_Return_Key_Type &type)
+{
+ int temp = 0;
+ _panel_client.prepare (context);
+ _panel_client.get_return_key_type (temp);
+ type = (Ecore_IMF_Input_Panel_Return_Key_Type)temp;
+ return 0;
+}
+
+int _isf_wsc_context_input_panel_return_key_disabled_set (int context, Eina_Bool disabled)
+{
+ _panel_client.prepare (context);
+ _panel_client.set_return_key_disable ((int)disabled);
+ _panel_client.send ();
+ return 0;
+}
+
+int _isf_wsc_context_input_panel_return_key_disabled_get (int context, Eina_Bool &disabled)
+{
+ int temp = 0;
+ _panel_client.prepare (context);
+ _panel_client.get_return_key_disable (temp);
+ disabled = (Eina_Bool)temp;
+ return 0;
+}
+
+int _isf_wsc_context_input_panel_layout_set (int context, Ecore_IMF_Input_Panel_Layout layout)
+{
+ _panel_client.prepare (context);
+ _panel_client.set_layout (layout);
+ _panel_client.send ();
+ return 0;
+}
+
+int _isf_wsc_context_input_panel_layout_get (int context, Ecore_IMF_Input_Panel_Layout *layout)
+{
+ int layout_temp;
+ _panel_client.prepare (context);
+ _panel_client.get_layout (&layout_temp);
+
+ *layout = (Ecore_IMF_Input_Panel_Layout)layout_temp;
+ return 0;
+}
+
+int _isf_wsc_context_input_panel_state_get (int context, Ecore_IMF_Input_Panel_State &state)
+{
+ int temp = 0;
+ _panel_client.prepare (context);
+ _panel_client.get_ise_state (temp);
+
+ state = (Ecore_IMF_Input_Panel_State)temp;
+ return 0;
+}
+
+int _isf_wsc_context_input_panel_caps_mode_set (int context, unsigned int mode)
+{
+ _panel_client.prepare (context);
+ _panel_client.set_caps_mode (mode);
+ _panel_client.send ();
+ return 0;
+}
+
+int _isf_wsc_context_candidate_window_geometry_get (int context, int *x, int *y, int *w, int *h)
+{
+ _panel_client.prepare (context);
+ _panel_client.get_candidate_window_geometry (x, y, w, h);
+ return 0;
+}
+
+int _isf_wsc_context_input_panel_send_will_show_ack (int context)
+{
+ _panel_client.prepare (context);
+ _panel_client.send_will_show_ack ();
+ _panel_client.send ();
+ return 0;
+}
+
+int _isf_wsc_context_input_panel_send_will_hide_ack (int context)
+{
+ _panel_client.prepare (context);
+ _panel_client.send_will_hide_ack ();
+ _panel_client.send ();
+ return 0;
+}
+
+int _isf_wsc_context_set_hardware_keyboard_mode (int context)
+{
+ _panel_client.prepare (context);
+ _panel_client.set_hardware_keyboard_mode ();
+ _panel_client.send ();
+ return 0;
+}
+
+int _isf_wsc_context_input_panel_send_candidate_will_hide_ack (int context)
+{
+ _panel_client.prepare (context);
+ _panel_client.send_candidate_will_hide_ack ();
+ _panel_client.send ();
+ return 0;
+}
+
+/*
+vi:ts=4:expandtab:nowrap
+*/
--- /dev/null
+/*
+ * ISF(Input Service Framework)
+ *
+ * ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable.
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * Contact: Jihoon Kim <jihoon48.kim@samsung.com>, Haifeng Deng <haifeng.deng@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __ISF_WSC_CONTROL_H
+#define __ISF_WSC_CONTROL_H
+
+#include <Ecore_IMF.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+ int _isf_wsc_context_input_panel_show (int client_id, int context, void *data, int length, bool &input_panel_show);
+ int _isf_wsc_context_input_panel_hide (int client_id, int context);
+ int _isf_wsc_context_control_panel_show (int context);
+ int _isf_wsc_context_control_panel_hide (int context);
+
+ int _isf_wsc_context_input_panel_language_set (int context, Ecore_IMF_Input_Panel_Lang lang);
+ int _isf_wsc_context_input_panel_language_locale_get (int context, char **locale);
+
+ int _isf_wsc_context_input_panel_imdata_set (int context, const void *data, int len);
+ int _isf_wsc_context_input_panel_imdata_get (int context, void *data, int *len);
+ int _isf_wsc_context_input_panel_geometry_get (int context, int *x, int *y, int *w, int *h);
+ int _isf_wsc_context_input_panel_layout_set (int context, Ecore_IMF_Input_Panel_Layout layout);
+ int _isf_wsc_context_input_panel_layout_get (int context, Ecore_IMF_Input_Panel_Layout *layout);
+ int _isf_wsc_context_input_panel_state_get (int context, Ecore_IMF_Input_Panel_State &state);
+ int _isf_wsc_context_input_panel_return_key_type_set (int context, Ecore_IMF_Input_Panel_Return_Key_Type type);
+ int _isf_wsc_context_input_panel_return_key_type_get (int context, Ecore_IMF_Input_Panel_Return_Key_Type &type);
+ int _isf_wsc_context_input_panel_return_key_disabled_set (int context, Eina_Bool disabled);
+ int _isf_wsc_context_input_panel_return_key_disabled_get (int context, Eina_Bool &disabled);
+ int _isf_wsc_context_input_panel_caps_mode_set (int context, unsigned int mode);
+
+ int _isf_wsc_context_candidate_window_geometry_get (int context, int *x, int *y, int *w, int *h);
+
+ int _isf_wsc_context_input_panel_send_will_show_ack (int context);
+ int _isf_wsc_context_input_panel_send_will_hide_ack (int context);
+
+ int _isf_wsc_context_set_hardware_keyboard_mode (int context);
+
+ int _isf_wsc_context_input_panel_send_candidate_will_hide_ack (int context);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ISF_WSC_CONTROL_H */
+
--- /dev/null
+/*
+ * ISF(Input Service Framework)
+ *
+ * ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable.
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * Contact: Jihoon Kim <jihoon48.kim@samsung.com>, Haifeng Deng <haifeng.deng@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#define Uses_SCIM_TRANSACTION
+
+
+/* IM control UI part */
+#include <Ecore.h>
+#include <Ecore_Wayland.h>
+#include <Ecore_Evas.h>
+#include <Ecore_IMF.h>
+#include <glib.h>
+#include "scim.h"
+#include "isf_wsc_control_ui.h"
+#include "isf_wsc_context.h"
+#include "isf_wsc_control.h"
+#include "ise_context.h"
+
+using namespace scim;
+
+/* IM control related variables */
+static Ise_Context iseContext;
+static bool IfInitContext = false;
+static unsigned int hw_kbd_num = 0;
+WSCContextISF *input_panel_ctx = NULL;
+
+static void _isf_wsc_context_init (void)
+{
+ iseContext.language = ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC;
+ iseContext.return_key_type = ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
+ iseContext.return_key_disabled = FALSE;
+ iseContext.prediction_allow = TRUE;
+
+ if (!IfInitContext) {
+ IfInitContext = true;
+ }
+}
+
+static int _get_context_id (WSCContextISF *ctx)
+{
+ WSCContextISF *context_scim = ctx;
+
+ if (!context_scim) return -1;
+
+ return context_scim->id;
+}
+
+int hw_keyboard_num_get ()
+{
+ return hw_kbd_num;
+}
+
+void isf_wsc_input_panel_init (void)
+{
+ //FIXME: Use wl_input protocol to check hw keyboard.
+ hw_kbd_num = 0;
+ LOGD ("The number of connected H/W keyboard : %d\n", hw_kbd_num);
+}
+
+void isf_wsc_input_panel_shutdown (void)
+{
+}
+
+void isf_wsc_context_input_panel_show (WSCContextISF* ctx)
+{
+ int length = -1;
+ void *packet = NULL;
+ char imdata[1024] = {0};
+ bool input_panel_show = false;
+ input_panel_ctx = ctx;
+
+ if (IfInitContext == false) {
+ _isf_wsc_context_init ();
+ }
+
+ /* set password mode */
+ iseContext.password_mode = EINA_FALSE;
+
+ /* set language */
+ iseContext.language = ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC;
+
+ /* set layout in ise context info */
+ iseContext.layout = wsc_context_input_panel_layout_get (ctx->ctx);
+
+ /* set layout variation in ise context info */
+ iseContext.layout_variation = 0;
+
+ /* set prediction allow */
+ iseContext.prediction_allow = EINA_TRUE;
+
+ if (iseContext.layout == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD)
+ iseContext.password_mode = EINA_TRUE;
+
+ if (iseContext.password_mode)
+ iseContext.prediction_allow = EINA_FALSE;
+
+ if (iseContext.layout == ECORE_IMF_INPUT_PANEL_LAYOUT_TERMINAL)
+ iseContext.prediction_allow = EINA_FALSE;
+
+ isf_wsc_context_prediction_allow_set (ctx, iseContext.prediction_allow);
+
+ if (hw_kbd_num != 0) {
+ LOGD ("H/W keyboard is existed.\n");
+ return;
+ }
+
+ /* set return key type */
+ iseContext.return_key_type = ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
+
+ /* set return key disabled */
+ iseContext.return_key_disabled = EINA_FALSE;
+
+ /* set caps mode */
+ iseContext.caps_mode = caps_mode_check (ctx, EINA_TRUE, EINA_FALSE);
+
+ /* set the size of imdata */
+ context_scim_imdata_get (ctx, (void *)imdata, &iseContext.imdata_size);
+
+ /* set the cursor position of the editable widget */
+ //ecore_imf_context_surrounding_get (ctx, NULL, &iseContext.cursor_pos);
+ iseContext.cursor_pos = 0;
+
+ iseContext.autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
+
+ LOGD ("ctx : %p, layout : %d, layout variation : %d\n", ctx, iseContext.layout, iseContext.layout_variation);
+ LOGD ("language : %d, cursor position : %d, caps mode : %d\n", iseContext.language, iseContext.cursor_pos, iseContext.caps_mode);
+ LOGD ("return_key_type : %d, return_key_disabled : %d, autocapital type : %d\n", iseContext.return_key_type, iseContext.return_key_disabled, iseContext.autocapital_type);
+
+ /* calculate packet size */
+ length = sizeof (iseContext);
+ length += iseContext.imdata_size;
+
+ /* create packet */
+ packet = calloc (1, length);
+ if (!packet)
+ return;
+
+ memcpy (packet, (void *)&iseContext, sizeof (iseContext));
+ memcpy ((void *)((unsigned int)packet + sizeof (iseContext)), (void *)imdata, iseContext.imdata_size);
+
+ int context_id = _get_context_id (ctx);
+
+ _isf_wsc_context_input_panel_show (get_panel_client_id (), context_id, packet, length, input_panel_show);
+
+ free (packet);
+
+ caps_mode_check (ctx, EINA_TRUE, EINA_TRUE);
+}
+
+void isf_wsc_context_input_panel_hide (WSCContextISF *ctx)
+{
+ int context_id = _get_context_id (ctx);
+ _isf_wsc_context_input_panel_hide (get_panel_client_id (), context_id);
+}
+
+void isf_wsc_context_set_hardware_keyboard_mode (WSCContextISF *ctx)
+{
+ if (IfInitContext == false) {
+ _isf_wsc_context_init ();
+ }
+
+ hw_kbd_num = 1;
+ SECURE_LOGD ("The number of connected H/W keyboard : %d\n", hw_kbd_num);
+ _isf_wsc_context_set_hardware_keyboard_mode (_get_context_id (ctx));
+}
+
+void
+isf_wsc_context_input_panel_layout_set (WSCContextISF *ctx, Ecore_IMF_Input_Panel_Layout layout)
+{
+ WSCContextISF *context_scim = ctx;
+
+ if (!IfInitContext)
+ _isf_wsc_context_init ();
+
+ if (context_scim == get_focused_ic ()) {
+ LOGD ("layout type : %d\n", layout);
+ _isf_wsc_context_input_panel_layout_set (_get_context_id (ctx), layout);
+ imengine_layout_set (ctx, layout);
+ }
+}
+
+Ecore_IMF_Input_Panel_Layout isf_wsc_context_input_panel_layout_get (WSCContextISF *ctx)
+{
+ Ecore_IMF_Input_Panel_Layout layout;
+ if (!IfInitContext)
+ _isf_wsc_context_init ();
+ _isf_wsc_context_input_panel_layout_get (_get_context_id (ctx), &layout);
+
+ return layout;
+}
+
+void isf_wsc_context_input_panel_caps_mode_set (WSCContextISF *ctx, unsigned int mode)
+{
+ if (!IfInitContext)
+ _isf_wsc_context_init ();
+ LOGD ("ctx : %p, mode : %d\n", ctx, mode);
+ _isf_wsc_context_input_panel_caps_mode_set (_get_context_id (ctx), mode);
+}
+
+void isf_wsc_context_input_panel_caps_lock_mode_set (WSCContextISF *ctx, Eina_Bool mode)
+{
+ WSCContextISF *context_scim = ctx;
+
+ if (!IfInitContext)
+ _isf_wsc_context_init ();
+
+ if (context_scim == get_focused_ic ())
+ caps_mode_check (ctx, EINA_TRUE, EINA_TRUE);
+}
+
+void isf_wsc_context_input_panel_language_set (WSCContextISF *ctx, Ecore_IMF_Input_Panel_Lang language)
+{
+ WSCContextISF *context_scim = ctx;
+
+ if (!IfInitContext)
+ _isf_wsc_context_init ();
+ iseContext.language = language;
+
+ if (context_scim == get_focused_ic ()) {
+ LOGD ("language mode : %d\n", language);
+ _isf_wsc_context_input_panel_language_set (_get_context_id (ctx), language);
+ }
+}
+
+Ecore_IMF_Input_Panel_Lang isf_imf_context_input_panel_language_get (WSCContextISF *ctx)
+{
+ if (!IfInitContext)
+ _isf_wsc_context_init ();
+ return iseContext.language;
+}
+
--- /dev/null
+/*
+ * ISF(Input Service Framework)
+ *
+ * ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable.
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * Contact: Jihoon Kim <jihoon48.kim@samsung.com>, Haifeng Deng <haifeng.deng@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __ISF_IMF_CONTROL_UI_H
+#define __ISF_IMF_CONTROL_UI_H
+
+#include "isf_wsc_context.h"
+#include <Ecore_IMF.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+ int hw_keyboard_num_get ();
+ bool process_update_input_context (int type, int value);
+ void clear_hide_request ();
+
+ void isf_wsc_input_panel_init ();
+ void isf_wsc_input_panel_shutdown ();
+ void isf_wsc_context_input_panel_show (WSCContextISF *ctx);
+ void isf_wsc_context_input_panel_hide (WSCContextISF *ctx);
+ void isf_wsc_context_input_panel_language_set (WSCContextISF *ctx, Ecore_IMF_Input_Panel_Lang lang);
+ Ecore_IMF_Input_Panel_Lang isf_wsc_context_input_panel_language_get (WSCContextISF *ctx);
+ void isf_wsc_context_input_panel_layout_set (WSCContextISF *ctx, Ecore_IMF_Input_Panel_Layout layout);
+ Ecore_IMF_Input_Panel_Layout isf_wsc_context_input_panel_layout_get (WSCContextISF *ctx);
+ void isf_wsc_context_input_panel_caps_mode_set (WSCContextISF *ctx, unsigned int mode);
+ void isf_wsc_context_input_panel_caps_lock_mode_set (WSCContextISF *ctx, Eina_Bool mode);
+ void isf_wsc_context_set_hardware_keyboard_mode (WSCContextISF *ctx);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ISF_IMF_CONTROL_UI_H */
+
--- /dev/null
+/*
+ * ISF(Input Service Framework)
+ *
+ * ISF is based on SCIM 1.4.7 and extended for supporting more fitable.
+ * Copyright (c) 2012-2014 Intel Co., Ltd.
+ *
+ * Contact: Yan Wang <yan.wang@intel.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#define Uses_SCIM_CONFIG_PATH
+#define Uses_SCIM_HELPER_MODULE
+#define Uses_SCIM_PANEL_AGENT
+#define Uses_SCIM_COMPOSE_KEY
+#define Uses_SCIM_IMENGINE_MODULE
+
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <list>
+#include <glib.h>
+#include <Evas.h>
+#include <Ecore.h>
+#include <Ecore_Wayland.h>
+#include <Ecore_File.h>
+#include <malloc.h>
+#include "scim_private.h"
+#include "scim.h"
+#include "scim_stl_map.h"
+#if HAVE_VCONF
+#include <vconf.h>
+#include <vconf-keys.h>
+#endif
+#include <privilege-control.h>
+#include <dlog.h>
+
+#include <linux/input.h>
+#include <xkbcommon/xkbcommon.h>
+#include <sys/mman.h>
+#include "input-method-client-protocol.h"
+#include "text-client-protocol.h"
+#include "isf_wsc_context.h"
+#include "isf_wsc_control_ui.h"
+#include "scim_stl_map.h"
+
+using namespace scim;
+
+#if SCIM_USE_STL_EXT_HASH_MAP
+ typedef __gnu_cxx::hash_map <uint32_t, uint32_t, __gnu_cxx::hash <uint32_t> > KeycodeRepository;
+#elif SCIM_USE_STL_HASH_MAP
+ typedef std::hash_map <uint32_t, ClientInfo, std::hash <uint32_t> > KeycodeRepository;
+#else
+ typedef std::map <uint32_t, uint32_t> KeycodeRepository;
+#endif
+
+static KeycodeRepository _keysym2keycode;
+
+/////////////////////////////////////////////////////////////////////////////
+// Declaration of macro.
+/////////////////////////////////////////////////////////////////////////////
+#define LOG_TAG "ISF_WSC_EFL"
+
+/* This structure stores the wayland input method information */
+struct weescim;
+
+#define MOD_SHIFT_MASK 0x01
+#define MOD_ALT_MASK 0x02
+#define MOD_CONTROL_MASK 0x04
+
+typedef void (*keyboard_input_key_handler_t)(struct weescim *wsc,
+ uint32_t serial,
+ uint32_t time, uint32_t key, uint32_t unicode,
+ enum wl_keyboard_key_state state);
+
+struct weescim
+{
+ struct wl_input_method *im;
+ struct wl_input_method_context *im_ctx;
+ struct wl_seat *seat;
+ struct wl_keyboard *keyboard;
+
+ struct xkb_context *xkb_context;
+
+ uint32_t modifiers;
+
+ struct xkb_keymap *keymap;
+ struct xkb_state *state;
+ xkb_mod_mask_t control_mask;
+ xkb_mod_mask_t alt_mask;
+ xkb_mod_mask_t shift_mask;
+
+ keyboard_input_key_handler_t key_handler;
+
+ char *surrounding_text;
+ char *preedit_str;
+ char *language;
+
+ uint32_t serial;
+ uint32_t text_direction;
+ uint32_t preedit_style;
+ uint32_t content_hint;
+ uint32_t content_purpose;
+ uint32_t surrounding_cursor;
+
+ Eina_Bool context_changed;
+ Eina_Bool hw_kbd;
+
+ WSCContextISF *wsc_ctx;
+};
+static struct weescim _wsc = {0};
+
+static char *
+append(char *s1, const char *s2)
+{
+ int len1, len2;
+ char *s;
+
+ len1 = strlen(s1);
+ len2 = strlen(s2);
+ s = (char*)realloc(s1, len1 + len2 + 1);
+ memcpy(s + len1, s2, len2);
+ s[len1 + len2] = '\0';
+
+ return s;
+}
+
+static char *
+insert_text(const char *text, uint32_t offset, const char *insert)
+{
+ int tlen = strlen(text), ilen = strlen(insert);
+ char *new_text = (char*)malloc(tlen + ilen + 1);
+
+ memcpy(new_text, text, offset);
+ memcpy(new_text + offset, insert, ilen);
+ memcpy(new_text + offset + ilen, text + offset, tlen - offset);
+ new_text[tlen + ilen] = '\0';
+
+ return new_text;
+}
+
+static void
+wsc_commit_preedit(weescim *ctx)
+{
+ char *surrounding_text;
+
+ if (!ctx->preedit_str ||
+ strlen(ctx->preedit_str) == 0)
+ return;
+
+ wl_input_method_context_cursor_position(ctx->im_ctx,
+ 0, 0);
+ wl_input_method_context_commit_string(ctx->im_ctx,
+ ctx->serial,
+ ctx->preedit_str);
+
+ if (ctx->surrounding_text) {
+ surrounding_text = insert_text(ctx->surrounding_text,
+ ctx->surrounding_cursor,
+ ctx->preedit_str);
+ free(ctx->surrounding_text);
+ ctx->surrounding_text = surrounding_text;
+ ctx->surrounding_cursor += strlen(ctx->preedit_str);
+ } else {
+ ctx->surrounding_text = strdup(ctx->preedit_str);
+ ctx->surrounding_cursor = strlen(ctx->preedit_str);
+ }
+
+ free(ctx->preedit_str);
+ ctx->preedit_str = strdup("");
+}
+
+static void
+wsc_send_preedit(weescim *ctx, int32_t cursor)
+{
+ uint32_t index = strlen(ctx->preedit_str);
+
+ if (ctx->preedit_style)
+ wl_input_method_context_preedit_styling(ctx->im_ctx,
+ 0,
+ strlen(ctx->preedit_str),
+ ctx->preedit_style);
+ if (cursor > 0)
+ index = cursor;
+ wl_input_method_context_preedit_cursor(ctx->im_ctx, index);
+ wl_input_method_context_preedit_string(ctx->im_ctx,
+ ctx->serial,
+ ctx->preedit_str,
+ ctx->preedit_str);
+}
+
+bool wsc_context_surrounding_get(weescim *ctx, char **text, int *cursor_pos)
+{
+ if (!ctx)
+ return false;
+
+ *text = strdup (ctx->surrounding_text);
+ *cursor_pos = ctx->surrounding_cursor;
+ return true;
+}
+
+Ecore_IMF_Input_Panel_Layout wsc_context_input_panel_layout_get(weescim *ctx)
+{
+ Ecore_IMF_Input_Panel_Layout layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
+
+ switch (ctx->content_purpose) {
+ case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
+ case WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER:
+ case WL_TEXT_INPUT_CONTENT_PURPOSE_DATE:
+ case WL_TEXT_INPUT_CONTENT_PURPOSE_TIME:
+ case WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME:
+ layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER;
+ break;
+ case WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE:
+ layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER;
+ break;
+ case WL_TEXT_INPUT_CONTENT_PURPOSE_URL:
+ layout = ECORE_IMF_INPUT_PANEL_LAYOUT_URL;
+ break;
+ case WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL:
+ layout = ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL;
+ break;
+ case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD:
+ layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD;
+ break;
+ default:
+ layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
+ break;
+ }
+
+ return layout;
+}
+
+bool wsc_context_input_panel_caps_lock_mode_get(weescim *ctx)
+{
+ if (ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE)
+ return true;
+
+ return false;
+}
+
+void wsc_context_delete_surrounding (weescim *ctx, int offset, int len)
+{
+ if (!ctx)
+ return;
+
+ wl_input_method_context_delete_surrounding_text(ctx->im_ctx, offset, len);
+}
+
+void wsc_context_commit_string(weescim *ctx, const char *str)
+{
+ if (ctx->preedit_str) {
+ free(ctx->preedit_str);
+ ctx->preedit_str = NULL;
+ }
+
+ ctx->preedit_str = strdup (str);
+ wsc_commit_preedit(ctx);
+}
+
+void wsc_context_commit_preedit_string(weescim *ctx)
+{
+ char *preedit_str = NULL;
+ int cursor_pos = 0;
+
+ isf_wsc_context_preedit_string_get(ctx->wsc_ctx, &preedit_str, &cursor_pos);
+ if (ctx->preedit_str) {
+ free(ctx->preedit_str);
+ ctx->preedit_str = NULL;
+ }
+
+ ctx->preedit_str = preedit_str;
+ wsc_commit_preedit(ctx);
+}
+
+void wsc_context_send_preedit_string(weescim *ctx)
+{
+ char *preedit_str = NULL;
+ int cursor_pos = 0;
+
+ isf_wsc_context_preedit_string_get(ctx->wsc_ctx, &preedit_str, &cursor_pos);
+ if (ctx->preedit_str) {
+ free(ctx->preedit_str);
+ ctx->preedit_str = NULL;
+ }
+
+ ctx->preedit_str = preedit_str;
+ wsc_send_preedit(ctx, cursor_pos);
+}
+
+void wsc_context_send_key(weescim *ctx, uint32_t keysym, uint32_t modifiers, uint32_t time, bool press)
+{
+ uint32_t keycode;
+ KeycodeRepository::iterator it = _keysym2keycode.find(keysym);
+
+ if(it == _keysym2keycode.end())
+ return;
+
+ keycode = it->second;
+ ctx->modifiers = modifiers;
+
+ if (press) {
+ if (ctx->modifiers) {
+ wl_input_method_context_modifiers(ctx->im_ctx, ctx->serial,
+ ctx->modifiers, 0, 0, 0);
+ }
+
+ wl_input_method_context_key(ctx->im_ctx, ctx->serial, time,
+ keycode, WL_KEYBOARD_KEY_STATE_PRESSED);
+ }
+ else {
+ wl_input_method_context_key(ctx->im_ctx, ctx->serial, time,
+ keycode, WL_KEYBOARD_KEY_STATE_RELEASED);
+
+ if (ctx->modifiers) {
+ wl_input_method_context_modifiers(ctx->im_ctx, ctx->serial,
+ 0, 0, 0, 0);
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Implementation of Wayland Input Method functions.
+/////////////////////////////////////////////////////////////////////////////
+static void
+_wsc_im_ctx_surrounding_text(void *data, struct wl_input_method_context *im_ctx, const char *text, uint32_t cursor, uint32_t anchor)
+{
+ struct weescim *wsc = (weescim*)data;
+
+ free (wsc->surrounding_text);
+ wsc->surrounding_text = strdup (text);
+ wsc->surrounding_cursor = cursor;
+}
+
+static void
+_wsc_im_ctx_reset(void *data, struct wl_input_method_context *im_ctx)
+{
+ struct weescim *wsc = (weescim*)data;
+
+ isf_wsc_context_reset(wsc->wsc_ctx);
+}
+
+static void
+_wsc_im_ctx_content_type(void *data, struct wl_input_method_context *im_ctx, uint32_t hint, uint32_t purpose)
+{
+ struct weescim *wsc = (weescim*)data;
+ Ecore_IMF_Input_Panel_Layout layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
+
+ ISF_LOG ("im_context = %p hint = %d purpose = %d", im_ctx, hint, purpose);
+
+ if (!wsc->context_changed)
+ return;
+
+ wsc->content_hint = hint;
+ wsc->content_purpose = purpose;
+
+ isf_wsc_context_input_panel_layout_set (wsc->wsc_ctx,
+ wsc_context_input_panel_layout_get (wsc));
+
+ caps_mode_check(wsc->wsc_ctx, EINA_TRUE, EINA_TRUE);
+
+ //FIXME: process hint like layout.
+
+ wsc->context_changed = EINA_FALSE;
+}
+
+static void
+_wsc_im_ctx_invoke_action(void *data, struct wl_input_method_context *im_ctx, uint32_t button, uint32_t index)
+{
+ struct weescim *wsc = (weescim*)data;
+
+ if (button != BTN_LEFT)
+ return;
+
+ wsc_context_send_preedit_string (wsc);
+}
+
+static void
+_wsc_im_ctx_commit_state(void *data, struct wl_input_method_context *im_ctx, uint32_t serial)
+{
+ struct weescim *wsc = (weescim*)data;
+
+ wsc->serial = serial;
+
+ if (wsc->surrounding_text)
+ ISF_LOG ("Surrounding text updated: %s", wsc->surrounding_text);
+
+ if(wsc->language)
+ wl_input_method_context_language (im_ctx, wsc->serial, wsc->language);
+
+ wl_input_method_context_text_direction (im_ctx, wsc->serial, wsc->text_direction);
+}
+
+static void
+_wsc_im_ctx_preferred_language(void *data, struct wl_input_method_context *im_ctx, const char *language)
+{
+ struct weescim *wsc = (weescim*)data;
+
+ if (language && wsc->language && !strcmp (language, wsc->language))
+ return;
+
+ if (wsc->language) {
+ free (wsc->language);
+ wsc->language = NULL;
+ }
+
+ if (language) {
+ wsc->language = strdup (language);
+ ISF_LOG ("Language changed, new: '%s'", language);
+ }
+}
+
+static const struct wl_input_method_context_listener wsc_im_context_listener = {
+ _wsc_im_ctx_surrounding_text,
+ _wsc_im_ctx_reset,
+ _wsc_im_ctx_content_type,
+ _wsc_im_ctx_invoke_action,
+ _wsc_im_ctx_commit_state,
+ _wsc_im_ctx_preferred_language,
+};
+
+static void
+_init_keysym2keycode(struct weescim *wsc)
+{
+ uint32_t i = 0;
+ uint32_t code;
+ uint32_t num_syms;
+ const xkb_keysym_t *syms;
+
+ if (!wsc->state)
+ return;
+
+ for (i = 0; i < 256; i++) {
+ code = i + 8;
+ num_syms = xkb_key_get_syms(wsc->state, code, &syms);
+
+ if (num_syms == 1)
+ _keysym2keycode[syms[0]] = i;
+ }
+}
+
+static void
+_fini_keysym2keycode(struct weescim *wsc)
+{
+ _keysym2keycode.clear();
+}
+
+static void
+_wsc_im_keyboard_keymap(void *data,
+ struct wl_keyboard *wl_keyboard,
+ uint32_t format,
+ int32_t fd,
+ uint32_t size)
+{
+ struct weescim *wsc = (weescim*)data;
+ char *map_str;
+
+ _fini_keysym2keycode(wsc);
+
+ if (wsc->state) {
+ xkb_state_unref(wsc->state);
+ wsc->state = NULL;
+ }
+
+ if (wsc->keymap) {
+ xkb_map_unref(wsc->keymap);
+ wsc->keymap = NULL;
+ }
+
+ if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
+ close(fd);
+ return;
+ }
+
+ map_str = (char*)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+ if (map_str == MAP_FAILED) {
+ close(fd);
+ return;
+ }
+
+ wsc->keymap =
+ xkb_map_new_from_string(wsc->xkb_context,
+ map_str,
+ XKB_KEYMAP_FORMAT_TEXT_V1,
+ (xkb_keymap_compile_flags)0);
+
+ munmap(map_str, size);
+ close(fd);
+
+ if (!wsc->keymap) {
+ fprintf(stderr, "failed to compile keymap\n");
+ return;
+ }
+
+ wsc->state = xkb_state_new(wsc->keymap);
+ if (!wsc->state) {
+ fprintf(stderr, "failed to create XKB state\n");
+ xkb_map_unref(wsc->keymap);
+ return;
+ }
+
+ wsc->control_mask =
+ 1 << xkb_map_mod_get_index(wsc->keymap, "Control");
+ wsc->alt_mask =
+ 1 << xkb_map_mod_get_index(wsc->keymap, "Mod1");
+ wsc->shift_mask =
+ 1 << xkb_map_mod_get_index(wsc->keymap, "Shift");
+
+ fprintf(stderr, "create _keysym2keycode\n");
+ _init_keysym2keycode(wsc);
+}
+
+static void
+_wsc_im_keyboard_key(void *data,
+ struct wl_keyboard *wl_keyboard,
+ uint32_t serial,
+ uint32_t time,
+ uint32_t key,
+ uint32_t state_w)
+{
+ struct weescim *wsc = (weescim*)data;
+ uint32_t code;
+ uint32_t num_syms;
+ const xkb_keysym_t *syms;
+ xkb_keysym_t sym;
+ enum wl_keyboard_key_state state = (wl_keyboard_key_state)state_w;
+
+ if (!wsc->state)
+ return;
+
+ code = key + 8;
+ num_syms = xkb_key_get_syms(wsc->state, code, &syms);
+
+ sym = XKB_KEY_NoSymbol;
+ if (num_syms == 1)
+ sym = syms[0];
+
+ if (wsc->key_handler)
+ (*wsc->key_handler)(wsc, serial, time, key, sym,
+ state);
+}
+
+static void
+_wsc_im_keyboard_modifiers(void *data,
+ struct wl_keyboard *wl_keyboard,
+ uint32_t serial,
+ uint32_t mods_depressed,
+ uint32_t mods_latched,
+ uint32_t mods_locked,
+ uint32_t group)
+{
+ struct weescim *wsc = (weescim*)data;
+ struct wl_input_method_context *context = wsc->im_ctx;
+ xkb_mod_mask_t mask;
+
+ if (!wsc->state)
+ return;
+
+ xkb_state_update_mask(wsc->state, mods_depressed,
+ mods_latched, mods_locked, 0, 0, group);
+ mask = xkb_state_serialize_mods(wsc->state,
+ (xkb_state_component)(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED));
+
+ wsc->modifiers = 0;
+ if (mask & wsc->control_mask)
+ wsc->modifiers |= MOD_CONTROL_MASK;
+ if (mask & wsc->alt_mask)
+ wsc->modifiers |= MOD_ALT_MASK;
+ if (mask & wsc->shift_mask)
+ wsc->modifiers |= MOD_SHIFT_MASK;
+
+ wl_input_method_context_modifiers(context, serial,
+ mods_depressed, mods_depressed,
+ mods_latched, group);
+}
+
+static const struct wl_keyboard_listener wsc_im_keyboard_listener = {
+ _wsc_im_keyboard_keymap,
+ NULL, /* enter */
+ NULL, /* leave */
+ _wsc_im_keyboard_key,
+ _wsc_im_keyboard_modifiers
+};
+
+static void
+_wsc_im_activate(void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx)
+{
+ struct weescim *wsc = (weescim*)data;
+
+ if (wsc->im_ctx)
+ wl_input_method_context_destroy (wsc->im_ctx);
+
+ if (wsc->preedit_str)
+ free (wsc->preedit_str);
+
+ wsc->preedit_str = strdup ("");
+ wsc->content_hint = WL_TEXT_INPUT_CONTENT_HINT_NONE;
+ wsc->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
+
+ free (wsc->language);
+ wsc->language = NULL;
+
+ free (wsc->surrounding_text);
+ wsc->surrounding_text = NULL;
+
+ wsc->im_ctx = im_ctx;
+ wl_input_method_context_add_listener (im_ctx, &wsc_im_context_listener, wsc);
+
+ wsc->keyboard = wl_input_method_context_grab_keyboard(im_ctx);
+ wl_keyboard_add_listener(wsc->keyboard, &wsc_im_keyboard_listener, wsc);
+
+ wsc->context_changed = EINA_TRUE;
+ isf_wsc_context_focus_in (wsc->wsc_ctx);
+ isf_wsc_context_input_panel_show (wsc->wsc_ctx);
+}
+
+static void
+_wsc_im_deactivate(void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx)
+{
+ struct weescim *wsc = (weescim*)data;
+
+ isf_wsc_context_input_panel_hide (wsc->wsc_ctx);
+ isf_wsc_context_focus_out (wsc->wsc_ctx);
+
+ if (wsc->im_ctx) {
+ wl_input_method_context_destroy(wsc->im_ctx);
+ wsc->im_ctx = NULL;
+ }
+}
+
+static const struct wl_input_method_listener wsc_im_listener = {
+ _wsc_im_activate,
+ _wsc_im_deactivate
+};
+
+static void
+_wsc_seat_handle_capabilities(void *data, struct wl_seat *seat,
+ uint32_t caps)
+{
+ struct weescim *wsc = (weescim*)data;
+
+ if ((caps & WL_SEAT_CAPABILITY_KEYBOARD)) {
+ wsc->hw_kbd = true;
+ } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD)) {
+ wsc->hw_kbd = false;
+ }
+}
+
+static const struct wl_seat_listener wsc_seat_listener = {
+ _wsc_seat_handle_capabilities,
+};
+
+static void
+_wsc_im_key_handler(struct weescim *wsc,
+ uint32_t serial, uint32_t time, uint32_t key, uint32_t sym,
+ enum wl_keyboard_key_state state)
+{
+}
+
+static void
+_wsc_setup(struct weescim *wsc)
+{
+ struct wl_list *globals;
+ struct wl_registry *registry;
+ Ecore_Wl_Global *global;
+
+ wsc->xkb_context = xkb_context_new((xkb_context_flags)0);
+ if (wsc->xkb_context == NULL) {
+ fprintf(stderr, "Failed to create XKB context\n");
+ return;
+ }
+
+ wsc->key_handler = _wsc_im_key_handler;
+
+ wsc->wsc_ctx = isf_wsc_context_new ();
+ wsc->wsc_ctx->ctx = wsc;
+
+ get_language(&wsc->language);
+
+ if (!(registry = ecore_wl_registry_get()))
+ return;
+
+ if (!(globals = (wl_list*)ecore_wl_globals_get()))
+ return;
+
+ EINA_INLIST_FOREACH(globals, global) {
+ if (strcmp (global->interface, "wl_input_method") == 0)
+ wsc->im = (wl_input_method*)wl_registry_bind (registry, global->id, &wl_input_method_interface, 1);
+ else if (strcmp (global->interface, "wl_seat") == 0)
+ wsc->seat = (wl_seat*)wl_registry_bind (registry, global->id, &wl_seat_interface, 1);
+ }
+
+ /* Input method listener */
+ ISF_LOG ("Adding wl_input_method listener");
+ wl_input_method_add_listener (wsc->im, &wsc_im_listener, wsc);
+
+ wl_seat_add_listener(wsc->seat, &wsc_seat_listener, wsc);
+
+ isf_wsc_context_add (wsc->wsc_ctx);
+}
+
+static void
+_wsc_free(struct weescim *wsc)
+{
+ _fini_keysym2keycode(wsc);
+
+ if (wsc->state) {
+ xkb_state_unref(wsc->state);
+ wsc->state = NULL;
+ }
+
+ if (wsc->keymap) {
+ xkb_map_unref(wsc->keymap);
+ wsc->keymap = NULL;
+ }
+
+ if (wsc->im_ctx)
+ wl_input_method_context_destroy (wsc->im_ctx);
+
+ isf_wsc_context_del(wsc->wsc_ctx);
+ isf_wsc_context_shutdown ();
+
+ free (wsc->preedit_str);
+ free (wsc->surrounding_text);
+}
+
+int main (int argc EINA_UNUSED, char **argv EINA_UNUSED)
+{
+ sleep(1);
+
+ _wsc_setup(&_wsc);
+
+ ecore_main_loop_begin();
+
+ _wsc_free(&_wsc);
+
+ return 0;
+}
+
+/*
+vi:ts=4:nowrap:expandtab
+*/
--- /dev/null
+/*
+ * 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.
+ */
+
+#ifndef TEXT_CLIENT_PROTOCOL_H
+#define TEXT_CLIENT_PROTOCOL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+#include "wayland-client.h"
+
+struct wl_client;
+struct wl_resource;
+
+struct wl_text_input;
+struct wl_text_input_manager;
+
+extern const struct wl_interface wl_text_input_interface;
+extern const struct wl_interface wl_text_input_manager_interface;
+
+#ifndef WL_TEXT_INPUT_CONTENT_HINT_ENUM
+#define WL_TEXT_INPUT_CONTENT_HINT_ENUM
+/**
+ * wl_text_input_content_hint - content hint
+ * @WL_TEXT_INPUT_CONTENT_HINT_NONE: no special behaviour
+ * @WL_TEXT_INPUT_CONTENT_HINT_DEFAULT: auto completion, correction and
+ * capitalization
+ * @WL_TEXT_INPUT_CONTENT_HINT_PASSWORD: hidden and sensitive text
+ * @WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION: suggest word completions
+ * @WL_TEXT_INPUT_CONTENT_HINT_AUTO_CORRECTION: suggest word corrections
+ * @WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION: switch to uppercase
+ * letters at the start of a sentence
+ * @WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE: prefer lowercase letters
+ * @WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE: prefer uppercase letters
+ * @WL_TEXT_INPUT_CONTENT_HINT_TITLECASE: prefer casing for titles and
+ * headings (can be language dependent)
+ * @WL_TEXT_INPUT_CONTENT_HINT_HIDDEN_TEXT: characters should be hidden
+ * @WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA: typed text should not be
+ * stored
+ * @WL_TEXT_INPUT_CONTENT_HINT_LATIN: just latin characters should be
+ * entered
+ * @WL_TEXT_INPUT_CONTENT_HINT_MULTILINE: the text input is multiline
+ *
+ * Content hint is a bitmask to allow to modify the behavior of the text
+ * input.
+ */
+enum wl_text_input_content_hint {
+ WL_TEXT_INPUT_CONTENT_HINT_NONE = 0x0,
+ WL_TEXT_INPUT_CONTENT_HINT_DEFAULT = 0x7,
+ WL_TEXT_INPUT_CONTENT_HINT_PASSWORD = 0xc0,
+ WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION = 0x1,
+ WL_TEXT_INPUT_CONTENT_HINT_AUTO_CORRECTION = 0x2,
+ WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION = 0x4,
+ WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE = 0x8,
+ WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE = 0x10,
+ WL_TEXT_INPUT_CONTENT_HINT_TITLECASE = 0x20,
+ WL_TEXT_INPUT_CONTENT_HINT_HIDDEN_TEXT = 0x40,
+ WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA = 0x80,
+ WL_TEXT_INPUT_CONTENT_HINT_LATIN = 0x100,
+ WL_TEXT_INPUT_CONTENT_HINT_MULTILINE = 0x200,
+};
+#endif /* WL_TEXT_INPUT_CONTENT_HINT_ENUM */
+
+#ifndef WL_TEXT_INPUT_CONTENT_PURPOSE_ENUM
+#define WL_TEXT_INPUT_CONTENT_PURPOSE_ENUM
+/**
+ * wl_text_input_content_purpose - content purpose
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL: default input, allowing all
+ * characters
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_ALPHA: allow only alphabetic characters
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS: allow only digits
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER: input a number (including
+ * decimal separator and sign)
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE: input a phone number
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_URL: input an URL
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL: input an email address
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_NAME: input a name of a person
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD: input a password (combine
+ * with password or sensitive_data hint)
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_DATE: input a date
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_TIME: input a time
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME: input a date and time
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL: input for a terminal
+ *
+ * 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.
+ */
+enum wl_text_input_content_purpose {
+ WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL = 0,
+ WL_TEXT_INPUT_CONTENT_PURPOSE_ALPHA = 1,
+ WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS = 2,
+ WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER = 3,
+ WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE = 4,
+ WL_TEXT_INPUT_CONTENT_PURPOSE_URL = 5,
+ WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL = 6,
+ WL_TEXT_INPUT_CONTENT_PURPOSE_NAME = 7,
+ WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD = 8,
+ WL_TEXT_INPUT_CONTENT_PURPOSE_DATE = 9,
+ WL_TEXT_INPUT_CONTENT_PURPOSE_TIME = 10,
+ WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME = 11,
+ WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL = 12,
+};
+#endif /* WL_TEXT_INPUT_CONTENT_PURPOSE_ENUM */
+
+#ifndef WL_TEXT_INPUT_PREEDIT_STYLE_ENUM
+#define WL_TEXT_INPUT_PREEDIT_STYLE_ENUM
+enum wl_text_input_preedit_style {
+ WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT = 0,
+ WL_TEXT_INPUT_PREEDIT_STYLE_NONE = 1,
+ WL_TEXT_INPUT_PREEDIT_STYLE_ACTIVE = 2,
+ WL_TEXT_INPUT_PREEDIT_STYLE_INACTIVE = 3,
+ WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT = 4,
+ WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE = 5,
+ WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION = 6,
+ WL_TEXT_INPUT_PREEDIT_STYLE_INCORRECT = 7,
+};
+#endif /* WL_TEXT_INPUT_PREEDIT_STYLE_ENUM */
+
+#ifndef WL_TEXT_INPUT_TEXT_DIRECTION_ENUM
+#define WL_TEXT_INPUT_TEXT_DIRECTION_ENUM
+enum wl_text_input_text_direction {
+ WL_TEXT_INPUT_TEXT_DIRECTION_AUTO = 0,
+ WL_TEXT_INPUT_TEXT_DIRECTION_LTR = 1,
+ WL_TEXT_INPUT_TEXT_DIRECTION_RTL = 2,
+};
+#endif /* WL_TEXT_INPUT_TEXT_DIRECTION_ENUM */
+
+/**
+ * wl_text_input - text input
+ * @enter: enter event
+ * @leave: leave event
+ * @modifiers_map: modifiers map
+ * @input_panel_state: state of the input panel
+ * @preedit_string: pre-edit
+ * @preedit_styling: pre-edit styling
+ * @preedit_cursor: pre-edit cursor
+ * @commit_string: commit
+ * @cursor_position: set cursor to new position
+ * @delete_surrounding_text: delete surrounding text
+ * @keysym: keysym
+ * @language: language
+ * @text_direction: text direction
+ *
+ * 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).
+ */
+struct wl_text_input_listener {
+ /**
+ * enter - enter event
+ * @surface: (none)
+ *
+ * Notify the text-input object when it received focus. Typically
+ * in response to an activate request.
+ */
+ void (*enter)(void *data,
+ struct wl_text_input *wl_text_input,
+ struct wl_surface *surface);
+ /**
+ * leave - 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.
+ */
+ void (*leave)(void *data,
+ struct wl_text_input *wl_text_input);
+ /**
+ * modifiers_map - modifiers map
+ * @map: (none)
+ *
+ * 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.
+ */
+ void (*modifiers_map)(void *data,
+ struct wl_text_input *wl_text_input,
+ struct wl_array *map);
+ /**
+ * input_panel_state - state of the input panel
+ * @state: (none)
+ *
+ * Notify when the visibility state of the input panel changed.
+ */
+ void (*input_panel_state)(void *data,
+ struct wl_text_input *wl_text_input,
+ uint32_t state);
+ /**
+ * preedit_string - pre-edit
+ * @serial: serial of the latest known text input state
+ * @text: (none)
+ * @commit: (none)
+ *
+ * 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.
+ */
+ void (*preedit_string)(void *data,
+ struct wl_text_input *wl_text_input,
+ uint32_t serial,
+ const char *text,
+ const char *commit);
+ /**
+ * preedit_styling - pre-edit styling
+ * @index: (none)
+ * @length: (none)
+ * @style: (none)
+ *
+ * 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.
+ */
+ void (*preedit_styling)(void *data,
+ struct wl_text_input *wl_text_input,
+ uint32_t index,
+ uint32_t length,
+ uint32_t style);
+ /**
+ * preedit_cursor - pre-edit cursor
+ * @index: (none)
+ *
+ * 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.
+ */
+ void (*preedit_cursor)(void *data,
+ struct wl_text_input *wl_text_input,
+ int32_t index);
+ /**
+ * commit_string - commit
+ * @serial: serial of the latest known text input state
+ * @text: (none)
+ *
+ * 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.
+ */
+ void (*commit_string)(void *data,
+ struct wl_text_input *wl_text_input,
+ uint32_t serial,
+ const char *text);
+ /**
+ * cursor_position - set cursor to new position
+ * @index: (none)
+ * @anchor: (none)
+ *
+ * Notify when the cursor or anchor position should be modified.
+ *
+ * This event should be handled as part of a following
+ * commit_string event.
+ */
+ void (*cursor_position)(void *data,
+ struct wl_text_input *wl_text_input,
+ int32_t index,
+ int32_t anchor);
+ /**
+ * delete_surrounding_text - delete surrounding text
+ * @index: (none)
+ * @length: (none)
+ *
+ * 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.
+ */
+ void (*delete_surrounding_text)(void *data,
+ struct wl_text_input *wl_text_input,
+ int32_t index,
+ uint32_t length);
+ /**
+ * keysym - keysym
+ * @serial: serial of the latest known text input state
+ * @time: (none)
+ * @sym: (none)
+ * @state: (none)
+ * @modifiers: (none)
+ *
+ * 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)
+ */
+ void (*keysym)(void *data,
+ struct wl_text_input *wl_text_input,
+ uint32_t serial,
+ uint32_t time,
+ uint32_t sym,
+ uint32_t state,
+ uint32_t modifiers);
+ /**
+ * language - language
+ * @serial: serial of the latest known text input state
+ * @language: (none)
+ *
+ * Sets the language of the input text. The "language" argument
+ * is a RFC-3066 format language tag.
+ */
+ void (*language)(void *data,
+ struct wl_text_input *wl_text_input,
+ uint32_t serial,
+ const char *language);
+ /**
+ * text_direction - text direction
+ * @serial: serial of the latest known text input state
+ * @direction: (none)
+ *
+ * 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.
+ */
+ void (*text_direction)(void *data,
+ struct wl_text_input *wl_text_input,
+ uint32_t serial,
+ uint32_t direction);
+};
+
+static inline int
+wl_text_input_add_listener(struct wl_text_input *wl_text_input,
+ const struct wl_text_input_listener *listener, void *data)
+{
+ return wl_proxy_add_listener((struct wl_proxy *) wl_text_input,
+ (void (**)(void)) listener, data);
+}
+
+#define WL_TEXT_INPUT_ACTIVATE 0
+#define WL_TEXT_INPUT_DEACTIVATE 1
+#define WL_TEXT_INPUT_SHOW_INPUT_PANEL 2
+#define WL_TEXT_INPUT_HIDE_INPUT_PANEL 3
+#define WL_TEXT_INPUT_RESET 4
+#define WL_TEXT_INPUT_SET_SURROUNDING_TEXT 5
+#define WL_TEXT_INPUT_SET_CONTENT_TYPE 6
+#define WL_TEXT_INPUT_SET_CURSOR_RECTANGLE 7
+#define WL_TEXT_INPUT_SET_PREFERRED_LANGUAGE 8
+#define WL_TEXT_INPUT_COMMIT_STATE 9
+#define WL_TEXT_INPUT_INVOKE_ACTION 10
+
+static inline void
+wl_text_input_set_user_data(struct wl_text_input *wl_text_input, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) wl_text_input, user_data);
+}
+
+static inline void *
+wl_text_input_get_user_data(struct wl_text_input *wl_text_input)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) wl_text_input);
+}
+
+static inline void
+wl_text_input_destroy(struct wl_text_input *wl_text_input)
+{
+ wl_proxy_destroy((struct wl_proxy *) wl_text_input);
+}
+
+static inline void
+wl_text_input_activate(struct wl_text_input *wl_text_input, struct wl_seat *seat, struct wl_surface *surface)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+ WL_TEXT_INPUT_ACTIVATE, seat, surface);
+}
+
+static inline void
+wl_text_input_deactivate(struct wl_text_input *wl_text_input, struct wl_seat *seat)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+ WL_TEXT_INPUT_DEACTIVATE, seat);
+}
+
+static inline void
+wl_text_input_show_input_panel(struct wl_text_input *wl_text_input)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+ WL_TEXT_INPUT_SHOW_INPUT_PANEL);
+}
+
+static inline void
+wl_text_input_hide_input_panel(struct wl_text_input *wl_text_input)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+ WL_TEXT_INPUT_HIDE_INPUT_PANEL);
+}
+
+static inline void
+wl_text_input_reset(struct wl_text_input *wl_text_input)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+ WL_TEXT_INPUT_RESET);
+}
+
+static inline void
+wl_text_input_set_surrounding_text(struct wl_text_input *wl_text_input, const char *text, uint32_t cursor, uint32_t anchor)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+ WL_TEXT_INPUT_SET_SURROUNDING_TEXT, text, cursor, anchor);
+}
+
+static inline void
+wl_text_input_set_content_type(struct wl_text_input *wl_text_input, uint32_t hint, uint32_t purpose)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+ WL_TEXT_INPUT_SET_CONTENT_TYPE, hint, purpose);
+}
+
+static inline void
+wl_text_input_set_cursor_rectangle(struct wl_text_input *wl_text_input, int32_t x, int32_t y, int32_t width, int32_t height)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+ WL_TEXT_INPUT_SET_CURSOR_RECTANGLE, x, y, width, height);
+}
+
+static inline void
+wl_text_input_set_preferred_language(struct wl_text_input *wl_text_input, const char *language)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+ WL_TEXT_INPUT_SET_PREFERRED_LANGUAGE, language);
+}
+
+static inline void
+wl_text_input_commit_state(struct wl_text_input *wl_text_input, uint32_t serial)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+ WL_TEXT_INPUT_COMMIT_STATE, serial);
+}
+
+static inline void
+wl_text_input_invoke_action(struct wl_text_input *wl_text_input, uint32_t button, uint32_t index)
+{
+ wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+ WL_TEXT_INPUT_INVOKE_ACTION, button, index);
+}
+
+#define WL_TEXT_INPUT_MANAGER_CREATE_TEXT_INPUT 0
+
+static inline void
+wl_text_input_manager_set_user_data(struct wl_text_input_manager *wl_text_input_manager, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) wl_text_input_manager, user_data);
+}
+
+static inline void *
+wl_text_input_manager_get_user_data(struct wl_text_input_manager *wl_text_input_manager)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) wl_text_input_manager);
+}
+
+static inline void
+wl_text_input_manager_destroy(struct wl_text_input_manager *wl_text_input_manager)
+{
+ wl_proxy_destroy((struct wl_proxy *) wl_text_input_manager);
+}
+
+static inline struct wl_text_input *
+wl_text_input_manager_create_text_input(struct wl_text_input_manager *wl_text_input_manager)
+{
+ struct wl_proxy *id;
+
+ id = wl_proxy_create((struct wl_proxy *) wl_text_input_manager,
+ &wl_text_input_interface);
+ if (!id)
+ return NULL;
+
+ wl_proxy_marshal((struct wl_proxy *) wl_text_input_manager,
+ WL_TEXT_INPUT_MANAGER_CREATE_TEXT_INPUT, id);
+
+ return (struct wl_text_input *) id;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include "wayland-util.h"
+
+extern const struct wl_interface wl_seat_interface;
+extern const struct wl_interface wl_surface_interface;
+extern const struct wl_interface wl_seat_interface;
+extern const struct wl_interface wl_surface_interface;
+extern const struct wl_interface wl_text_input_interface;
+
+static const struct wl_interface *types[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &wl_seat_interface,
+ &wl_surface_interface,
+ &wl_seat_interface,
+ &wl_surface_interface,
+ &wl_text_input_interface,
+};
+
+static const struct wl_message wl_text_input_requests[] = {
+ { "activate", "oo", types + 5 },
+ { "deactivate", "o", types + 7 },
+ { "show_input_panel", "", types + 0 },
+ { "hide_input_panel", "", types + 0 },
+ { "reset", "", types + 0 },
+ { "set_surrounding_text", "suu", types + 0 },
+ { "set_content_type", "uu", types + 0 },
+ { "set_cursor_rectangle", "iiii", types + 0 },
+ { "set_preferred_language", "s", types + 0 },
+ { "commit_state", "u", types + 0 },
+ { "invoke_action", "uu", types + 0 },
+};
+
+static const struct wl_message wl_text_input_events[] = {
+ { "enter", "o", types + 8 },
+ { "leave", "", types + 0 },
+ { "modifiers_map", "a", types + 0 },
+ { "input_panel_state", "u", types + 0 },
+ { "preedit_string", "uss", types + 0 },
+ { "preedit_styling", "uuu", types + 0 },
+ { "preedit_cursor", "i", types + 0 },
+ { "commit_string", "us", types + 0 },
+ { "cursor_position", "ii", types + 0 },
+ { "delete_surrounding_text", "iu", types + 0 },
+ { "keysym", "uuuuu", types + 0 },
+ { "language", "us", types + 0 },
+ { "text_direction", "uu", types + 0 },
+};
+
+WL_EXPORT const struct wl_interface wl_text_input_interface = {
+ "wl_text_input", 1,
+ 11, wl_text_input_requests,
+ 13, wl_text_input_events,
+};
+
+static const struct wl_message wl_text_input_manager_requests[] = {
+ { "create_text_input", "n", types + 9 },
+};
+
+WL_EXPORT const struct wl_interface wl_text_input_manager_interface = {
+ "wl_text_input_manager", 1,
+ 1, wl_text_input_manager_requests,
+ 0, NULL,
+};
+
--- /dev/null
+MAINTAINERCLEANFILES = Makefile.in
+CLEANFILES = *.bak *.edj
+
+INCLUDES = -I$(top_builddir) \
+ -I$(top_builddir)/ism/src \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/ism/src \
+ -I$(top_srcdir)/ism/intl \
+ -I$(top_srcdir)/ism/data \
+ -I$(top_srcdir)/ism/utils \
+ -I$(includedir) \
+ -DSCIM_DATADIR=\"@SCIM_DATADIR@\" \
+ -DSCIM_LOCALEDIR=\"@SCIM_LOCALEDIR@\" \
+ -DSCIM_SYSCONFDIR=\"@SCIM_SYSCONFDIR@\" \
+ -DSCIM_LIBEXECDIR=\"@SCIM_LIBEXECDIR@\" \
+ -DSCIM_ICONDIR=\"@SCIM_ICONDIR@\" \
+ -DSCIM_MODULE_PATH=\"@SCIM_MODULE_PATH@\" \
+ -DSCIM_TEMPDIR=\"@SCIM_TEMPDIR@\"
+
+noinst_HEADERS = isf_wsm_utility.h
+
+if ISF_BUILD_WSM_EFL
+CONFIG_WSM_EFL = isf-wsm-efl
+endif
+
+bin_PROGRAMS = $(CONFIG_WSM_EFL)
+
+isf_wsm_efl_SOURCES = isf_wsm_efl.cpp \
+ isf_wsm_utility.cpp
+
+isf_wsm_efl_CXXFLAGS = @EFL_CFLAGS@ @VCONF_CFLAGS@ @DLOG_CFLAGS@ @TTS_CFLAGS@ @FEEDBACK_CFLAGS@
+
+isf_wsm_efl_LDFLAGS = @EFL_LIBS@ @LTLIBINTL@ -rpath $(libdir) \
+ @VCONF_LIBS@ \
+ @WAYLAND_LIBS@ \
+ @DLOG_LIBS@ \
+ @TTS_LIBS@ \
+ @FEEDBACK_LIBS@
+
+isf_wsm_efl_LDADD = $(top_builddir)/ism/src/libscim@SCIM_EPOCH@.la
+
--- /dev/null
+/*
+ * ISF(Input Service Framework)
+ *
+ * ISF is based on SCIM 1.4.7 and extended for supporting more fitable.
+ * Copyright (c) 2012-2014 Intel Co., Ltd.
+ *
+ * Contact: Yan Wang <yan.wang@intel.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#define Uses_SCIM_CONFIG_PATH
+#define Uses_SCIM_HELPER_MODULE
+#define Uses_SCIM_PANEL_AGENT
+#define Uses_SCIM_COMPOSE_KEY
+#define Uses_SCIM_IMENGINE_MODULE
+
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <list>
+#include <glib.h>
+#include <Evas.h>
+#include <Ecore.h>
+#include <Ecore_Wayland.h>
+#include <Ecore_File.h>
+#include <Elementary.h>
+#include <malloc.h>
+#include "scim_private.h"
+#include "scim.h"
+#include "scim_stl_map.h"
+#if HAVE_VCONF
+#include <vconf.h>
+#include <vconf-keys.h>
+#endif
+#include <privilege-control.h>
+#include "isf_wsm_utility.h"
+#include <dlog.h>
+#if HAVE_TTS
+#include <tts.h>
+#endif
+#if HAVE_FEEDBACK
+#include <feedback.h>
+#endif
+
+using namespace scim;
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Declaration of macro.
+/////////////////////////////////////////////////////////////////////////////
+#define EFL_CANDIDATE_THEME1 (SCIM_DATADIR "/isf_candidate_theme1.edj")
+
+#define ISF_CANDIDATE_TABLE 0
+
+#define ISF_EFL_AUX 1
+#define ISF_EFL_CANDIDATE_0 2
+#define ISF_EFL_CANDIDATE_ITEMS 3
+
+#define ISE_DEFAULT_HEIGHT_PORTRAIT 444
+#define ISE_DEFAULT_HEIGHT_LANDSCAPE 316
+
+#define ISF_SYSTEM_APPSERVICE_READY_VCONF "memory/appservice/status"
+#define ISF_SYSTEM_APPSERVICE_READY_STATE 1
+#define ISF_SYSTEM_WM_WAIT_COUNT 200
+#define ISF_SYSTEM_WAIT_DELAY 100 * 1000
+#define ISF_CANDIDATE_DESTROY_DELAY 3
+
+#define ISF_PREEDIT_BORDER 16
+
+#define LOG_TAG "ISF_WSM_EFL"
+
+/////////////////////////////////////////////////////////////////////////////
+// Declaration of external variables.
+/////////////////////////////////////////////////////////////////////////////
+extern MapStringVectorSizeT _groups;
+extern std::vector<String> _uuids;
+extern std::vector<String> _names;
+extern std::vector<String> _module_names;
+extern std::vector<String> _langs;
+extern std::vector<String> _icons;
+extern std::vector<uint32> _options;
+extern std::vector<TOOLBAR_MODE_T> _modes;
+
+extern EAPI CommonLookupTable g_isf_candidate_table;
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Declaration of internal data types.
+/////////////////////////////////////////////////////////////////////////////
+typedef enum _WINDOW_STATE {
+ WINDOW_STATE_HIDE = 0,
+ WINDOW_STATE_WILL_HIDE,
+ WINDOW_STATE_WILL_SHOW,
+ WINDOW_STATE_SHOW,
+ WINDOW_STATE_ON,
+} WINDOW_STATE;
+
+typedef std::map <String, Ecore_File_Monitor *> OSPEmRepository;
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Declaration of internal functions.
+/////////////////////////////////////////////////////////////////////////////
+static Evas_Object *efl_create_window (const char *strWinName, const char *strEffect);
+static void efl_set_transient_for_app_window (Ecore_X_Window window);
+static int efl_get_angle_for_app_window (void);
+static int efl_get_angle_for_ise_window (void);
+
+static int ui_candidate_get_valid_height (void);
+static void ui_candidate_hide (bool bForce, bool bSetVirtualKbd = true, bool will_hide = false);
+static void ui_destroy_candidate_window (void);
+static void ui_settle_candidate_window (void);
+static void ui_candidate_show (bool bSetVirtualKbd = true);
+static void ui_create_candidate_window (void);
+static void update_table (int table_type, const LookupTable &table);
+static void ui_candidate_window_close_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info);
+
+static bool check_wm_ready (void);
+static bool check_system_ready (void);
+static void launch_default_soft_keyboard (keynode_t *key = NULL, void* data = NULL);
+
+/* PanelAgent related functions */
+static bool initialize_panel_agent (const String &config, const String &display, bool resident);
+
+static void slot_reload_config (void);
+static void slot_focus_in (void);
+static void slot_focus_out (void);
+static void slot_expand_candidate (void);
+static void slot_contract_candidate (void);
+static void slot_set_candidate_style (int portrait_line, int mode);
+static void slot_update_input_context (int type, int value);
+static void slot_update_ise_geometry (int x, int y, int width, int height);
+static void slot_update_spot_location (int x, int y, int top_y);
+static void slot_update_factory_info (const PanelFactoryInfo &info);
+static void slot_show_preedit_string (void);
+static void slot_show_aux_string (void);
+static void slot_show_candidate_table (void);
+static void slot_hide_preedit_string (void);
+static void slot_hide_aux_string (void);
+static void slot_hide_candidate_table (void);
+static void slot_update_preedit_string (const String &str, const AttributeList &attrs, int caret);
+static void slot_update_preedit_caret (int caret);
+static void slot_update_aux_string (const String &str, const AttributeList &attrs);
+static void slot_update_candidate_table (const LookupTable &table);
+static void slot_select_candidate (int index);
+static void slot_set_active_ise (const String &uuid, bool changeDefault);
+static bool slot_get_ise_list (std::vector<String> &list);
+static bool slot_get_ise_information (String uuid, String &name, String &language, int &type, int &option, String &module_name);
+static bool slot_get_keyboard_ise_list (std::vector<String> &name_list);
+static void slot_get_language_list (std::vector<String> &name);
+static void slot_get_all_language (std::vector<String> &lang);
+static void slot_get_ise_language (char *name, std::vector<String> &list);
+static bool slot_get_ise_info (const String &uuid, ISE_INFO &info);
+static void slot_get_candidate_geometry (struct rectinfo &info);
+static void slot_get_input_panel_geometry (struct rectinfo &info);
+static void slot_set_keyboard_ise (const String &uuid);
+static void slot_get_keyboard_ise (String &ise_name, String &ise_uuid);
+static void slot_accept_connection (int fd);
+static void slot_close_connection (int fd);
+static void slot_exit (void);
+
+static void slot_register_helper_properties (int id, const PropertyList &props);
+static void slot_show_ise (void);
+static void slot_hide_ise (void);
+
+static void slot_will_hide_ack (void);
+static void slot_candidate_will_hide_ack (void);
+
+static void slot_get_ise_state (int &state);
+
+static Eina_Bool panel_agent_handler (void *data, Ecore_Fd_Handler *fd_handler);
+
+static Eina_Bool efl_create_control_window (void);
+static void _launch_default_soft_keyboard (void);
+
+/////////////////////////////////////////////////////////////////////////////
+// Declaration of internal variables.
+/////////////////////////////////////////////////////////////////////////////
+static Evas_Object *_candidate_window = 0;
+static Evas_Object *_candidate_area_1 = 0;
+static Evas_Object *_candidate_area_2 = 0;
+static Evas_Object *_candidate_bg = 0;
+static Evas_Object *_candidate_0_scroll = 0;
+static Evas_Object *_candidate_scroll = 0;
+static Evas_Object *_scroller_bg = 0;
+static Evas_Object *_candidate_0_table = 0;
+static Evas_Object *_candidate_table = 0;
+static Evas_Object *_candidate_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
+static Evas_Object *_candidate_items [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
+static Evas_Object *_seperate_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
+static Evas_Object *_seperate_items [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
+static Evas_Object *_line_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
+static Evas_Object *_line_items [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
+static Evas_Object *_more_btn = 0;
+static Evas_Object *_close_btn = 0;
+static bool _candidate_show_requested = false;
+
+static int _candidate_x = 0;
+static int _candidate_y = 0;
+static int _candidate_width = 0;
+static int _candidate_height = 0;
+static int _candidate_valid_height = 0;
+
+static bool _candidate_area_1_visible = false;
+static bool _candidate_area_2_visible = false;
+static bool _aux_area_visible = false;
+
+static ISF_CANDIDATE_MODE_T _candidate_mode = SOFT_CANDIDATE_WINDOW;
+static ISF_CANDIDATE_PORTRAIT_LINE_T _candidate_port_line = ONE_LINE_CANDIDATE;
+
+static int _candidate_port_width = 480;
+static int _candidate_port_height_min = 76;
+static int _candidate_port_height_min_2 = 150;
+static int _candidate_port_height_max = 286;
+static int _candidate_port_height_max_2 = 350;
+static int _candidate_land_width = 784;
+static int _candidate_land_height_min = 84;
+static int _candidate_land_height_min_2 = 168;
+static int _candidate_land_height_max = 150;
+static int _candidate_land_height_max_2 = 214;
+static int _candidate_area_1_pos [2] = {0, 2};
+static int _more_btn_pos [4] = {369, 11, 689, 11};
+static int _close_btn_pos [4] = {362, 211, 682, 75};
+
+static int _v_padding = 2;
+static int _item_min_width = 99;
+static int _item_min_height = 82;
+
+static int _candidate_scroll_0_width_min = 350;
+static int _candidate_scroll_0_width_max = 670;
+
+static int _candidate_scroll_width = 453;
+static int _candidate_scroll_width_min = 453;
+static int _candidate_scroll_width_max = 663;
+static int _candidate_scroll_height_min = 124;
+static int _candidate_scroll_height_max = 190;
+
+static Evas_Object *_preedit_window = 0;
+static Evas_Object *_preedit_text = 0;
+static int _preedit_width = 100;
+static int _preedit_height = 54;
+
+static Evas_Object *_aux_area = 0;
+static Evas_Object *_aux_line = 0;
+static Evas_Object *_aux_table = 0;
+static int _aux_height = 0;
+static int _aux_port_width = 444;
+static int _aux_land_width = 764;
+static std::vector<Evas_Object *> _aux_items;
+static std::vector<Evas_Object *> _aux_seperates;
+
+static Evas_Object *_tmp_preedit_text = 0;
+static Evas_Object *_tmp_aux_text = 0;
+static Evas_Object *_tmp_candidate_text = 0;
+
+static int _spot_location_x = -1;
+static int _spot_location_y = -1;
+static int _spot_location_top_y = -1;
+static int _candidate_angle = 0;
+static int _window_angle = -1;
+
+static int _ise_width = 0;
+static int _ise_height = 0;
+static WINDOW_STATE _ise_state = WINDOW_STATE_HIDE;
+static WINDOW_STATE _candidate_state = WINDOW_STATE_HIDE;
+
+static int _indicator_height = 0;//24;
+static int _screen_width = 720;
+static int _screen_height = 1280;
+static float _width_rate = 1.0;
+static float _height_rate = 1.0;
+static int _blank_width = 30;
+
+static String _candidate_name = String ("candidate");
+static String _candidate_edje_file = String (EFL_CANDIDATE_THEME1);
+
+static String _candidate_font_name = String ("Tizen");
+static int _candidate_font_size = 38;
+static int _aux_font_size = 38;
+static int _click_object = 0;
+static int _click_down_pos [2] = {0, 0};
+static int _click_up_pos [2] = {0, 0};
+static bool _is_click = true;
+static bool _appsvc_callback_regist = false;
+static String _initial_ise_uuid = String ("");
+static ConfigPointer _config;
+static PanelAgent *_panel_agent = 0;
+static std::vector<Ecore_Fd_Handler *> _read_handler_list;
+
+static clock_t _clock_start;
+
+static Ecore_Timer *_check_size_timer = NULL;
+static Ecore_Timer *_longpress_timer = NULL;
+static Ecore_Timer *_destroy_timer = NULL;
+static Ecore_Timer *_system_ready_timer = NULL;
+static Ecore_Timer *_off_prepare_done_timer = NULL;
+static Ecore_Timer *_candidate_hide_timer = NULL;
+
+static Ecore_X_Window _ise_window = 0;
+static Ecore_X_Window _app_window = 0;
+static Ecore_X_Window _control_window = 0;
+
+static Ecore_File_Monitor *_inh_helper_ise_em = NULL;
+static Ecore_File_Monitor *_inh_keyboard_ise_em = NULL;
+static Ecore_File_Monitor *_osp_helper_ise_em = NULL;
+static Ecore_File_Monitor *_osp_keyboard_ise_em = NULL;
+static OSPEmRepository _osp_bin_em;
+static OSPEmRepository _osp_info_em;
+
+static bool hw_kbd_mode = false;
+
+#if HAVE_TTS
+static tts_h _tts = NULL;
+#endif
+
+#if HAVE_FEEDBACK
+static bool feedback_initialized = false;
+#endif
+
+static Ecore_Event_Handler *_candidate_show_handler = NULL;
+
+/* This structure stores the geometry information reported by ISE */
+struct GeometryCache
+{
+ bool valid; /* Whether this information is currently valid */
+ int angle; /* For which angle this information is useful */
+ struct rectinfo geometry; /* Geometry information */
+};
+static struct GeometryCache _ise_reported_geometry = {0};
+
+/////////////////////////////////////////////////////////////////////////////
+// Implementation of internal functions.
+/////////////////////////////////////////////////////////////////////////////
+/**
+ * @brief Print system time point for panel performance.
+ *
+ * @param strInfo The output information.
+ */
+static void check_time (const char *strInfo)
+{
+ gettime (_clock_start, strInfo);
+ ISF_LOG ("%s ppid=%d pid=%d\n", strInfo, getppid (), getpid ());
+}
+
+/**
+ * @brief Check the specific file.
+ *
+ * @param strFile The file path.
+ *
+ * @return true if the file is existed, otherwise false.
+ */
+static bool check_file (const char* strFile)
+{
+ struct stat st;
+
+ /* Workaround so that "/" returns a true, otherwise we can't monitor "/" in ecore_file_monitor */
+ if (stat (strFile, &st) < 0 && strcmp (strFile, "/"))
+ return false;
+ else
+ return true;
+}
+
+/**
+ * @brief Flush memory for elm.
+ *
+ * @return void
+ */
+static void flush_memory (void)
+{
+ elm_cache_all_flush ();
+ malloc_trim (0);
+}
+
+/**
+ * @brief Get ISE geometry information.
+ * Returns the "expected" ISE geometry when kbd_state is ON, otherwise w/h set to 0
+ *
+ * @param info The data is used to store ISE position and size.
+ * @param kbd_state The keyboard state.
+ */
+static struct rectinfo get_ise_geometry ()
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ struct rectinfo info = {0, 0, 0, 0};
+
+ int win_w = _screen_width, win_h = _screen_height;
+ int angle = (_window_angle == -1) ? efl_get_angle_for_app_window () : _window_angle;
+
+ if (angle == 90 || angle == 270) {
+ win_w = _screen_height;
+ win_h = _screen_width;
+ }
+
+ /* If we have geometry reported by ISE, use the geometry information */
+ if (_ise_reported_geometry.valid && _ise_reported_geometry.angle == angle) {
+ info = _ise_reported_geometry.geometry;
+ } else {
+ /* READ ISE's SIZE HINT HERE */
+ int pos_x, pos_y, width, height;
+
+ // FIXME: Get the ISE's SIZE.
+ pos_x = 0;
+ pos_y = 0;
+ width = 0;
+ height = 0;
+
+ info.pos_x = pos_x;
+ info.pos_y = pos_y;
+ info.width = width;
+ info.height = height;
+ }
+ _ise_width = info.width;
+ _ise_height = info.height;
+
+ return info;
+}
+
+/**
+ * @brief Set keyboard geometry for autoscroll.
+ * This includes the ISE geometry together with candidate window
+ *
+ * @param kbd_state The keyboard state.
+ */
+static void set_keyboard_geometry_atom_info (Ecore_X_Window window, struct rectinfo ise_rect)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ if (hw_kbd_mode) {
+ ise_rect.pos_x = 0;
+ if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
+ ise_rect.width = _candidate_width;
+ ise_rect.height = _candidate_height;
+ }
+ int angle = efl_get_angle_for_app_window ();
+ if (angle == 90 || angle == 270)
+ ise_rect.pos_y = _screen_width - ise_rect.height;
+ else
+ ise_rect.pos_y = _screen_height - ise_rect.height;
+ } else {
+ if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
+ if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
+ _candidate_valid_height = ui_candidate_get_valid_height ();
+ if ((_candidate_height - _candidate_valid_height) > _ise_height) {
+ _candidate_valid_height = _candidate_height;
+ ise_rect.pos_y = ise_rect.pos_y + ise_rect.height - _candidate_height;
+ ise_rect.height = _candidate_height;
+ } else {
+ ise_rect.pos_y -= _candidate_valid_height;
+ ise_rect.height += _candidate_valid_height;
+ }
+ }
+ }
+ }
+
+ // FIXME: Ecore_X dependency.
+}
+
+/**
+ * @brief Get ISE index according to uuid.
+ *
+ * @param uuid The ISE uuid.
+ *
+ * @return The ISE index
+ */
+static int get_ise_index (const String uuid)
+{
+ int index = 0;
+ if (uuid.length () > 0) {
+ for (unsigned int i = 0; i < _uuids.size (); i++) {
+ if (uuid == _uuids[i]) {
+ index = i;
+ break;
+ }
+ }
+ }
+
+ return index;
+}
+
+/**
+ * @brief Get ISE module file path.
+ *
+ * @param module_name The ISE's module name.
+ * @param type The ISE's type.
+ *
+ * @return ISE module file path if successfully, otherwise return empty string.
+ */
+static String get_module_file_path (const String &module_name, const String &type)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ String strFile;
+ if (module_name.substr (0, 1) == String ("/")) {
+ strFile = module_name + String (".so");
+ if (access (strFile.c_str (), R_OK) == 0)
+ return strFile;
+ }
+
+ /* Check inhouse path */
+ strFile = String (SCIM_MODULE_PATH) +
+ String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION) +
+ String (SCIM_PATH_DELIM_STRING) + type +
+ String (SCIM_PATH_DELIM_STRING) + module_name + String (".so");
+ if (access (strFile.c_str (), R_OK) == 0)
+ return strFile;
+
+ const char *module_path_env = getenv ("SCIM_MODULE_PATH");
+ if (module_path_env) {
+ strFile = String (module_path_env) +
+ String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION) +
+ String (SCIM_PATH_DELIM_STRING) + type +
+ String (SCIM_PATH_DELIM_STRING) + module_name + String (".so");
+ if (access (strFile.c_str (), R_OK) == 0)
+ return strFile;
+ }
+
+ return String ("");
+}
+
+/**
+ * @brief Get module names for all 3rd party's IMEs.
+ * @param ops_module_names The list to store module names for all 3rd party's IMEs.
+ * @return module name list size
+ */
+static int osp_module_list_get (std::vector <String> &ops_module_names)
+{
+ const char *module_path_env = getenv ("SCIM_MODULE_PATH");
+ if (module_path_env) {
+ String path = String (module_path_env) +
+ String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION) +
+ String (SCIM_PATH_DELIM_STRING) + String ("Helper");
+ ops_module_names.clear ();
+
+ DIR *dir = opendir (path.c_str ());
+ if (dir) {
+ struct dirent *file = readdir (dir);
+ while (file) {
+ struct stat filestat;
+ String absfn = path + String (SCIM_PATH_DELIM_STRING) + file->d_name;
+ stat (absfn.c_str (), &filestat);
+ if (S_ISREG (filestat.st_mode)) {
+ String link_name = String (file->d_name);
+ ops_module_names.push_back (link_name.substr (0, link_name.find_last_of ('.')));
+ }
+
+ file = readdir (dir);
+ }
+ closedir (dir);
+ }
+ }
+
+ std::sort (ops_module_names.begin (), ops_module_names.end ());
+ ops_module_names.erase (std::unique (ops_module_names.begin (), ops_module_names.end ()), ops_module_names.end ());
+
+ return ops_module_names.size ();
+}
+
+static String osp_module_name_get (const String &path)
+{
+ String pkg_id = path.substr (path.find_last_of (SCIM_PATH_DELIM) + 1);
+ String ise_name = String ("");
+ String bin_path = path + String ("/bin");
+ DIR *dir = opendir (bin_path.c_str ());
+ if (dir) {
+ struct dirent *file = readdir (dir);
+ while (file) {
+ struct stat filestat;
+ String absfn = bin_path + String (SCIM_PATH_DELIM_STRING) + file->d_name;
+ stat (absfn.c_str (), &filestat);
+ if (S_ISREG (filestat.st_mode)) {
+ String ext = absfn.substr (absfn.length () - 4);
+ if (ext == String (".exe")) {
+ int begin = absfn.find_last_of (SCIM_PATH_DELIM) + 1;
+ ise_name = absfn.substr (begin, absfn.find_last_of ('.') - begin);
+ break;
+ }
+ }
+
+ file = readdir (dir);
+ }
+ closedir (dir);
+ } else {
+ LOGD ("open (%s) is failed!!!", bin_path.c_str ());
+ }
+ String module_name = String ("");
+ if (ise_name.length () > 0)
+ module_name = pkg_id + String (".") + ise_name;
+
+ LOGD ("module name = %s", module_name.c_str ());
+ return module_name;
+}
+
+static void osp_engine_dir_monitor_cb (void *data, Ecore_File_Monitor *em, Ecore_File_Event event, const char *path)
+{
+ String em_path = String (ecore_file_monitor_path_get (em));
+ String manifest_file = em_path.substr (0, em_path.find_last_of (SCIM_PATH_DELIM)) + String ("/info/manifest.xml");
+ String ext = String (path).substr (String (path).length () - 4);
+
+ if (event == ECORE_FILE_EVENT_CLOSED) {
+ if (String (path) == manifest_file || ext == String (".exe")) {
+ LOGD ("path = %s, event = %d", path, event);
+ String pkg_path = em_path.substr (0, em_path.find_last_of (SCIM_PATH_DELIM));
+ String module_name = osp_module_name_get (pkg_path);
+ const char *module_path_env = getenv ("SCIM_MODULE_PATH");
+ if (module_path_env && module_name.length () > 0) {
+ String module_path = String (module_path_env) +
+ String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION) +
+ String (SCIM_PATH_DELIM_STRING) + String ("Helper") + String (SCIM_PATH_DELIM_STRING) + module_name + String (".so");
+ isf_update_ise_module (String (module_path), _config);
+ _panel_agent->update_ise_list (_uuids);
+ _panel_agent->reload_config ();
+#if 0
+ String uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
+ int index = get_ise_index (uuid);
+ if (_modes[index] == TOOLBAR_HELPER_MODE) {
+ String active_module = get_module_file_path (_module_names[index], String ("Helper"));
+ if (String (module_path) == active_module) {
+ /* Restart helper ISE */
+ _panel_agent->hide_helper (uuid);
+ _panel_agent->stop_helper (uuid);
+ _panel_agent->start_helper (uuid);
+ }
+ }
+#endif
+ }
+ }
+ }
+}
+
+static void add_monitor_for_osp_module (const String &module_name)
+{
+ String rpath = String ("/opt/apps/") + module_name.substr (0, module_name.find_first_of ('.'));
+ String exe_path = rpath + String ("/bin");
+ String manifest_path = rpath + String ("/info");
+
+ if (_osp_bin_em.find (module_name) == _osp_bin_em.end () || _osp_bin_em[module_name] == NULL) {
+ _osp_bin_em[module_name] = ecore_file_monitor_add (exe_path.c_str (), osp_engine_dir_monitor_cb, NULL);
+ LOGD ("add %s", module_name.c_str ());
+ }
+ if (_osp_info_em.find (module_name) == _osp_info_em.end () || _osp_info_em[module_name] == NULL) {
+ _osp_info_em[module_name] = ecore_file_monitor_add (manifest_path.c_str (), osp_engine_dir_monitor_cb, NULL);
+ }
+}
+
+/**
+ * @brief : add monitor for engine file and info file update of 3rd party's IMEs
+ */
+static void add_monitor_for_all_osp_modules (void)
+{
+ std::vector<String> osp_module_list;
+ osp_module_list_get (osp_module_list);
+
+ if (osp_module_list.size () > 0) {
+ for (unsigned int i = 0; i < osp_module_list.size (); i++)
+ add_monitor_for_osp_module (osp_module_list[i]);
+ }
+}
+
+/**
+ * @brief Callback function for ISE file monitor.
+ *
+ * @param data Data to pass when it is called.
+ * @param em The handle of Ecore_File_Monitor.
+ * @param event The event type.
+ * @param path The path for current event.
+ */
+static void ise_file_monitor_cb (void *data, Ecore_File_Monitor *em, Ecore_File_Event event, const char *path)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " path=" << path << "\n";
+ LOGD ("path = %s, event = %d", path, event);
+
+ String directory = String (path);
+ directory = directory.substr (0, 4);
+ if (event == ECORE_FILE_EVENT_DELETED_FILE || event == ECORE_FILE_EVENT_CLOSED ||
+ (event == ECORE_FILE_EVENT_CREATED_FILE && directory == String ("/opt"))) {
+ String file_path = String (path);
+ String file_ext = file_path.substr (file_path.length () - 3);
+ if (file_ext != String (".so")) {
+ LOGD ("%s is not valid so file!!!", path);
+ return;
+ }
+
+ int begin = String (path).find_last_of (SCIM_PATH_DELIM) + 1;
+ String module_name = String (path).substr (begin, String (path).find_last_of ('.') - begin);
+
+ if (event == ECORE_FILE_EVENT_DELETED_FILE) {
+ /* Update ISE list */
+ std::vector<String> list;
+ slot_get_ise_list (list);
+
+ /* delete osp monitor */
+ OSPEmRepository::iterator iter = _osp_bin_em.find (module_name);
+ if (iter != _osp_bin_em.end ()) {
+ ecore_file_monitor_del (iter->second);
+ _osp_bin_em.erase (iter);
+ LOGD ("delete %s", module_name.c_str ());
+ }
+ iter = _osp_info_em.find (module_name);
+ if (iter != _osp_info_em.end ()) {
+ ecore_file_monitor_del (iter->second);
+ _osp_info_em.erase (iter);
+ }
+ } else if (event == ECORE_FILE_EVENT_CLOSED) {
+ isf_update_ise_module (String (path), _config);
+ _panel_agent->update_ise_list (_uuids);
+ _panel_agent->reload_config ();
+#if 0
+ String uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
+ int index = get_ise_index (uuid);
+ String strFile = String (ecore_file_monitor_path_get (em)) +
+ String (SCIM_PATH_DELIM_STRING) + _module_names[index] + String (".so");
+
+ if (String (path) == strFile && _modes[index] == TOOLBAR_HELPER_MODE) {
+ /* Restart helper ISE */
+ _panel_agent->hide_helper (uuid);
+ _panel_agent->stop_helper (uuid);
+ _panel_agent->start_helper (uuid);
+ }
+
+ /* add osp monitor */
+ if (event == ECORE_FILE_EVENT_CREATED_FILE && directory == String ("/opt")) {
+ add_monitor_for_osp_module (module_name);
+ LOGD ("add %s", module_name.c_str ());
+ }
+#endif
+ }
+ }
+}
+
+/**
+ * @brief Delete keyboard ISE file monitor.
+ */
+static void delete_ise_directory_em (void) {
+ if (_inh_keyboard_ise_em) {
+ ecore_file_monitor_del (_inh_keyboard_ise_em);
+ _inh_keyboard_ise_em = NULL;
+ }
+ if (_inh_helper_ise_em) {
+ ecore_file_monitor_del (_inh_helper_ise_em);
+ _inh_helper_ise_em = NULL;
+ }
+
+ if (_osp_keyboard_ise_em) {
+ ecore_file_monitor_del (_osp_keyboard_ise_em);
+ _osp_keyboard_ise_em = NULL;
+ }
+ if (_osp_helper_ise_em) {
+ ecore_file_monitor_del (_osp_helper_ise_em);
+ _osp_helper_ise_em = NULL;
+ }
+
+ OSPEmRepository::iterator iter;
+ for (iter = _osp_bin_em.begin (); iter != _osp_bin_em.end (); iter++) {
+ if (iter->second) {
+ ecore_file_monitor_del (iter->second);
+ iter->second = NULL;
+ }
+ }
+ for (iter = _osp_info_em.begin (); iter != _osp_info_em.end (); iter++) {
+ if (iter->second) {
+ ecore_file_monitor_del (iter->second);
+ iter->second = NULL;
+ }
+ }
+ _osp_bin_em.clear ();
+ _osp_info_em.clear ();
+}
+
+/**
+ * @brief Add inhouse ISEs and OSP ISEs directory monitor.
+ */
+static void add_ise_directory_em (void) {
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ // inhouse IMEngine path
+ String path = String (SCIM_MODULE_PATH) +
+ String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION) +
+ String (SCIM_PATH_DELIM_STRING) + String ("IMEngine");
+ if (_inh_keyboard_ise_em == NULL)
+ _inh_keyboard_ise_em = ecore_file_monitor_add (path.c_str (), ise_file_monitor_cb, NULL);
+
+ // inhouse Helper path
+ path = String (SCIM_MODULE_PATH) +
+ String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION) +
+ String (SCIM_PATH_DELIM_STRING) + String ("Helper");
+ if (_inh_helper_ise_em == NULL)
+ _inh_helper_ise_em = ecore_file_monitor_add (path.c_str (), ise_file_monitor_cb, NULL);
+
+ const char *module_path_env = getenv ("SCIM_MODULE_PATH");
+ if (module_path_env) {
+ // OSP IMEngine path
+ path = String (module_path_env) +
+ String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION) +
+ String (SCIM_PATH_DELIM_STRING) + String ("IMEngine");
+ if (access (path.c_str (), R_OK) == 0) {
+ if (_osp_keyboard_ise_em == NULL) {
+ _osp_keyboard_ise_em = ecore_file_monitor_add (path.c_str (), ise_file_monitor_cb, NULL);
+ LOGD ("ecore_file_monitor_add path=%s", path.c_str ());
+ }
+ } else {
+ LOGD ("access path=%s is failed!!!", path.c_str ());
+ }
+
+ // OSP Helper path
+ path = String (module_path_env) +
+ String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION) +
+ String (SCIM_PATH_DELIM_STRING) + String ("Helper");
+ if (access (path.c_str (), R_OK) == 0) {
+ if (_osp_helper_ise_em == NULL) {
+ _osp_helper_ise_em = ecore_file_monitor_add (path.c_str (), ise_file_monitor_cb, NULL);
+ LOGD ("ecore_file_monitor_add path=%s", path.c_str ());
+ }
+ } else {
+ LOGD ("access path=%s is failed!!!", path.c_str ());
+ }
+ } else {
+ LOGD ("getenv (\"SCIM_MODULE_PATH\") is failed!!!");
+ }
+
+ add_monitor_for_all_osp_modules ();
+}
+
+/**
+ * @brief Set keyboard ISE.
+ *
+ * @param uuid The keyboard ISE's uuid.
+ * @param module_name The keyboard ISE's module name.
+ *
+ * @return false if keyboard ISE change is failed, otherwise return true.
+ */
+static bool set_keyboard_ise (const String &uuid, const String &module_name)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ TOOLBAR_MODE_T mode = _panel_agent->get_current_toolbar_mode ();
+
+ if (TOOLBAR_HELPER_MODE == mode) {
+ String pre_uuid = _panel_agent->get_current_helper_uuid ();
+ _panel_agent->hide_helper (pre_uuid);
+ _panel_agent->stop_helper (pre_uuid);
+ } else if (TOOLBAR_KEYBOARD_MODE == mode) {
+ uint32 kbd_option = 0;
+ String kbd_uuid, kbd_name;
+ isf_get_keyboard_ise (_config, kbd_uuid, kbd_name, kbd_option);
+ if (kbd_uuid == uuid)
+ return false;
+ }
+
+ _panel_agent->change_factory (uuid);
+
+ String language = String ("~other");/*scim_get_locale_language (scim_get_current_locale ());*/
+ _config->write (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + language, uuid);
+
+ return true;
+}
+
+/**
+ * @brief Set helper ISE.
+ *
+ * @param uuid The helper ISE's uuid.
+ * @param module_name The helper ISE's module name.
+ *
+ * @return false if helper ISE change is failed, otherwise return true.
+ */
+static bool set_helper_ise (const String &uuid, const String &module_name)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ TOOLBAR_MODE_T mode = _panel_agent->get_current_toolbar_mode ();
+ String pre_uuid = _panel_agent->get_current_helper_uuid ();
+ if (pre_uuid == uuid)
+ return false;
+
+ if (TOOLBAR_HELPER_MODE == mode) {
+ _panel_agent->hide_helper (pre_uuid);
+ _panel_agent->stop_helper (pre_uuid);
+ char buf[256] = {0};
+ snprintf (buf, sizeof (buf), "time:%ld pid:%d %s %s stop helper(%s)\n",
+ time (0), getpid (), __FILE__, __func__, pre_uuid.c_str ());
+ isf_save_log (buf);
+ }
+
+ /* Set ComposeKey as keyboard ISE */
+ uint32 kbd_option = 0;
+ String kbd_uuid, kbd_name;
+ isf_get_keyboard_ise (_config, kbd_uuid, kbd_name, kbd_option);
+ if (kbd_uuid != String (SCIM_COMPOSE_KEY_FACTORY_UUID)) {
+ kbd_uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
+ _panel_agent->change_factory (kbd_uuid);
+
+ String language = String ("~other");/*scim_get_locale_language (scim_get_current_locale ());*/
+ _config->write (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + language, kbd_uuid);
+ }
+ char buf[256] = {0};
+ snprintf (buf, sizeof (buf), "time:%ld pid:%d %s %s Start helper(%s)\n",
+ time (0), getpid (), __FILE__, __func__, uuid.c_str ());
+ isf_save_log (buf);
+
+ _panel_agent->start_helper (uuid);
+ _config->write (String (SCIM_CONFIG_DEFAULT_HELPER_ISE), uuid);
+
+ return true;
+}
+
+/**
+ * @brief Set active ISE.
+ *
+ * @param uuid The ISE's uuid.
+ *
+ * @return false if ISE change is failed, otherwise return true.
+ */
+static bool set_active_ise (const String &uuid)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+ char buf[256] = {0};
+ snprintf (buf, sizeof (buf), "time:%ld pid:%d %s %s set ISE(%s)\n",
+ time (0), getpid (), __FILE__, __func__, uuid.c_str ());
+ isf_save_log (buf);
+
+ if (uuid.length () <= 0)
+ return false;
+
+ bool ise_changed = false;
+
+ for (unsigned int i = 0; i < _uuids.size (); i++) {
+ if (!uuid.compare (_uuids[i])) {
+ if (TOOLBAR_KEYBOARD_MODE == _modes[i])
+ ise_changed = set_keyboard_ise (_uuids[i], _module_names[i]);
+ else if (TOOLBAR_HELPER_MODE == _modes[i])
+ ise_changed = set_helper_ise (_uuids[i], _module_names[i]);
+
+ if (ise_changed) {
+ _panel_agent->set_current_toolbar_mode (_modes[i]);
+ _panel_agent->set_current_ise_name (_names[i]);
+
+ _ise_width = 0;
+ _ise_height = 0;
+ _ise_state = WINDOW_STATE_HIDE;
+ _candidate_mode = SOFT_CANDIDATE_WINDOW;
+ _candidate_port_line = ONE_LINE_CANDIDATE;
+ if (_candidate_window)
+ ui_create_candidate_window ();
+
+ scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _uuids[i]);
+ scim_global_config_flush ();
+
+ _config->flush ();
+ _config->reload ();
+ _panel_agent->reload_config ();
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * @brief Load ISF configuration and ISEs information.
+ */
+static void load_config (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ /* Read configurations. */
+ if (!_config.null ()) {
+ bool shared_ise = _config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), false);
+ _panel_agent->set_should_shared_ise (shared_ise);
+ }
+
+ isf_load_ise_information (ALL_ISE, _config);
+}
+
+/**
+ * @brief Reload config callback function for ISF panel.
+ *
+ * @param config The config pointer.
+ */
+static void config_reload_cb (const ConfigPointer &config)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ /* load_config (); */
+}
+
+static Eina_Bool system_ready_timeout_cb (void *data)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ LOGW ("Launching IME because of appservice ready timeout\n");
+
+ _launch_default_soft_keyboard ();
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+//////////////////////////////////////////////////////////////////////
+// Start of Candidate Functions
+//////////////////////////////////////////////////////////////////////
+/**
+ * @brief Get candidate window valid height for autoscroll.
+ *
+ * @return The valid height.
+ */
+static int ui_candidate_get_valid_height (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "\n";
+
+ int height = 0;
+ int angle = 0;
+
+ if (_candidate_window) {
+ if (_candidate_state == WINDOW_STATE_SHOW)
+ angle = _candidate_angle;
+ else
+ angle = efl_get_angle_for_app_window ();
+
+ if (_aux_area_visible && _candidate_area_1_visible) {
+ if (angle == 90 || angle == 270)
+ height = _candidate_land_height_min_2;
+ else
+ height = _candidate_port_height_min_2;
+ } else {
+ if (angle == 90 || angle == 270)
+ height = _candidate_land_height_min;
+ else
+ height = _candidate_port_height_min;
+ }
+ }
+ return height;
+}
+
+/**
+ * @brief Resize candidate window size.
+ *
+ * @param new_width New width for candidate window.
+ * @param new_height New height for candidate window.
+ */
+static void ui_candidate_window_resize (int new_width, int new_height)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " width:" << new_width << " height:" << new_height << "\n";
+
+ if (!_candidate_window)
+ return;
+
+ int height;
+
+ LOGD ("%s (w: %d, h: %d)\n", __func__, new_width, new_height);
+ evas_object_resize (_aux_line, new_width, 2);
+ _candidate_width = new_width;
+ _candidate_height = new_height;
+ if (_candidate_state == WINDOW_STATE_SHOW)
+ _panel_agent->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
+
+ if (_candidate_state == WINDOW_STATE_SHOW && _candidate_mode == FIXED_CANDIDATE_WINDOW) {
+ height = ui_candidate_get_valid_height ();
+ if ((_ise_width == 0 && _ise_height == 0) ||
+ (_ise_height > 0 && _candidate_valid_height != height) ||
+ (_ise_height > 0 && (_candidate_height - height) > _ise_height)) {
+ set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
+ _panel_agent->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
+ }
+ }
+
+ /* Get height for portrait and landscape */
+ int port_width = _candidate_port_width;
+ int port_height = _candidate_port_height_min;
+ int land_width = _candidate_land_width;
+ int land_height = _candidate_land_height_min;
+ if (_candidate_angle == 90 || _candidate_angle == 270) {
+ land_height = new_height;
+ if (land_height == _candidate_land_height_min_2) {
+ port_height = _candidate_port_height_min_2;
+ } else if (land_height == _candidate_land_height_max) {
+ port_height = _candidate_port_height_max;
+ } else if (land_height == _candidate_land_height_max_2) {
+ port_height = _candidate_port_height_max_2;
+ }
+ } else {
+ port_height = new_height;
+ if (port_height == _candidate_port_height_min_2) {
+ land_height = _candidate_land_height_min_2;
+ } else if (port_height == _candidate_port_height_max) {
+ land_height = _candidate_land_height_max;
+ } else if (port_height == _candidate_port_height_max_2) {
+ land_height = _candidate_land_height_max_2;
+ }
+ }
+
+ // FIXME: ECORE_X dependency.
+}
+
+/**
+ * @brief This function will show/hide widgets of candidate window,
+ * and resize candidate window size according to aux_area/candidate_area.
+ */
+static void ui_candidate_window_adjust (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+ if (!_candidate_window)
+ return;
+
+ int x, y, width, height;
+
+ /* Get candidate window size */
+ // FIXME:
+ x = y = 0;
+ width = _candidate_width;
+ height = _candidate_height;
+
+ if (_aux_area_visible && _candidate_area_2_visible) {
+ evas_object_show (_aux_line);
+ evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
+ if (_candidate_angle == 90 || _candidate_angle == 270) {
+ ui_candidate_window_resize (width, _candidate_land_height_max_2);
+ evas_object_move (_close_btn, _close_btn_pos[2], _close_btn_pos[3] + _candidate_port_height_min_2 - _candidate_port_height_min);
+ evas_object_move (_candidate_area_2, 0, _candidate_land_height_min_2);
+ evas_object_move (_scroller_bg, 0, _candidate_land_height_min_2);
+ } else {
+ ui_candidate_window_resize (width, _candidate_port_height_max_2);
+ evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
+ evas_object_move (_candidate_area_2, 0, _candidate_port_height_min_2);
+ evas_object_move (_scroller_bg, 0, _candidate_port_height_min_2);
+ }
+ } else if (_aux_area_visible && _candidate_area_1_visible) {
+ evas_object_show (_aux_line);
+ evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
+ if (_candidate_angle == 90 || _candidate_angle == 270) {
+ ui_candidate_window_resize (width, _candidate_land_height_min_2);
+ evas_object_move (_more_btn, _more_btn_pos[2], _more_btn_pos[3] + _candidate_port_height_min_2 - _candidate_port_height_min);
+ } else {
+ ui_candidate_window_resize (width, _candidate_port_height_min_2);
+ evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
+ }
+ } else if (_aux_area_visible) {
+ evas_object_hide (_aux_line);
+ ui_candidate_window_resize (width, _aux_height + 2);
+ } else if (_candidate_area_2_visible) {
+ evas_object_hide (_aux_line);
+ evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
+ if (_candidate_angle == 90 || _candidate_angle == 270) {
+ ui_candidate_window_resize (width, _candidate_land_height_max);
+ evas_object_move (_close_btn, _close_btn_pos[2], _close_btn_pos[3]);
+ evas_object_move (_candidate_area_2, 0, _candidate_land_height_min);
+ evas_object_move (_scroller_bg, 0, _candidate_land_height_min);
+ } else {
+ ui_candidate_window_resize (width, _candidate_port_height_max);
+ evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1]);
+ evas_object_move (_candidate_area_2, 0, _candidate_port_height_min);
+ evas_object_move (_scroller_bg, 0, _candidate_port_height_min);
+ }
+ } else {
+ evas_object_hide (_aux_line);
+ evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
+ if (_candidate_angle == 90 || _candidate_angle == 270) {
+ ui_candidate_window_resize (width, _candidate_land_height_min);
+ evas_object_move (_more_btn, _more_btn_pos[2], _more_btn_pos[3]);
+ } else {
+ ui_candidate_window_resize (width, _candidate_port_height_min);
+ evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1]);
+ }
+ }
+}
+
+/**
+ * @brief Rotate candidate window.
+ *
+ * @param angle The angle of candidate window.
+ */
+static void ui_candidate_window_rotate (int angle)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+ if (!_candidate_window)
+ return;
+
+ ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
+
+ if (angle == 90 || angle == 270) {
+ _candidate_scroll_width = _candidate_scroll_width_max;
+ ui_candidate_window_resize (_candidate_land_width, _candidate_land_height_min);
+ evas_object_resize (_aux_area, _aux_land_width, _aux_height);
+ evas_object_resize (_candidate_area_1, _candidate_scroll_0_width_max, _item_min_height);
+ evas_object_resize (_candidate_area_2, _candidate_scroll_width, _candidate_scroll_height_min);
+ evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_min + 6);
+ } else {
+ _candidate_scroll_width = _candidate_scroll_width_min;
+ ui_candidate_window_resize (_candidate_port_width, _candidate_port_height_min);
+ evas_object_resize (_aux_area, _aux_port_width, _aux_height);
+ evas_object_resize (_candidate_area_1, _candidate_scroll_0_width_min, (_item_min_height+2)*_candidate_port_line-2);
+ evas_object_resize (_candidate_area_2, _candidate_scroll_width, _candidate_scroll_height_max);
+ evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
+ }
+
+ evas_object_hide (_candidate_area_2);
+ _candidate_area_2_visible = false;
+ ui_candidate_window_adjust ();
+ if (_candidate_area_1_visible) {
+ update_table (ISF_CANDIDATE_TABLE, g_isf_candidate_table);
+ }
+ flush_memory ();
+
+ LOGD ("elm_win_rotation_with_resize_set (window : %p, angle : %d)\n", _candidate_window, angle);
+ elm_win_rotation_with_resize_set (_candidate_window, angle);
+ if (_preedit_window)
+ elm_win_rotation_with_resize_set (_preedit_window, angle);
+}
+
+/**
+ * @brief This function is used to judge whether candidate window should be hidden.
+ *
+ * @return true if candidate window should be hidden, otherwise return false.
+ */
+static bool ui_candidate_can_be_hide (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ if (_aux_area_visible || _candidate_area_1_visible || _candidate_area_2_visible)
+ return false;
+ else
+ return true;
+}
+
+/**
+ * @brief Delete check candidate window size timer.
+ *
+ * @return void
+ */
+static void ui_candidate_delete_check_size_timer (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ if (_check_size_timer != NULL) {
+ ecore_timer_del (_check_size_timer);
+ _check_size_timer = NULL;
+ }
+}
+
+/**
+ * @brief Callback function for check candidate window size timer.
+ *
+ * @param data Data to pass when it is called.
+ *
+ * @return ECORE_CALLBACK_CANCEL
+ */
+static Eina_Bool ui_candidate_check_size_timeout (void *data)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ ui_candidate_delete_check_size_timer ();
+ ui_candidate_window_resize (_candidate_width, _candidate_height);
+ ui_settle_candidate_window ();
+ return ECORE_CALLBACK_CANCEL;
+}
+
+/**
+ * @brief Delete longpress timer.
+ *
+ * @return void
+ */
+static void ui_candidate_delete_longpress_timer (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ if (_longpress_timer != NULL) {
+ ecore_timer_del (_longpress_timer);
+ _longpress_timer = NULL;
+ }
+}
+
+/**
+ * @brief Callback function for candidate longpress timer.
+ *
+ * @param data Data to pass when it is called.
+ *
+ * @return ECORE_CALLBACK_CANCEL
+ */
+static Eina_Bool ui_candidate_longpress_timeout (void *data)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ int index = (int)GPOINTER_TO_INT(data);
+ ui_candidate_delete_longpress_timer ();
+ _is_click = false;
+ _panel_agent->send_longpress_event (_click_object, index);
+ return ECORE_CALLBACK_CANCEL;
+}
+
+/**
+ * @brief Delete destroy timer.
+ *
+ * @return void
+ */
+static void ui_candidate_delete_destroy_timer (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ if (_destroy_timer != NULL) {
+ ecore_timer_del (_destroy_timer);
+ _destroy_timer = NULL;
+ }
+}
+
+/**
+ * @brief Callback function for destroy timer.
+ *
+ * @param data Data to pass when it is called.
+ *
+ * @return ECORE_CALLBACK_CANCEL
+ */
+static Eina_Bool ui_candidate_destroy_timeout (void *data)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ ui_candidate_delete_destroy_timer ();
+ ui_destroy_candidate_window ();
+ return ECORE_CALLBACK_CANCEL;
+}
+
+/**
+ * @brief Callback function for off_prepare_done.
+ *
+ * @param data Data to pass when it is called.
+ *
+ * @return ECORE_CALLBACK_CANCEL
+ */
+static Eina_Bool off_prepare_done_timeout (void *data)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ /* WMSYNC, #8 Let the Window Manager to actually hide keyboard window */
+ // WILL_HIDE_REQUEST_DONE Ack to WM
+ // FIXME:
+
+ _off_prepare_done_timer = NULL;
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+/**
+ * @brief Delete candidate hide timer.
+ *
+ * @return void
+ */
+static void delete_candidate_hide_timer (void)
+{
+ LOGD ("deleting candidate_hide_timer");
+ if (_candidate_hide_timer) {
+ ecore_timer_del (_candidate_hide_timer);
+ _candidate_hide_timer = NULL;
+ }
+}
+
+static void candidate_window_hide (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "\n";
+
+ delete_candidate_hide_timer ();
+ _candidate_state = WINDOW_STATE_HIDE;
+
+ LOGD ("evas_object_hide (_candidate_window, %p)\n", elm_win_xwindow_get (_candidate_window));
+
+ if (_candidate_window) {
+ /* There are cases that when there are rapid ISE_HIDE and ISE_SHOW requests,
+ candidate window should be displayed but STATE_OFF for the first ISE_HIDE
+ calls this function, so when the candidate window is shown by the following
+ STATE_ON message, a blank area is displayed in candidate window -
+ so we let the _cnadidate_area_1 as the default area that would be displayed */
+ //evas_object_hide (_candidate_area_1);
+ //evas_object_hide (_more_btn);
+ _candidate_area_1_visible = false;
+
+ evas_object_hide (_candidate_window);
+ SCIM_DEBUG_MAIN (3) << " Hide candidate window\n";
+ }
+}
+
+/**
+ * @brief Callback function for candidate hide timer
+ *
+ * @param data Data to pass when it is called.
+ *
+ * @return ECORE_CALLBACK_CANCEL
+ */
+static Eina_Bool candidate_hide_timer (void *data)
+{
+ LOGD ("calling candidate_window_hide()");
+ candidate_window_hide ();
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+/**
+ * @brief Delete candidate show handler.
+ *
+ * @return void
+ */
+static void delete_candidate_show_handler (void)
+{
+ if (_candidate_show_handler) {
+ ecore_event_handler_del (_candidate_show_handler);
+ _candidate_show_handler = NULL;
+ }
+}
+
+
+/**
+ * @brief Show candidate window.
+ *
+ * @param bSetVirtualKbd The flag for set_keyboard_geometry_atom_info () calling.
+ */
+static void ui_candidate_show (bool bSetVirtualKbd)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+ int hw_kbd_detect = _config->read (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 0);
+
+ delete_candidate_hide_timer ();
+
+ if (!_candidate_window) return;
+
+ /* FIXME : SHOULD UNIFY THE METHOD FOR CHECKING THE HW KEYBOARD EXISTENCE */
+ /* If the ISE is not visible currently, wait for the ISE to be opened and then show our candidate window */
+ _candidate_show_requested = true;
+ if( (hw_kbd_detect == 0 && _ise_state != WINDOW_STATE_SHOW)) {
+ LOGD ("setting _show_can didate_requested to TRUE");
+ return;
+ }
+
+ ui_candidate_window_rotate (_candidate_angle);
+
+ /* If the candidate window was about to hide, turn it back to SHOW state now */
+ if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
+ _candidate_state = WINDOW_STATE_SHOW;
+ }
+
+ /* Change to WILL_SHOW state only when we are not currently in SHOW state */
+ if (_candidate_state != WINDOW_STATE_SHOW) {
+ _candidate_state = WINDOW_STATE_WILL_SHOW;
+ }
+
+ if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
+ if (bSetVirtualKbd) {
+ set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
+ }
+ }
+
+ ui_candidate_delete_check_size_timer ();
+ _check_size_timer = ecore_timer_add (0.02, ui_candidate_check_size_timeout, NULL);
+
+ SCIM_DEBUG_MAIN (3) << " Show candidate window\n";
+ if (_ise_state == WINDOW_STATE_SHOW) {
+ edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "more_button");
+ edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "close_button");
+ } else {
+ edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "close_button");
+ edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "more_button");
+ }
+
+ /* If we are in hardward keyboard mode, this candidate window is now considered to be a input panel */
+ if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
+ if (hw_kbd_mode) {
+ LOGD ("sending ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW");
+ _panel_agent->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW);
+ }
+ }
+
+ evas_object_show (_candidate_window);
+}
+
+/**
+ * @brief Hide candidate window.
+ *
+ * @param bForce The flag to hide candidate window by force.
+ * @param bSetVirtualKbd The flag for set_keyboard_geometry_atom_info () calling.
+ */
+static void ui_candidate_hide (bool bForce, bool bSetVirtualKbd, bool will_hide)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " bForce:" << bForce << " bSetVirtualKbd:" << bSetVirtualKbd << " will_hide:" << will_hide << "...\n";
+
+ if (!_candidate_window)
+ return;
+
+ if (bForce) {
+ if (_candidate_area_2 && _candidate_area_2_visible) {
+ evas_object_hide (_candidate_area_2);
+ _candidate_area_2_visible = false;
+ evas_object_hide (_scroller_bg);
+ evas_object_hide (_close_btn);
+ _panel_agent->candidate_more_window_hide ();
+ ui_candidate_window_adjust ();
+ }
+ }
+
+ if (bForce || ui_candidate_can_be_hide ()) {
+ if (will_hide) {
+ LOGD ("candidate_state = WILL_HIDE");
+ _candidate_state = WINDOW_STATE_WILL_HIDE;
+
+ delete_candidate_hide_timer ();
+ _candidate_hide_timer = ecore_timer_add (2.0, candidate_hide_timer, NULL);
+ }
+
+ if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
+ /* FIXME : should check if bSetVirtualKbd flag is really needed in this case */
+ if (_ise_state == WINDOW_STATE_SHOW) {
+ set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
+ } else {
+ if (bSetVirtualKbd) {
+ set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
+ }
+ }
+ }
+
+ if (!will_hide) {
+ /* If we are not in will_hide state, hide the candidate window immediately */
+ candidate_window_hide ();
+ evas_object_hide (_preedit_window);
+ }
+ }
+}
+
+/**
+ * @brief Callback function for more button.
+ *
+ * @param data Data to pass when it is called.
+ * @param e The evas for current event.
+ * @param button The evas object for current event.
+ * @param event_info The information for current event.
+ */
+static void ui_candidate_window_more_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ _panel_agent->candidate_more_window_show ();
+
+ if (_candidate_angle == 180 || _candidate_angle == 270) {
+ Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
+ ecore_evas_move_resize (ee, 0, 0, 0, 0);
+ }
+
+ evas_object_show (_candidate_area_2);
+ _candidate_area_2_visible = true;
+ evas_object_show (_scroller_bg);
+ evas_object_hide (_more_btn);
+ evas_object_show (_close_btn);
+
+ ui_candidate_window_adjust ();
+ ui_settle_candidate_window ();
+ flush_memory ();
+}
+
+/**
+ * @brief Callback function for close button.
+ *
+ * @param data Data to pass when it is called.
+ * @param e The evas for current event.
+ * @param button The evas object for current event.
+ * @param event_info The information for current event.
+ */
+static void ui_candidate_window_close_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ if (_candidate_area_2 == NULL || !_candidate_area_2_visible)
+ return;
+
+ evas_object_hide (_candidate_area_2);
+ _candidate_area_2_visible = false;
+ evas_object_hide (_scroller_bg);
+ evas_object_hide (_close_btn);
+ _panel_agent->candidate_more_window_hide ();
+
+ evas_object_show (_candidate_area_1);
+ _candidate_area_1_visible = true;
+ evas_object_show (_more_btn);
+
+ elm_scroller_region_show (_candidate_area_2, 0, 0, _candidate_scroll_width, 100);
+ if (_candidate_angle == 180 || _candidate_angle == 270) {
+ Ecore_Evas *ee= ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
+ ecore_evas_move_resize (ee, 0, 0, 0, 0);
+ }
+
+ ui_candidate_window_adjust ();
+ ui_settle_candidate_window ();
+ flush_memory ();
+}
+
+/**
+ * @brief Callback function for mouse button press.
+ *
+ * @param data Data to pass when it is called.
+ * @param e The evas for current event.
+ * @param button The evas object for current event.
+ * @param event_info The information for current event.
+ */
+static void ui_mouse_button_pressed_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ _click_object = GPOINTER_TO_INT (data) & 0xFF;
+ _is_click = true;
+
+ Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
+ _click_down_pos [0] = ev->canvas.x;
+ _click_down_pos [1] = ev->canvas.y;
+
+ if (_click_object == ISF_EFL_CANDIDATE_0 || _click_object == ISF_EFL_CANDIDATE_ITEMS) {
+ int index = GPOINTER_TO_INT (data) >> 8;
+
+#if HAVE_FEEDBACK
+ if (feedback_initialized) {
+ int feedback_result = 0;
+
+ feedback_result = feedback_play_type (FEEDBACK_TYPE_SOUND, FEEDBACK_PATTERN_SIP);
+
+ if (FEEDBACK_ERROR_NONE == feedback_result)
+ LOGD ("Sound play successful");
+ else
+ LOGW ("Cannot play feedback sound : %d", feedback_result);
+
+ feedback_result = feedback_play_type (FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_SIP);
+
+ if (FEEDBACK_ERROR_NONE == feedback_result)
+ LOGD ("Vibration play successful");
+ else
+ LOGW ("Cannot play feedback vibration : %d", feedback_result);
+ }
+#endif
+
+ ui_candidate_delete_longpress_timer ();
+ _longpress_timer = ecore_timer_add (1.0, ui_candidate_longpress_timeout, (void *)index);
+ }
+}
+
+/**
+ * @brief Callback function for mouse button release.
+ *
+ * @param data Data to pass when it is called.
+ * @param e The evas for current event.
+ * @param button The evas object for current event.
+ * @param event_info The information for current event.
+ */
+static void ui_mouse_button_released_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " index:" << GPOINTER_TO_INT (data) << "...\n";
+
+ ui_candidate_delete_longpress_timer ();
+
+ int index = GPOINTER_TO_INT (data);
+ if (_click_object == ISF_EFL_AUX && _is_click) {
+/* double ret = 0;
+ const char *buf = edje_object_part_state_get (button, "aux", &ret);
+ if (strcmp ("selected", buf)) {
+ for (unsigned int i = 0; i < _aux_items.size (); i++) {
+ buf = edje_object_part_state_get (_aux_items [i], "aux", &ret);
+ if (!strcmp ("selected", buf))
+ edje_object_signal_emit (_aux_items [i], "aux,state,unselected", "aux");
+ }
+ edje_object_signal_emit (button, "aux,state,selected", "aux");
+ _panel_agent->select_aux (index);
+ }*/
+ int r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3;
+ edje_object_color_class_get (_aux_items [index], "text_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3);
+ // Normal item is clicked
+ if (!(r == 62 && g == 207 && b == 255)) {
+ for (unsigned int i = 0; i < _aux_items.size (); i++) {
+ edje_object_color_class_set (_aux_items [i], "text_color", 249, 249, 249, 255, r2, g2, b2, a2, r3, g3, b3, a3);
+ }
+ edje_object_color_class_set (_aux_items [index], "text_color", 62, 207, 255, 255, r2, g2, b2, a2, r3, g3, b3, a3);
+ _panel_agent->select_aux (index);
+ }
+ } else if (_click_object == ISF_EFL_CANDIDATE_0 && _is_click) {
+ ui_candidate_window_close_button_cb (NULL, NULL, _close_btn, NULL);
+ _panel_agent->select_candidate (index);
+ } else if (_click_object == ISF_EFL_CANDIDATE_ITEMS && _is_click) {
+ ui_candidate_window_close_button_cb (NULL, NULL, _close_btn, NULL);
+ _panel_agent->select_candidate (index);
+ }
+}
+
+/**
+ * @brief Callback function for mouse move.
+ *
+ * @param data Data to pass when it is called.
+ * @param e The evas for current event.
+ * @param button The evas object for current event.
+ * @param event_info The information for current event.
+ */
+static void ui_mouse_moved_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
+ _click_up_pos [0] = ev->canvas.x;
+ _click_up_pos [1] = ev->canvas.y;
+
+ if (abs (_click_up_pos [0] - _click_down_pos [0]) >= (int)(15 * _height_rate) ||
+ abs (_click_up_pos [1] - _click_down_pos [1]) >= (int)(15 * _height_rate)) {
+ _is_click = false;
+ ui_candidate_delete_longpress_timer ();
+ }
+}
+
+/**
+ * @brief Open TTS device.
+ *
+ * @return false if open is failed, otherwise return true.
+ */
+static bool ui_open_tts (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+#if HAVE_TTS
+ int r = tts_create (&_tts);
+ if (TTS_ERROR_NONE != r) {
+ LOGW ("tts_create FAILED : result(%d)\n", r);
+ _tts = NULL;
+ return false;
+ }
+
+ r = tts_set_mode (_tts, TTS_MODE_SCREEN_READER);
+ if (TTS_ERROR_NONE != r) {
+ LOGW ("tts_set_mode FAILED : result(%d)\n", r);
+ }
+
+ tts_state_e current_state;
+ r = tts_get_state (_tts, ¤t_state);
+ if (TTS_ERROR_NONE != r) {
+ LOGW ("tts_get_state FAILED : result(%d)\n", r);
+ }
+
+ if (TTS_STATE_CREATED == current_state) {
+ r = tts_prepare (_tts);
+ if (TTS_ERROR_NONE != r) {
+ LOGW ("tts_prepare FAILED : ret(%d)\n", r);
+ }
+ }
+ return true;
+#else
+ return false;
+#endif
+}
+
+/**
+ * @brief Close TTS device.
+ */
+static void ui_close_tts (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+#if HAVE_TTS
+ if (_tts) {
+ int r = tts_unprepare (_tts);
+ if (TTS_ERROR_NONE != r) {
+ LOGW ("tts_unprepare FAILED : result(%d)\n", r);
+ }
+
+ r = tts_destroy (_tts);
+ if (TTS_ERROR_NONE != r) {
+ LOGW ("tts_destroy FAILED : result(%d)\n", r);
+ }
+ }
+#endif
+}
+
+/**
+ * @brief Play string by TTS.
+ *
+ * @param str The string for playing.
+ */
+static void ui_play_tts (const char* str)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << "\n";
+
+#if HAVE_TTS
+ if (_tts == NULL) {
+ if (!ui_open_tts ())
+ return;
+ }
+
+ if (str) {
+ int r;
+ int utt_id = 0;
+ tts_state_e current_state;
+
+ r = tts_get_state (_tts, ¤t_state);
+ if (TTS_ERROR_NONE != r) {
+ LOGW ("Fail to get state from TTS : ret(%d)\n", r);
+ }
+
+ if (TTS_STATE_PLAYING == current_state) {
+ r = tts_stop (_tts);
+ if (TTS_ERROR_NONE != r) {
+ LOGW ("Fail to stop TTS : ret(%d)\n", r);
+ }
+ }
+ /* FIXME: Should support for all languages */
+ r = tts_add_text (_tts, str, "en_US", TTS_VOICE_TYPE_FEMALE, TTS_SPEED_NORMAL, &utt_id);
+ if (TTS_ERROR_NONE == r) {
+ r = tts_play (_tts);
+ if (TTS_ERROR_NONE != r) {
+ LOGW ("Fail to play TTS : ret(%d)\n", r);
+ }
+ }
+ }
+#endif
+}
+
+/**
+ * @brief Mouse over (find focus object and play text by TTS) when screen reader is enabled.
+ *
+ * @param mouse_x Mouse X position.
+ * @param mouse_y Mouse Y position.
+ */
+static void ui_mouse_over (int mouse_x, int mouse_y)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+ if (_candidate_window == NULL || _candidate_state != WINDOW_STATE_SHOW)
+ return;
+
+ int x, y, width, height;
+ for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
+ if (_candidate_0 [i]) {
+ evas_object_geometry_get (_candidate_0 [i], &x, &y, &width, &height);
+ if (mouse_x >= x && mouse_x <= x + width && mouse_y >= y && mouse_y <= y + height) {
+ /* FIXME: Should consider emoji case */
+ String mbs = utf8_wcstombs (g_isf_candidate_table.get_candidate_in_current_page (i));
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " play candidate string: " << mbs << "\n";
+ ui_play_tts (mbs.c_str ());
+ return;
+ }
+ }
+ }
+
+ String strTts = String ("");
+ if (_candidate_area_2_visible) {
+ evas_object_geometry_get (_close_btn, &x, &y, &width, &height);
+ if (mouse_x >= x && mouse_x <= x + width && mouse_y >= y && mouse_y <= y + height)
+ strTts = String ("close button");
+ } else {
+ evas_object_geometry_get (_more_btn, &x, &y, &width, &height);
+ if (mouse_x >= x && mouse_x <= x + width && mouse_y >= y && mouse_y <= y + height)
+ strTts = String ("more button");
+ }
+ if (strTts.length () > 0)
+ ui_play_tts (strTts.c_str ());
+}
+
+/**
+ * @brief Mouse click (find focus object and do click event) when screen reader is enabled.
+ *
+ * @param mouse_x Mouse X position.
+ * @param mouse_y Mouse Y position.
+ */
+static void ui_mouse_click (int mouse_x, int mouse_y)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+ if (_candidate_window == NULL || _candidate_state != WINDOW_STATE_SHOW)
+ return;
+
+ int x, y, width, height;
+ for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
+ if (_candidate_0 [i]) {
+ evas_object_geometry_get (_candidate_0 [i], &x, &y, &width, &height);
+ if (mouse_x >= x && mouse_x <= x + width && mouse_y >= y && mouse_y <= y + height) {
+ Evas_Event_Mouse_Down event_info;
+ event_info.canvas.x = mouse_x;
+ event_info.canvas.y = mouse_y;
+ ui_mouse_button_pressed_cb (GINT_TO_POINTER ((i << 8) + ISF_EFL_CANDIDATE_0), NULL, NULL, &event_info);
+ ui_mouse_button_released_cb (GINT_TO_POINTER (i), NULL, NULL, &event_info);
+ return;
+ }
+ }
+ }
+
+ if (_candidate_area_2_visible) {
+ evas_object_geometry_get (_close_btn, &x, &y, &width, &height);
+ if (mouse_x >= x && mouse_x <= x + width && mouse_y >= y && mouse_y <= y + height) {
+ ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
+ }
+ } else {
+ evas_object_geometry_get (_more_btn, &x, &y, &width, &height);
+ if (mouse_x >= x && mouse_x <= x + width && mouse_y >= y && mouse_y <= y + height) {
+ ui_candidate_window_more_button_cb (NULL, NULL, NULL, NULL);
+ }
+ }
+}
+
+/**
+ * @brief Create preedit window.
+ */
+static void ui_create_preedit_window (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ _preedit_width = 100;
+ _preedit_height = _preedit_height * _height_rate;
+ if (_preedit_window == NULL) {
+ _preedit_window = efl_create_window ("preedit", "Preedit Window");
+ evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
+
+ int preedit_font_size = (int)(32 * _width_rate);
+
+ _preedit_text = edje_object_add (evas_object_evas_get (_preedit_window));
+ edje_object_file_set (_preedit_text, _candidate_edje_file.c_str (), "preedit_text");
+ edje_object_text_class_set (_preedit_text, "preedit_text_class", _candidate_font_name.c_str (), preedit_font_size);
+ evas_object_size_hint_fill_set (_preedit_text, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_size_hint_weight_set (_preedit_text, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add (_preedit_window, _preedit_text);
+ evas_object_show (_preedit_text);
+
+ _tmp_preedit_text = evas_object_text_add (evas_object_evas_get (_preedit_window));
+ evas_object_text_font_set (_tmp_preedit_text, _candidate_font_name.c_str (), preedit_font_size);
+ }
+}
+
+/**
+ * @brief Create native style candidate window.
+ */
+static void ui_create_native_candidate_window (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ _candidate_port_width = _screen_width;
+ _candidate_port_height_min = 84 * _height_rate * _candidate_port_line;
+ _candidate_port_height_min_2 = 84 * _height_rate + _candidate_port_height_min;
+ _candidate_port_height_max = 444 * _height_rate + _candidate_port_height_min;
+ _candidate_port_height_max_2 = 84 * _height_rate + _candidate_port_height_max;
+ _candidate_land_width = _screen_height;
+ _candidate_land_height_min = 84 * _width_rate;
+ _candidate_land_height_min_2 = 168 * _width_rate;
+ _candidate_land_height_max = 316 * _width_rate + _candidate_land_height_min;
+ _candidate_land_height_max_2 = 426 * _width_rate;
+
+ _candidate_scroll_0_width_min= _screen_width;
+ _candidate_scroll_0_width_max= _screen_height;
+ _candidate_scroll_width_min = _screen_width;
+ _candidate_scroll_width_max = _screen_height;
+ _candidate_scroll_height_min = 252 * _width_rate;
+ _candidate_scroll_height_max = 420 * _height_rate;
+
+ _candidate_area_1_pos [0] = 0 * _width_rate;
+ _candidate_area_1_pos [1] = 2 * _height_rate;
+ _more_btn_pos [0] = 628 * _width_rate;
+ _more_btn_pos [1] = 12 * _height_rate;
+ _more_btn_pos [2] = 1188 * _height_rate;
+ _more_btn_pos [3] = 12 * _width_rate;
+ _close_btn_pos [0] = 628 * _width_rate;
+ _close_btn_pos [1] = 12 * _height_rate;
+ _close_btn_pos [2] = 1188 * _height_rate;
+ _close_btn_pos [3] = 12 * _width_rate;
+
+ _aux_height = 84 * _height_rate - 2;
+ _aux_port_width = _screen_width;
+ _aux_land_width = _screen_height;
+
+ _item_min_height = 84 * _height_rate - 2;
+
+ /* Create candidate window */
+ if (_candidate_window == NULL) {
+ _candidate_window = efl_create_window ("candidate", "Prediction Window");
+ if (_candidate_angle == 90 || _candidate_angle == 270) {
+ _candidate_width = _candidate_land_width;
+ _candidate_height = _candidate_land_height_min;
+ } else {
+ _candidate_width = _candidate_port_width;
+ _candidate_height = _candidate_port_height_min;
+ }
+
+ // FIXME: Ecore_X dependency.
+
+ /* Add background */
+ _candidate_bg = edje_object_add (evas_object_evas_get (_candidate_window));
+ edje_object_file_set (_candidate_bg, _candidate_edje_file.c_str (), "candidate_bg");
+ evas_object_size_hint_weight_set (_candidate_bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add (_candidate_window, _candidate_bg);
+ evas_object_show (_candidate_bg);
+
+ /* Create _candidate_0 scroller */
+ _candidate_0_scroll = elm_scroller_add (_candidate_window);
+ elm_scroller_bounce_set (_candidate_0_scroll, EINA_TRUE, EINA_FALSE);
+ elm_scroller_policy_set (_candidate_0_scroll, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
+ evas_object_resize (_candidate_0_scroll, _candidate_scroll_0_width_min, (_item_min_height+2)*_candidate_port_line-2);
+ evas_object_move (_candidate_0_scroll, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
+ _candidate_0_table = elm_table_add (_candidate_window);
+ evas_object_size_hint_weight_set (_candidate_0_table, 0.0, 0.0);
+ evas_object_size_hint_align_set (_candidate_0_table, 0.0, 0.0);
+ elm_table_padding_set (_candidate_0_table, 0, 0);
+ elm_object_content_set (_candidate_0_scroll, _candidate_0_table);
+ evas_object_show (_candidate_0_table);
+ _candidate_area_1 = _candidate_0_scroll;
+
+ /* Create more button */
+ _more_btn = edje_object_add (evas_object_evas_get (_candidate_window));
+ if (_ise_width == 0 && _ise_height == 0)
+ edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "close_button");
+ else
+ edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "more_button");
+ evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1]);
+ evas_object_resize (_more_btn, 80 * _width_rate, 64 * _height_rate);
+ evas_object_event_callback_add (_more_btn, EVAS_CALLBACK_MOUSE_UP, ui_candidate_window_more_button_cb, NULL);
+
+ /* Add scroller background */
+ _candidate_scroll_width = _candidate_scroll_width_min;
+ _scroller_bg = edje_object_add (evas_object_evas_get (_candidate_window));
+ edje_object_file_set (_scroller_bg, _candidate_edje_file.c_str (), "scroller_bg");
+ evas_object_size_hint_weight_set (_scroller_bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
+ evas_object_move (_scroller_bg, 0, _candidate_port_height_min);
+
+ /* Create vertical scroller */
+ _candidate_scroll = elm_scroller_add (_candidate_window);
+ elm_scroller_bounce_set (_candidate_scroll, 0, 1);
+ elm_scroller_policy_set (_candidate_scroll, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
+ evas_object_resize (_candidate_scroll, _candidate_scroll_width, _candidate_scroll_height_max);
+ evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
+ elm_scroller_page_size_set (_candidate_scroll, 0, _item_min_height+_v_padding);
+ evas_object_move (_candidate_scroll, 0, _candidate_port_height_min);
+ _candidate_table = elm_table_add (_candidate_window);
+ evas_object_size_hint_weight_set (_candidate_table, 0.0, 0.0);
+ evas_object_size_hint_align_set (_candidate_table, 0.0, 0.0);
+ elm_table_padding_set (_candidate_table, 0, 0);
+ elm_object_content_set (_candidate_scroll, _candidate_table);
+ evas_object_show (_candidate_table);
+ _candidate_area_2 = _candidate_scroll;
+
+ /* Create close button */
+ _close_btn = edje_object_add (evas_object_evas_get (_candidate_window));
+ if (_ise_width == 0 && _ise_height == 0)
+ edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "more_button");
+ else
+ edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "close_button");
+ evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1]);
+ evas_object_resize (_close_btn, 80 * _width_rate, 64 * _height_rate);
+ evas_object_event_callback_add (_close_btn, EVAS_CALLBACK_MOUSE_UP, ui_candidate_window_close_button_cb, NULL);
+
+ _tmp_candidate_text = evas_object_text_add (evas_object_evas_get (_candidate_window));
+ evas_object_text_font_set (_tmp_candidate_text, _candidate_font_name.c_str (), _candidate_font_size);
+
+ /* Create aux */
+ _aux_area = elm_scroller_add (_candidate_window);
+ elm_scroller_bounce_set (_aux_area, 1, 0);
+ elm_scroller_policy_set (_aux_area, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
+ evas_object_resize (_aux_area, _aux_port_width, _aux_height);
+ evas_object_move (_aux_area, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
+
+ _aux_table = elm_table_add (_candidate_window);
+ elm_object_content_set (_aux_area, _aux_table);
+ elm_table_padding_set (_aux_table, 0, 0);
+ evas_object_size_hint_weight_set (_aux_table, 0.0, 0.0);
+ evas_object_size_hint_align_set (_aux_table, 0.0, 0.0);
+ evas_object_show (_aux_table);
+
+ _aux_line = edje_object_add (evas_object_evas_get (_candidate_window));
+ edje_object_file_set (_aux_line, _candidate_edje_file.c_str (), "popup_line");
+ evas_object_resize (_aux_line, _candidate_port_width, 2);
+ evas_object_move (_aux_line, 0, _aux_height + 2);
+
+ _tmp_aux_text = evas_object_text_add (evas_object_evas_get (_candidate_window));
+ evas_object_text_font_set (_tmp_aux_text, _candidate_font_name.c_str (), _aux_font_size);
+ }
+
+ flush_memory ();
+}
+
+/**
+ * @brief Create candidate window.
+ *
+ * @return void
+ */
+static void ui_create_candidate_window (void)
+{
+ check_time ("\nEnter ui_create_candidate_window");
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ ui_destroy_candidate_window ();
+
+ _candidate_x = 0;
+ _candidate_y = 0;
+ _candidate_angle = 0;
+
+ ui_create_native_candidate_window ();
+
+ unsigned int set = 1;
+ // FIXME:
+
+ int angle = efl_get_angle_for_app_window ();
+ if (_candidate_angle != angle) {
+ _candidate_angle = angle;
+ ui_candidate_window_rotate (angle);
+ } else {
+ ui_settle_candidate_window ();
+ }
+
+ check_time ("Exit ui_create_candidate_window");
+}
+
+/**
+ * @brief Destroy candidate window.
+ *
+ * @return void
+ */
+static void ui_destroy_candidate_window (void)
+{
+ check_time ("Enter ui_destroy_candidate_window");
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ /* Delete candidate items, popup lines and seperator items */
+ for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
+ if (_candidate_0 [i]) {
+ evas_object_del (_candidate_0 [i]);
+ _candidate_0 [i] = NULL;
+ }
+ if (_candidate_items [i]) {
+ evas_object_del (_candidate_items [i]);
+ _candidate_items [i] = NULL;
+ }
+
+ if (_seperate_0 [i]) {
+ evas_object_del (_seperate_0 [i]);
+ _seperate_0 [i] = NULL;
+ }
+ if (_seperate_items [i]) {
+ evas_object_del (_seperate_items [i]);
+ _seperate_items [i] = NULL;
+ }
+
+ if (_line_0 [i]) {
+ evas_object_del (_line_0 [i]);
+ _line_0 [i] = NULL;
+ }
+ if (_line_items [i]) {
+ evas_object_del (_line_items [i]);
+ _line_items [i] = NULL;
+ }
+ }
+
+ _aux_items.clear ();
+ _aux_seperates.clear ();
+ /* Delete candidate window */
+ if (_candidate_window) {
+ LOGD ("calling ui_candidate_hide (true)");
+ ui_candidate_hide (true);
+
+ evas_object_del (_candidate_window);
+ _candidate_window = NULL;
+ _aux_area = NULL;
+ _candidate_area_1 = NULL;
+ _candidate_area_2 = NULL;
+ _scroller_bg = NULL;
+ }
+
+ if (_preedit_window) {
+ evas_object_del (_preedit_text);
+ _preedit_text = NULL;
+
+ evas_object_hide (_preedit_window);
+ evas_object_del (_preedit_window);
+ _preedit_window = NULL;
+ }
+
+ flush_memory ();
+ check_time ("Exit ui_destroy_candidate_window");
+}
+
+/**
+ * @brief Settle candidate window position.
+ */
+static void ui_settle_candidate_window (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ if (!_candidate_window)
+ return;
+
+ /* If both ISE and candidate window are going to be hidden,
+ let's just not move our candidate window */
+ if (_ise_state == WINDOW_STATE_WILL_HIDE && _candidate_state == WINDOW_STATE_WILL_HIDE)
+ return;
+
+ int spot_x, spot_y;
+ int x, y, width, height;
+ int pos_x = 0, pos_y = 0, ise_width = 0, ise_height = 0;
+ bool get_geometry_result = false;
+ bool reverse = false;
+
+ /* Get candidate window position */
+ ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
+
+ //FIXME: Ecore_X dependency.
+
+ if ((_ise_state != WINDOW_STATE_SHOW && _ise_state != WINDOW_STATE_WILL_HIDE) ||
+ get_geometry_result == false) {
+ ise_height = 0;
+ ise_width = 0;
+ }
+
+ int height2 = ui_candidate_get_valid_height ();
+
+ if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
+ if (_candidate_angle == 90) {
+ spot_x = _screen_width - ise_height - height2;
+ spot_y = 0;
+ } else if (_candidate_angle == 270) {
+ spot_x = ise_height - (_candidate_height - height2);
+ spot_y = 0;
+ } else if (_candidate_angle == 180) {
+ spot_x = 0;
+ spot_y = ise_height - (_candidate_height - height2);
+ } else {
+ spot_x = 0;
+ spot_y = _screen_height - ise_height - height2;
+ }
+ } else {
+ spot_x = _spot_location_x;
+ spot_y = _spot_location_y;
+
+ rectinfo ise_rect = {0, 0, ise_width, ise_height};
+ if (_candidate_angle == 90 || _candidate_angle == 270) {
+ if (ise_rect.height <= (uint32)0 || ise_rect.height >= (uint32)_screen_width)
+ ise_rect.height = ISE_DEFAULT_HEIGHT_LANDSCAPE * _width_rate;
+ } else {
+ if (ise_rect.height <= (uint32)0 || ise_rect.height >= (uint32) _screen_height)
+ ise_rect.height = ISE_DEFAULT_HEIGHT_PORTRAIT * _height_rate;
+ }
+
+ int nOffset = _candidate_port_height_min / 3;
+ if (_candidate_angle == 270) {
+ if (ise_rect.height > 0 && spot_y + height2 > _screen_width - (int)ise_rect.height + nOffset) {
+ reverse = true;
+ spot_x = _screen_width - _spot_location_top_y - (_candidate_height - height2);
+ } else {
+ spot_x = _screen_width - _spot_location_y - _candidate_height;
+ }
+ } else if (_candidate_angle == 90) {
+ if (ise_rect.height > 0 && spot_y + height2 > _screen_width - (int)ise_rect.height + nOffset) {
+ reverse = true;
+ spot_x = _spot_location_top_y - height2;
+ } else {
+ spot_x = spot_y;
+ }
+ } else if (_candidate_angle == 180) {
+ if (ise_rect.height > 0 && spot_y + height2 > _screen_height - (int)ise_rect.height + nOffset) {
+ reverse = true;
+ spot_y = _screen_height - _spot_location_top_y - (_candidate_height - height2);
+ } else {
+ spot_y = _screen_height - _spot_location_y - _candidate_height;
+ }
+ } else {
+ if (ise_rect.height > 0 && spot_y + height2 > _screen_height - (int)ise_rect.height + nOffset) {
+ reverse = true;
+ spot_y = _spot_location_top_y - height2;
+ } else {
+ spot_y = spot_y;
+ }
+ }
+ }
+ if (_candidate_angle == 90) {
+ spot_y = (_screen_height - _candidate_width) / 2;
+ spot_x = spot_x < _indicator_height ? _indicator_height : spot_x;
+ if (spot_x > _screen_width - _candidate_height)
+ spot_x = _screen_width - _candidate_height;
+ } else if (_candidate_angle == 270) {
+ spot_y = (_screen_height - _candidate_width) / 2;
+ spot_x = spot_x < 0 ? 0 : spot_x;
+ if (spot_x > _screen_width - (_indicator_height+_candidate_height))
+ spot_x = _screen_width - (_indicator_height+_candidate_height);
+ } else if (_candidate_angle == 180) {
+ spot_x = (_screen_width - _candidate_width) / 2;
+ spot_y = spot_y < 0 ? 0 : spot_y;
+ if (spot_y > _screen_height - (_indicator_height+_candidate_height))
+ spot_y = _screen_height - (_indicator_height+_candidate_height);
+ } else {
+ spot_x = (_screen_width - _candidate_width) / 2;
+ spot_y = spot_y < _indicator_height ? _indicator_height : spot_y;
+ if (spot_y > _screen_height - _candidate_height)
+ spot_y = _screen_height - _candidate_height;
+ }
+
+ if (spot_x != x || spot_y != y) {
+ _candidate_x = spot_x;
+ _candidate_y = spot_y;
+ evas_object_move (_candidate_window, spot_x, spot_y);
+ LOGD ("Moving candidate window to : %d %d", spot_x, spot_y);
+ if (_preedit_window) {
+ if (_candidate_angle == 90) {
+ spot_x -= _preedit_height;
+ spot_y = _screen_height - _preedit_width;
+ } else if (_candidate_angle == 270) {
+ spot_x += height2;
+ } else if (_candidate_angle == 180) {
+ spot_x = _screen_width - _preedit_width;
+ spot_y += height2;
+ } else {
+ spot_y -= _preedit_height;
+ }
+ evas_object_move (_preedit_window, spot_x, spot_y);
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+// End of Candidate Functions
+//////////////////////////////////////////////////////////////////////
+
+/**
+ * @brief Set transient for app window.
+ *
+ * @param window The Ecore_X_Window handler of app window.
+ */
+static void efl_set_transient_for_app_window (Ecore_X_Window window)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ /* Set a transient window for window stack */
+ //FIXME:
+}
+
+/**
+ * @brief Get angle for app window.
+ *
+ * @param win_obj The Evas_Object handler of application window.
+ *
+ * @return The angle of app window.
+ */
+static int efl_get_angle_for_app_window ()
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ int ret;
+ int count;
+ int angle = 0;
+ unsigned char *prop_data = NULL;
+
+ //FIXME:
+
+ return angle;
+}
+
+/**
+ * @brief Get angle for ise window.
+ *
+ * @param win_obj The Evas_Object handler of ise window.
+ *
+ * @return The angle of ise window.
+ */
+static int efl_get_angle_for_ise_window ()
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ int ret;
+ int count;
+ int angle = 0;
+ unsigned char *prop_data = NULL;
+
+ //FIXME:
+
+ return angle;
+}
+
+/**
+ * @brief Set showing effect for application window.
+ *
+ * @param win The Evas_Object handler of application window.
+ * @param strEffect The pointer of effect string.
+ */
+static void efl_set_showing_effect_for_app_window (Evas_Object *win, const char* strEffect)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+ //FIXME:
+}
+
+/**
+ * @brief Create elementary window.
+ *
+ * @param strWinName The window name.
+ * @param strEffect The window effect string.
+ *
+ * @return The window pointer
+ */
+static Evas_Object *efl_create_window (const char *strWinName, const char *strEffect)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ Evas_Object *win = elm_win_add (NULL, strWinName, ELM_WIN_UTILITY);
+ elm_win_title_set (win, strWinName);
+
+ /* set window properties */
+ elm_win_autodel_set (win, EINA_TRUE);
+ elm_object_focus_allow_set (win, EINA_FALSE);
+ elm_win_borderless_set (win, EINA_TRUE);
+ elm_win_alpha_set (win, EINA_TRUE);
+ elm_win_prop_focus_skip_set (win, EINA_TRUE);
+ efl_set_showing_effect_for_app_window (win, strEffect);
+
+ //const char *szProfile[] = {"mobile", ""};
+ //elm_win_profiles_set (win, szProfile, 1);
+
+ return win;
+}
+
+/**
+ * @brief Create elementary control window.
+ *
+ * @return EINA_TRUE if successful, otherwise return EINA_FALSE
+ */
+static Eina_Bool efl_create_control_window (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ /* WMSYNC, #1 Creating and registering control window */
+ // FIXME:
+ return EINA_TRUE;
+}
+
+/**
+ * @brief Get screen resolution.
+ *
+ * @param width The screen width.
+ * @param height The screen height.
+ */
+static void efl_get_screen_resolution (int &width, int &height)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ width = 720;
+ height = 1280;
+}
+
+//////////////////////////////////////////////////////////////////////
+// Start of PanelAgent Functions
+//////////////////////////////////////////////////////////////////////
+
+/**
+ * @brief Initialize panel agent.
+ *
+ * @param config The config string for PanelAgent.
+ * @param display The current display.
+ * @param resident The variable indicates whether panel will be resident.
+ *
+ * @return true if initialize is successful, otherwise return false.
+ */
+static bool initialize_panel_agent (const String &config, const String &display, bool resident)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ _panel_agent = new PanelAgent ();
+
+ if (!_panel_agent || !_panel_agent->initialize (config, display, resident))
+ return false;
+
+ _panel_agent->signal_connect_reload_config (slot (slot_reload_config));
+ _panel_agent->signal_connect_focus_in (slot (slot_focus_in));
+ _panel_agent->signal_connect_focus_out (slot (slot_focus_out));
+ _panel_agent->signal_connect_expand_candidate (slot (slot_expand_candidate));
+ _panel_agent->signal_connect_contract_candidate (slot (slot_contract_candidate));
+ _panel_agent->signal_connect_set_candidate_ui (slot (slot_set_candidate_style));
+ _panel_agent->signal_connect_update_factory_info (slot (slot_update_factory_info));
+ _panel_agent->signal_connect_update_spot_location (slot (slot_update_spot_location));
+ _panel_agent->signal_connect_update_input_context (slot (slot_update_input_context));
+ _panel_agent->signal_connect_update_ise_geometry (slot (slot_update_ise_geometry));
+ _panel_agent->signal_connect_show_preedit_string (slot (slot_show_preedit_string));
+ _panel_agent->signal_connect_show_aux_string (slot (slot_show_aux_string));
+ _panel_agent->signal_connect_show_lookup_table (slot (slot_show_candidate_table));
+ _panel_agent->signal_connect_hide_preedit_string (slot (slot_hide_preedit_string));
+ _panel_agent->signal_connect_hide_aux_string (slot (slot_hide_aux_string));
+ _panel_agent->signal_connect_hide_lookup_table (slot (slot_hide_candidate_table));
+ _panel_agent->signal_connect_update_preedit_string (slot (slot_update_preedit_string));
+ _panel_agent->signal_connect_update_preedit_caret (slot (slot_update_preedit_caret));
+ _panel_agent->signal_connect_update_aux_string (slot (slot_update_aux_string));
+ _panel_agent->signal_connect_update_lookup_table (slot (slot_update_candidate_table));
+ _panel_agent->signal_connect_select_candidate (slot (slot_select_candidate));
+ _panel_agent->signal_connect_get_candidate_geometry (slot (slot_get_candidate_geometry));
+ _panel_agent->signal_connect_get_input_panel_geometry (slot (slot_get_input_panel_geometry));
+ _panel_agent->signal_connect_set_active_ise_by_uuid (slot (slot_set_active_ise));
+ _panel_agent->signal_connect_get_ise_list (slot (slot_get_ise_list));
+ _panel_agent->signal_connect_get_ise_information (slot (slot_get_ise_information));
+ _panel_agent->signal_connect_get_keyboard_ise_list (slot (slot_get_keyboard_ise_list));
+ _panel_agent->signal_connect_get_language_list (slot (slot_get_language_list));
+ _panel_agent->signal_connect_get_all_language (slot (slot_get_all_language));
+ _panel_agent->signal_connect_get_ise_language (slot (slot_get_ise_language));
+ _panel_agent->signal_connect_get_ise_info_by_uuid (slot (slot_get_ise_info));
+ _panel_agent->signal_connect_set_keyboard_ise (slot (slot_set_keyboard_ise));
+ _panel_agent->signal_connect_get_keyboard_ise (slot (slot_get_keyboard_ise));
+ _panel_agent->signal_connect_accept_connection (slot (slot_accept_connection));
+ _panel_agent->signal_connect_close_connection (slot (slot_close_connection));
+ _panel_agent->signal_connect_exit (slot (slot_exit));
+
+ _panel_agent->signal_connect_register_helper_properties (slot (slot_register_helper_properties));
+ _panel_agent->signal_connect_show_ise (slot (slot_show_ise));
+ _panel_agent->signal_connect_hide_ise (slot (slot_hide_ise));
+
+ _panel_agent->signal_connect_will_hide_ack (slot (slot_will_hide_ack));
+
+ _panel_agent->signal_connect_candidate_will_hide_ack (slot (slot_candidate_will_hide_ack));
+ _panel_agent->signal_connect_get_ise_state (slot (slot_get_ise_state));
+
+ std::vector<String> load_ise_list;
+ _panel_agent->get_active_ise_list (load_ise_list);
+
+ return true;
+}
+
+/**
+ * @brief Reload config slot function for PanelAgent.
+ */
+static void slot_reload_config (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ if (!_config.null ())
+ _config->reload ();
+}
+
+/**
+ * @brief Focus in slot function for PanelAgent.
+ */
+static void slot_focus_in (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ ui_candidate_delete_destroy_timer ();
+}
+
+/**
+ * @brief Focus out slot function for PanelAgent.
+ */
+static void slot_focus_out (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+ ui_candidate_delete_destroy_timer ();
+ _destroy_timer = ecore_timer_add (ISF_CANDIDATE_DESTROY_DELAY, ui_candidate_destroy_timeout, NULL);
+}
+
+/**
+ * @brief Expand candidate slot function for PanelAgent.
+ */
+static void slot_expand_candidate (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+ if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
+ return;
+
+ if (_candidate_area_2 && !_candidate_area_2_visible)
+ ui_candidate_window_more_button_cb (NULL, NULL, NULL, NULL);
+}
+
+/**
+ * @brief Contract candidate slot function for PanelAgent.
+ */
+static void slot_contract_candidate (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
+ return;
+
+ ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
+}
+
+/**
+ * @brief Set candidate style slot function for PanelAgent.
+ *
+ * @param portrait_line The displayed line number for portrait.
+ * @param mode The candidate mode.
+ */
+static void slot_set_candidate_style (int portrait_line, int mode)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " display_line:" << portrait_line << " mode:" << mode << "\n";
+ if ((portrait_line != _candidate_port_line) || (mode != _candidate_mode)) {
+ _candidate_mode = (ISF_CANDIDATE_MODE_T)mode;
+ _candidate_port_line = (ISF_CANDIDATE_PORTRAIT_LINE_T)portrait_line;
+
+ if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
+ if (_candidate_window)
+ ui_destroy_candidate_window ();
+
+ return;
+ }
+
+ if (_candidate_window)
+ ui_create_candidate_window ();
+ }
+}
+
+/**
+ * @brief Update keyboard ISE information slot function for PanelAgent.
+ *
+ * @param info The information of current Keyboard ISE.
+ */
+static void slot_update_factory_info (const PanelFactoryInfo &info)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ String ise_name = info.name;
+ String ise_icon = info.icon;
+
+ String old_ise = _panel_agent->get_current_ise_name ();
+ if (old_ise != ise_name) {
+ int hw_kbd_detect = _config->read (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 0);
+ if (hw_kbd_detect && _candidate_window) {
+ ui_destroy_candidate_window ();
+ }
+ }
+
+ TOOLBAR_MODE_T mode = _panel_agent->get_current_toolbar_mode ();
+
+ if (TOOLBAR_HELPER_MODE == mode)
+ ise_name = _names[get_ise_index (_panel_agent->get_current_helper_uuid ())];
+
+ if (ise_name.length () > 0)
+ _panel_agent->set_current_ise_name (ise_name);
+}
+
+/**
+ * @brief Update cursor position slot function for PanelAgent.
+ *
+ * @param x The x position of current cursor.
+ * @param y The bottom y position of current cursor.
+ * @param top_y The top y position of current cursor.
+ */
+static void slot_update_spot_location (int x, int y, int top_y)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ if (x >= 0 && x < _screen_height && y >= 0 && y < _screen_height) {
+ _spot_location_x = x;
+ _spot_location_y = y;
+ _spot_location_top_y = top_y;
+
+ ui_settle_candidate_window ();
+ }
+}
+
+/**
+ * @brief The input context of ISE is changed.
+ *
+ * @param type The event type.
+ * @param value The event value.
+ */
+static void slot_update_input_context (int type, int value)
+{
+}
+
+/**
+ * @brief Update ise geometry.
+ *
+ * @param x The x position in screen.
+ * @param y The y position in screen.
+ * @param width The ISE window width.
+ * @param height The ISE window height.
+ */
+static void slot_update_ise_geometry (int x, int y, int width, int height)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << x << " y:" << y << " width:" << width << " height:" << height << "...\n";
+
+ LOGD ("x : %d , y : %d , width : %d , height : %d", x, y, width, height);
+
+ int hw_kbd_detect = _config->read (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 0);
+ if (hw_kbd_detect)
+ return;
+
+ int old_height = _ise_height;
+
+ _ise_width = width;
+ _ise_height = height;
+
+ if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
+ if (old_height != height) {
+ ui_settle_candidate_window ();
+ }
+ }
+
+ if (old_height != height && _ise_state == WINDOW_STATE_SHOW) {
+ _ise_reported_geometry.valid = true;
+ _ise_reported_geometry.angle = efl_get_angle_for_ise_window ();
+ _ise_reported_geometry.geometry.pos_x = x;
+ _ise_reported_geometry.geometry.pos_y = y;
+ _ise_reported_geometry.geometry.width = width;
+ _ise_reported_geometry.geometry.height = height;
+ set_keyboard_geometry_atom_info (_app_window, _ise_reported_geometry.geometry);
+ _panel_agent->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
+ }
+}
+
+/**
+ * @brief Show preedit slot function for PanelAgent.
+ */
+static void slot_show_preedit_string (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+ if (_preedit_window == NULL) {
+ ui_create_preedit_window ();
+ int angle = efl_get_angle_for_app_window ();
+ elm_win_rotation_with_resize_set (_preedit_window, angle);
+
+ /* Move preedit window according to candidate window position */
+ if (_candidate_window) {
+ /* Get candidate window position */
+ int x, y, width, height;
+ ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
+
+ int height2 = ui_candidate_get_valid_height ();
+ if (angle == 90) {
+ x -= _preedit_height;
+ y = _screen_height - _preedit_width;
+ } else if (_candidate_angle == 270) {
+ x += height2;
+ } else if (_candidate_angle == 180) {
+ x = _screen_width - _preedit_width;
+ y += height2;
+ } else {
+ y -= _preedit_height;
+ }
+ evas_object_move (_preedit_window, x, y);
+ }
+ }
+
+ if (evas_object_visible_get (_preedit_window))
+ return;
+
+ slot_show_candidate_table ();
+ evas_object_show (_preedit_window);
+}
+
+/**
+ * @brief Show aux slot function for PanelAgent.
+ */
+static void slot_show_aux_string (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+ if (_candidate_window == NULL)
+ ui_create_candidate_window ();
+
+ if (_aux_area == NULL || _aux_area_visible)
+ return;
+
+ evas_object_show (_aux_area);
+ _aux_area_visible = true;
+ ui_candidate_window_adjust ();
+
+ LOGD ("calling ui_candidate_show ()");
+ ui_candidate_show ();
+ ui_settle_candidate_window ();
+}
+
+/**
+ * @brief Show candidate table slot function for PanelAgent.
+ */
+static void slot_show_candidate_table (void)
+{
+ int feedback_result = 0;
+
+ if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
+ _panel_agent->helper_candidate_show ();
+ return;
+ }
+
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+ if (_candidate_window == NULL)
+ ui_create_candidate_window ();
+
+ if (_candidate_state == WINDOW_STATE_SHOW &&
+ (_candidate_area_1_visible || _candidate_area_2_visible)) {
+ efl_set_transient_for_app_window (elm_win_xwindow_get (_candidate_window));
+ return;
+ }
+
+ evas_object_show (_candidate_area_1);
+ _candidate_area_1_visible = true;
+ ui_candidate_window_adjust ();
+
+ LOGD ("calling ui_candidate_show ()");
+ ui_candidate_show ();
+ ui_settle_candidate_window ();
+
+#if HAVE_FEEDBACK
+ feedback_result = feedback_initialize ();
+
+ if (FEEDBACK_ERROR_NONE == feedback_result) {
+ LOGD ("Feedback initialize successful");
+ feedback_initialized = true;
+ } else {
+ LOGW ("Feedback initialize fail : %d",feedback_result);
+ feedback_initialized = false;
+ }
+#endif
+}
+
+/**
+ * @brief Hide preedit slot function for PanelAgent.
+ */
+static void slot_hide_preedit_string (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ if (!_preedit_window || !evas_object_visible_get (_preedit_window))
+ return;
+
+ evas_object_hide (_preedit_window);
+}
+
+/**
+ * @brief Hide aux slot function for PanelAgent.
+ */
+static void slot_hide_aux_string (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ if (!_aux_area || !_aux_area_visible)
+ return;
+
+ evas_object_hide (_aux_area);
+ _aux_area_visible = false;
+ elm_scroller_region_show (_aux_area, 0, 0, 10, 10);
+ ui_candidate_window_adjust ();
+
+ LOGD ("calling ui_candidate_hide (false)");
+ ui_candidate_hide (false);
+ ui_settle_candidate_window ();
+
+ if (ui_candidate_can_be_hide ()) {
+ _candidate_show_requested = false;
+ LOGD ("setting _show_can didate_requested to FALSE");
+ }
+}
+
+/**
+ * @brief Hide candidate table slot function for PanelAgent.
+ */
+static void slot_hide_candidate_table (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ int feedback_result = 0;
+
+ if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
+ _panel_agent->helper_candidate_hide ();
+ return;
+ }
+
+ if (!_candidate_area_1 || _candidate_state == WINDOW_STATE_WILL_HIDE)
+ return;
+
+ if (_candidate_area_1_visible || _candidate_area_2_visible) {
+ bool bForce = false;
+ if (_candidate_area_1_visible) {
+ if (_aux_area_visible) {
+ evas_object_hide (_candidate_area_1);
+ _candidate_area_1_visible = false;
+ evas_object_hide (_more_btn);
+ } else {
+ /* Let's not actually hide the _candidate_area_1 object, for the case that
+ even if the application replies CANDIDATE_WILL_HIDE_ACK a little late,
+ it is better to display the previous candidates instead of blank screen */
+ _candidate_area_1_visible = false;
+ bForce = true;
+ }
+ }
+ if (_candidate_area_2_visible) {
+ evas_object_hide (_candidate_area_2);
+ _candidate_area_2_visible = false;
+ evas_object_hide (_scroller_bg);
+ evas_object_hide (_close_btn);
+ _panel_agent->candidate_more_window_hide ();
+ }
+ ui_candidate_window_adjust ();
+
+ LOGD ("calling ui_candidate_hide (%d, true, true)", bForce);
+ ui_candidate_hide (bForce, true, true);
+ ui_settle_candidate_window ();
+ }
+
+#if HAVE_FEEDBACK
+ feedback_result = feedback_deinitialize ();
+
+ if (FEEDBACK_ERROR_NONE == feedback_result)
+ LOGD ("Feedback deinitialize successful");
+ else
+ LOGW ("Feedback deinitialize fail : %d", feedback_result);
+
+ feedback_initialized = false;
+#endif
+
+ if (ui_candidate_can_be_hide ()) {
+ _candidate_show_requested = false;
+ LOGD ("setting _show_can didate_requested to FALSE");
+ }
+}
+
+/**
+ * @brief Update preedit slot function for PanelAgent.
+ *
+ * @param str The new preedit string.
+ * @param attrs The attribute list of new preedit string.
+ */
+static void slot_update_preedit_string (const String &str, const AttributeList &attrs, int caret)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " string=" << str << "\n";
+
+ if (str.length () <= 0)
+ return;
+
+ if (_preedit_window == NULL || !evas_object_visible_get (_preedit_window)) {
+ slot_show_preedit_string ();
+ }
+
+ int x, y, width, height, candidate_width;
+ evas_object_text_text_set (_tmp_preedit_text, str.c_str ());
+ evas_object_geometry_get (_tmp_preedit_text, &x, &y, &width, &height);
+ ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &candidate_width, &height);
+ _preedit_width = (width + ISF_PREEDIT_BORDER * 2) < candidate_width ? (width + ISF_PREEDIT_BORDER * 2) : candidate_width;
+
+ /* Resize preedit window and avoid text blink */
+ int old_width, old_height;
+ evas_object_geometry_get (_preedit_window, &x, &y, &old_width, &old_height);
+ if (old_width < _preedit_width) {
+ evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
+ edje_object_part_text_set (_preedit_text, "preedit", str.c_str ());
+ } else {
+ edje_object_part_text_set (_preedit_text, "preedit", str.c_str ());
+ evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
+ }
+
+ /* Move preedit window */
+ if (_candidate_angle == 90 || _candidate_angle == 180) {
+ ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_preedit_window)), &x, &y, &width, &height);
+ if (_candidate_angle == 90) {
+ y = _screen_height - _preedit_width;
+ } else if (_candidate_angle == 180) {
+ x = _screen_width - _preedit_width;
+ }
+ evas_object_move (_preedit_window, x, y);
+ }
+}
+
+/**
+ * @brief Update caret slot function for PanelAgent.
+ *
+ * @param caret The caret position.
+ */
+static void slot_update_preedit_caret (int caret)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " caret=" << caret << "\n";
+}
+
+/**
+ * @brief Set hightlight text color and background color for edje object.
+ *
+ * @param item The edje object pointer.
+ * @param nForeGround The text color.
+ * @param nBackGround The background color.
+ * @param bSetBack The flag for background color.
+ */
+static void set_highlight_color (Evas_Object *item, uint32 nForeGround, uint32 nBackGround, bool bSetBack)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ int r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3;
+ if (edje_object_color_class_get (item, "text_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3)) {
+ r = SCIM_RGB_COLOR_RED(nForeGround);
+ g = SCIM_RGB_COLOR_GREEN(nForeGround);
+ b = SCIM_RGB_COLOR_BLUE(nForeGround);
+ edje_object_color_class_set (item, "text_color", r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3);
+ }
+ if (bSetBack && edje_object_color_class_get (item, "rect_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3)) {
+ r = SCIM_RGB_COLOR_RED(nBackGround);
+ g = SCIM_RGB_COLOR_GREEN(nBackGround);
+ b = SCIM_RGB_COLOR_BLUE(nBackGround);
+ edje_object_color_class_set (item, "rect_color", r, g, b, 255, r2, g2, b2, a2, r3, g3, b3, a3);
+ }
+}
+
+/**
+ * @brief Update aux slot function for PanelAgent.
+ *
+ * @param str The new aux string.
+ * @param attrs The attribute list of new aux string.
+ */
+static void slot_update_aux_string (const String &str, const AttributeList &attrs)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+ if (_candidate_window == NULL)
+ ui_create_candidate_window ();
+
+ if (!_aux_area || (str.length () <= 0))
+ return;
+
+ if (!_aux_area_visible) {
+ LOGD ("calling ui_candidate_show ()");
+ ui_candidate_show ();
+ slot_show_aux_string ();
+ }
+
+ int x, y, width, height, item_width = 0;
+ unsigned int window_width = 0, count = 0, i;
+
+ Evas_Object *aux_edje = NULL;
+
+ /* Get highlight item index */
+ int aux_index = -1, aux_start = 0, aux_end = 0;
+ String strAux = str;
+ bool bSetBack = false;
+ uint32 nForeGround = SCIM_RGB_COLOR(62, 207, 255);
+ uint32 nBackGround = SCIM_RGB_COLOR(0, 0, 0);
+ for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
+ if (aux_index == -1 && ait->get_type () == SCIM_ATTR_DECORATE) {
+ aux_index = ait->get_value ();
+ } else if (ait->get_type () == SCIM_ATTR_FOREGROUND) {
+ nForeGround = ait->get_value ();
+ } else if (ait->get_type () == SCIM_ATTR_BACKGROUND) {
+ nBackGround = ait->get_value ();
+ bSetBack = true;
+ }
+ }
+
+ std::vector<String> aux_list;
+ scim_split_string_list (aux_list, strAux, '|');
+
+ if (_aux_items.size () > 0) {
+ for (i = 0; i < _aux_items.size (); i++)
+ evas_object_del (_aux_items [i]);
+ _aux_items.clear ();
+ }
+ if (_aux_seperates.size () > 0) {
+ for (i = 0; i < _aux_seperates.size (); i++)
+ evas_object_del (_aux_seperates [i]);
+ _aux_seperates.clear ();
+ }
+
+ int seperate_width = 4;
+ int seperate_height = 52 * _height_rate;
+ Evas *evas = evas_object_evas_get (_candidate_window);
+ for (i = 0; i < aux_list.size (); i++) {
+ if (i > 0) {
+ Evas_Object *seperate_item = edje_object_add (evas);
+ edje_object_file_set (seperate_item, _candidate_edje_file.c_str (), "seperate_line");
+ evas_object_size_hint_min_set (seperate_item, seperate_width, seperate_height);
+ elm_table_pack (_aux_table, seperate_item, 2 * i - 1, 0, 1, 1);
+ evas_object_show (seperate_item);
+ _aux_seperates.push_back (seperate_item);
+ }
+
+ count++;
+ aux_edje = edje_object_add (evas);
+ edje_object_file_set (aux_edje, _candidate_edje_file.c_str (), "aux");
+ edje_object_text_class_set (aux_edje, "aux_text_class", _candidate_font_name.c_str (), _aux_font_size);
+ edje_object_part_text_set (aux_edje, "aux", aux_list [i].c_str ());
+ elm_table_pack (_aux_table, aux_edje, 2 * i, 0, 1, 1);
+ evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_DOWN, ui_mouse_button_pressed_cb, GINT_TO_POINTER ((i << 8) + ISF_EFL_AUX));
+ evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
+ evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_AUX));
+ evas_object_show (aux_edje);
+ _aux_items.push_back (aux_edje);
+/* if (i == (unsigned int)aux_index)
+ edje_object_signal_emit (aux_edje, "aux,state,selected", "aux");
+ else
+ edje_object_signal_emit (aux_edje, "aux,state,unselected", "aux");
+*/
+ evas_object_text_text_set (_tmp_aux_text, aux_list [i].c_str ());
+ evas_object_geometry_get (_tmp_aux_text, &x, &y, &width, &height);
+ item_width = width + 2*_blank_width;
+ item_width = item_width > _item_min_width ? item_width : _item_min_width;
+ evas_object_size_hint_min_set (aux_edje, item_width, _aux_height);
+ if (aux_index == (int)i || (aux_index == -1 && i == 0)) {
+ aux_start = window_width;
+ aux_end = window_width + item_width;
+ }
+ window_width = window_width + item_width + 4;
+ }
+
+ // Set highlight item
+ for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
+ if (ait->get_type () == SCIM_ATTR_DECORATE) {
+ unsigned int index = ait->get_value ();
+ if (index < _aux_items.size ())
+ set_highlight_color (_aux_items [index], nForeGround, nBackGround, bSetBack);
+ }
+ }
+
+ int w, h;
+ elm_scroller_region_get (_aux_area, &x, &y, &w, &h);
+ item_width = aux_end - aux_start;
+ if (item_width > 0) {
+ if (item_width >= w)
+ elm_scroller_region_show (_aux_area, aux_end - w, y, w, h);
+ else if (aux_end > x + w)
+ elm_scroller_region_show (_aux_area, aux_end - w, y, w, h);
+ else if (aux_start < x)
+ elm_scroller_region_show (_aux_area, aux_start, y, w, h);
+ }
+ flush_memory ();
+}
+
+/**
+ * @brief Update candidate/associate table.
+ *
+ * @param table_type The table type.
+ * @param table The lookup table for candidate or associate.
+ */
+static void update_table (int table_type, const LookupTable &table)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " (" << table.get_current_page_size () << ")\n";
+
+ int item_num = table.get_current_page_size ();
+ if (item_num < 0)
+ return;
+
+ String mbs;
+ WideString wcs;
+
+ AttributeList attrs;
+ int i, x, y, width, height, item_0_width = 0;
+
+ int nLast = 0;
+ std::vector<uint32> row_items;
+
+ int seperate_width = 4;
+ int seperate_height = 52 * _height_rate;
+ int line_width = _candidate_scroll_width;
+ int line_height = _v_padding;
+ int total_width = 0;
+ int current_width = 0;
+ int line_0 = 0;
+ int line_count = 0;
+ int more_item_count = 0;
+ int scroll_0_width = _candidate_scroll_0_width_min;
+ int cursor_pos = table.get_cursor_pos ();
+ int cursor_line = 0;
+
+ if (_candidate_angle == 90 || _candidate_angle == 270)
+ scroll_0_width = 1176 * _height_rate;
+ else
+ scroll_0_width = 618 * _width_rate;
+
+ Evas *evas = evas_object_evas_get (_candidate_window);
+ for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
+ if (_candidate_0 [i]) {
+ evas_object_del (_candidate_0 [i]);
+ _candidate_0 [i] = NULL;
+ }
+ if (_seperate_0 [i]) {
+ evas_object_del (_seperate_0 [i]);
+ _seperate_0 [i] = NULL;
+ }
+ if (_candidate_items [i]) {
+ evas_object_del (_candidate_items [i]);
+ _candidate_items [i] = NULL;
+ }
+ if (_seperate_items [i]) {
+ evas_object_del (_seperate_items [i]);
+ _seperate_items [i] = NULL;
+ }
+ if (_line_items [i]) {
+ evas_object_del (_line_items [i]);
+ _line_items [i] = NULL;
+ }
+
+ if (i < item_num) {
+ bool bHighLight = false;
+ bool bSetBack = false;
+ uint32 nForeGround = SCIM_RGB_COLOR(249, 249, 249);
+ uint32 nBackGround = SCIM_RGB_COLOR(0, 0, 0);
+ attrs = table.get_attributes_in_current_page (i);
+ for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
+ if (ait->get_type () == SCIM_ATTR_DECORATE && ait->get_value () == SCIM_ATTR_DECORATE_HIGHLIGHT) {
+ bHighLight = true;
+ nForeGround = SCIM_RGB_COLOR(62, 207, 255);
+ } else if (ait->get_type () == SCIM_ATTR_FOREGROUND) {
+ bHighLight = true;
+ nForeGround = ait->get_value ();
+ } else if (ait->get_type () == SCIM_ATTR_BACKGROUND) {
+ bSetBack = true;
+ nBackGround = ait->get_value ();
+ }
+ }
+
+ wcs = table.get_candidate_in_current_page (i);
+ mbs = utf8_wcstombs (wcs);
+
+ if (!_candidate_0 [i] && total_width <= scroll_0_width) {
+ _candidate_0 [i] = edje_object_add (evas);
+ edje_object_file_set (_candidate_0 [i], _candidate_edje_file.c_str (), _candidate_name.c_str ());
+ edje_object_text_class_set (_candidate_0 [i], "candidate_text_class", _candidate_font_name.c_str (), _candidate_font_size);
+ evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_DOWN, ui_mouse_button_pressed_cb, GINT_TO_POINTER ((i << 8) + ISF_EFL_CANDIDATE_0));
+ evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
+ evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_CANDIDATE_0));
+ evas_object_show (_candidate_0 [i]);
+
+ edje_object_part_text_set (_candidate_0 [i], "candidate", mbs.c_str ());
+ /* Resize _candidate_0 [i] display width */
+ evas_object_text_text_set (_tmp_candidate_text, mbs.c_str ());
+ evas_object_geometry_get (_tmp_candidate_text, &x, &y, &width, &height);
+ item_0_width = width + 2*_blank_width;
+ item_0_width = item_0_width > _item_min_width ? item_0_width : _item_min_width;
+ evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
+ if (bHighLight || bSetBack) {
+ set_highlight_color (_candidate_0 [i], nForeGround, nBackGround, bSetBack);
+ }
+
+ /* Check whether this item is the last one */
+ if (i == item_num - 1) {
+ if (_candidate_angle == 90 || _candidate_angle == 270)
+ scroll_0_width = _candidate_land_width;
+ else
+ scroll_0_width = _candidate_port_width;
+ }
+
+ /* Add first item */
+ if (i == 0) {
+ item_0_width = item_0_width > scroll_0_width ? scroll_0_width : item_0_width;
+ evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
+ elm_table_pack (_candidate_0_table, _candidate_0 [i], 0, 0, item_0_width, _item_min_height);
+ total_width += item_0_width;
+ continue;
+ } else {
+ total_width += (item_0_width + seperate_width);
+ if (total_width <= scroll_0_width) {
+ _seperate_0 [i] = edje_object_add (evas);
+ edje_object_file_set (_seperate_0 [i], _candidate_edje_file.c_str (), "seperate_line");
+ evas_object_size_hint_min_set (_seperate_0 [i], seperate_width, seperate_height);
+ elm_table_pack (_candidate_0_table, _seperate_0 [i],
+ total_width - item_0_width - seperate_width,
+ line_0*(_item_min_height+line_height) + (_item_min_height - seperate_height)/2,
+ seperate_width, seperate_height);
+ evas_object_show (_seperate_0 [i]);
+
+ elm_table_pack (_candidate_0_table, _candidate_0 [i], total_width - item_0_width, line_0*(_item_min_height+line_height), item_0_width, _item_min_height);
+ continue;
+ } else if ((_candidate_angle == 0 || _candidate_angle == 180) &&
+ (_candidate_port_line > 1 && (line_0 + 1) < _candidate_port_line)) {
+ line_0++;
+ scroll_0_width = _candidate_scroll_0_width_min;
+ item_0_width = item_0_width > scroll_0_width ? scroll_0_width : item_0_width;
+ evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
+ elm_table_pack (_candidate_0_table, _candidate_0 [i], 0, line_0*(_item_min_height+line_height), item_0_width, _item_min_height);
+ total_width = item_0_width;
+
+ row_items.push_back (i - nLast);
+ nLast = i;
+ continue;
+ } else {
+ row_items.push_back (i - nLast);
+ nLast = i;
+ }
+ }
+ }
+
+ if (!_candidate_items [i]) {
+ _candidate_items [i] = edje_object_add (evas);
+ edje_object_file_set (_candidate_items [i], _candidate_edje_file.c_str (), _candidate_name.c_str ());
+ edje_object_text_class_set (_candidate_items [i], "candidate_text_class", _candidate_font_name.c_str (), _candidate_font_size);
+ evas_object_event_callback_add (_candidate_items [i], EVAS_CALLBACK_MOUSE_DOWN, ui_mouse_button_pressed_cb, GINT_TO_POINTER ((i << 8) + ISF_EFL_CANDIDATE_ITEMS));
+ evas_object_event_callback_add (_candidate_items [i], EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
+ evas_object_event_callback_add (_candidate_items [i], EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_CANDIDATE_ITEMS));
+ evas_object_show (_candidate_items [i]);
+ }
+ if (bHighLight || bSetBack) {
+ set_highlight_color (_candidate_items [i], nForeGround, nBackGround, bSetBack);
+ }
+ edje_object_part_text_set (_candidate_items [i], "candidate", mbs.c_str ());
+ /* Resize _candidate_items [i] display width */
+ evas_object_text_text_set (_tmp_candidate_text, mbs.c_str ());
+ evas_object_geometry_get (_tmp_candidate_text, &x, &y, &width, &height);
+ item_0_width = width + 2*_blank_width;
+ item_0_width = item_0_width > _item_min_width ? item_0_width : _item_min_width;
+ evas_object_size_hint_min_set (_candidate_items [i], item_0_width, _item_min_height);
+ if (current_width > 0 && current_width + item_0_width > _candidate_scroll_width) {
+ current_width = 0;
+ line_count++;
+
+ row_items.push_back (i - nLast);
+ nLast = i;
+ if (cursor_pos >= i)
+ cursor_line++;
+ }
+ if (current_width == 0 && !_line_items [i]) {
+ _line_items [i] = edje_object_add (evas);
+ edje_object_file_set (_line_items [i], _candidate_edje_file.c_str (), "popup_line");
+ evas_object_size_hint_min_set (_line_items [i], line_width, line_height);
+ x = 0;
+ y = line_count*(_item_min_height+line_height);
+ elm_table_pack (_candidate_table, _line_items [i], x, y, line_width, line_height);
+ evas_object_show (_line_items [i]);
+ }
+ if (current_width != 0 && !_seperate_items [i]) {
+ _seperate_items [i] = edje_object_add (evas);
+ edje_object_file_set (_seperate_items [i], _candidate_edje_file.c_str (), "seperate_line");
+ evas_object_size_hint_min_set (_seperate_items [i], seperate_width, seperate_height);
+ x = current_width;
+ y = line_count*(_item_min_height+line_height) + line_height + (_item_min_height - seperate_height)/2;
+ elm_table_pack (_candidate_table, _seperate_items [i], x, y, seperate_width, seperate_height);
+ evas_object_show (_seperate_items [i]);
+ current_width += seperate_width;
+ }
+ x = current_width;
+ y = line_count*(_item_min_height+line_height) + line_height;
+ elm_table_pack (_candidate_table, _candidate_items [i], x, y, item_0_width, _item_min_height);
+ current_width += item_0_width;
+ more_item_count++;
+ }
+ }
+
+ for (i = 1; i < _candidate_port_line; i++) {
+ if ((_candidate_angle == 0 || _candidate_angle == 180)) {
+ if (_line_0 [i] == NULL) {
+ _line_0 [i] = edje_object_add (evas);
+ edje_object_file_set (_line_0 [i], _candidate_edje_file.c_str (), "popup_line");
+ evas_object_size_hint_min_set (_line_0 [i], line_width, line_height);
+ x = 0;
+ y = i * (_item_min_height + line_height) - line_height;
+ elm_table_pack (_candidate_0_table, _line_0 [i], x, y, line_width, line_height);
+ evas_object_show (_line_0 [i]);
+ }
+
+ // Create blank line
+ if (line_0 + 1 < _candidate_port_line && i > line_0) {
+ int nIndex = item_num + i;
+ nIndex = nIndex < SCIM_LOOKUP_TABLE_MAX_PAGESIZE ? nIndex : SCIM_LOOKUP_TABLE_MAX_PAGESIZE - 1;
+ _seperate_0 [nIndex] = edje_object_add (evas);
+ edje_object_file_set (_seperate_0 [nIndex], _candidate_edje_file.c_str (), "seperate_line");
+ evas_object_size_hint_min_set (_seperate_0 [nIndex], seperate_width, _item_min_height);
+ elm_table_pack (_candidate_0_table, _seperate_0 [nIndex],
+ 0, i*(_item_min_height+line_height), seperate_width, _item_min_height);
+ }
+ } else if (_line_0 [i]) {
+ evas_object_del (_line_0 [i]);
+ _line_0 [i] = NULL;
+ }
+ }
+
+ row_items.push_back (item_num - nLast); /* Add the number of last row */
+ _panel_agent->update_candidate_item_layout (row_items);
+ _panel_agent->update_displayed_candidate_number (item_num - more_item_count);
+ if (more_item_count == 0) {
+ ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
+ evas_object_hide (_more_btn);
+ evas_object_hide (_close_btn);
+ } else if (!_candidate_area_2_visible) {
+ evas_object_show (_more_btn);
+ evas_object_hide (_close_btn);
+ } else {
+ evas_object_hide (_more_btn);
+ evas_object_show (_close_btn);
+ }
+
+ int w, h;
+ elm_scroller_region_get (_candidate_area_2, &x, &y, &w, &h);
+
+ int line_h = _item_min_height + _v_padding;
+ int cursor_y = cursor_line * line_h;
+ if (cursor_y < y) {
+ elm_scroller_region_show (_candidate_area_2, 0, cursor_y, w, h);
+ } else if (cursor_y >= y + h) {
+ elm_scroller_region_show (_candidate_area_2, 0, cursor_y + line_h - h, w, h);
+ }
+
+ flush_memory ();
+}
+
+/**
+ * @brief Update candidate table slot function for PanelAgent.
+ *
+ * @param table The lookup table for candidate.
+ */
+static void slot_update_candidate_table (const LookupTable &table)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ if (_candidate_mode == SOFT_CANDIDATE_WINDOW){
+ _panel_agent->update_helper_lookup_table (table);
+ return ;
+ }
+
+ if (_candidate_window == NULL)
+ ui_create_candidate_window ();
+
+ if (!_candidate_window || table.get_current_page_size () < 0)
+ return;
+
+ update_table (ISF_CANDIDATE_TABLE, table);
+}
+
+/**
+ * @brief Send selected candidate index.
+ *
+ * @param selected candidate string index number.
+ */
+static void slot_select_candidate (int index)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+ _panel_agent->select_candidate (index);
+}
+
+/**
+ * @brief Get candidate geometry slot function for PanelAgent.
+ *
+ * @param info The data is used to store candidate position and size.
+ */
+static void slot_get_candidate_geometry (struct rectinfo &info)
+{
+ int x = 0;
+ int y = 0;
+ int width = 0;
+ int height = 0;
+
+ if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
+ info.pos_x = x;
+ info.pos_y = y;
+ info.width = width;
+ info.height = height;
+ return;
+ }
+
+ if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
+ /* Get candidate window position */
+ /*ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);*/
+ /* Get exact candidate window size */
+ /*int x2, y2;
+ evas_object_geometry_get (_candidate_window, &x2, &y2, &width, &height);*/
+
+ x = _candidate_x;
+ y = _candidate_y;
+ width = _candidate_width;
+ height = _candidate_height;
+ }
+ info.pos_x = x;
+ info.pos_y = y;
+ info.width = width;
+ info.height = height;
+
+ LOGD ("%d %d %d %d", info.pos_x, info.pos_y, info.width, info.height);
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << info.pos_x << " y:" << info.pos_y
+ << " width:" << info.width << " height:" << info.height << "\n";
+}
+
+/**
+ * @brief Get input panel geometry slot function for PanelAgent.
+ *
+ * @param info The data is used to store input panel position and size.
+ */
+static void slot_get_input_panel_geometry (struct rectinfo &info)
+{
+ int hw_kbd_detect = _config->read (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 0);
+ if (hw_kbd_detect) {
+ info.pos_x = 0;
+ info.width = 0;
+ info.height = 0;
+ if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
+ info.width = _candidate_width;
+ info.height = _candidate_height;
+ }
+ int angle = efl_get_angle_for_app_window ();
+ if (angle == 90 || angle == 270)
+ info.pos_y = _screen_width - info.height;
+ else
+ info.pos_y = _screen_height - info.height;
+ } else {
+ info = get_ise_geometry ();
+ if (_ise_state != WINDOW_STATE_SHOW) {
+ info.width = 0;
+ info.height = 0;
+ } else {
+ if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
+ if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
+ int height = ui_candidate_get_valid_height ();
+
+ if ((_candidate_height - height) > _ise_height) {
+ info.pos_y = info.pos_y + info.height - _candidate_height;
+ info.height = _candidate_height;
+ } else {
+ info.pos_y -= height;
+ info.height += height;
+ }
+ }
+ }
+ }
+ }
+
+ LOGD ("%d %d %d %d", info.pos_x, info.pos_y, info.width, info.height);
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << info.pos_x << " y:" << info.pos_y
+ << " width:" << info.width << " height:" << info.height << "\n";
+}
+
+/**
+ * @brief Set active ISE slot function for PanelAgent.
+ *
+ * @param uuid The active ISE's uuid.
+ * @param changeDefault The flag for changeing default ISE.
+ */
+static void slot_set_active_ise (const String &uuid, bool changeDefault)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " (" << uuid << ")\n";
+
+ set_active_ise (uuid);
+}
+
+/**
+ * @brief Get all ISEs list slot function for PanelAgent.
+ *
+ * @param list The list is used to store all ISEs.
+ *
+ * @return true if this operation is successful, otherwise return false.
+ */
+static bool slot_get_ise_list (std::vector<String> &list)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ /* update ise list */
+ bool ret = isf_update_ise_list (ALL_ISE, _config);
+
+ list.clear ();
+ list = _uuids;
+
+ _panel_agent->update_ise_list (list);
+
+ if (ret && _initial_ise_uuid.length () > 0) {
+ String active_uuid = _initial_ise_uuid;
+ String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
+ int hw_kbd_detect = _config->read (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 0);
+ if (std::find (_uuids.begin (), _uuids.end (), default_uuid) == _uuids.end ()) {
+ if (hw_kbd_detect && _modes[get_ise_index (_initial_ise_uuid)] != TOOLBAR_KEYBOARD_MODE) {
+ active_uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
+ }
+ set_active_ise (active_uuid);
+ } else if (!hw_kbd_detect) { // Check whether keyboard engine is installed
+ String IMENGINE_KEY = String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + String ("~other");
+ String keyboard_uuid = _config->read (IMENGINE_KEY, String (""));
+ if (std::find (_uuids.begin (), _uuids.end (), keyboard_uuid) == _uuids.end ()) {
+ active_uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
+ _panel_agent->change_factory (active_uuid);
+ _config->write (IMENGINE_KEY, active_uuid);
+ _config->flush ();
+ }
+ }
+ }
+
+ add_ise_directory_em ();
+ return ret;
+}
+
+/**
+ * @brief Get the ISE's information.
+ *
+ * @param uuid The ISE's uuid.
+ * @param name The ISE's name.
+ * @param language The ISE's language.
+ * @param type The ISE's type.
+ * @param option The ISE's option.
+ *
+ * @return true if this operation is successful, otherwise return false.
+ */
+static bool slot_get_ise_information (String uuid, String &name, String &language, int &type, int &option, String &module_name)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ if (uuid.length () > 0) {
+ for (unsigned int i = 0; i < _uuids.size (); i++) {
+ if (uuid == _uuids[i]) {
+ name = _names[i];
+ language = _langs[i];
+ type = _modes[i];
+ option = _options[i];
+ module_name = "";
+ return true;
+ }
+ }
+ }
+
+ std::cerr << __func__ << " is failed!!!\n";
+ return false;
+}
+
+/**
+ * @brief Get keyboard ISEs list slot function for PanelAgent.
+ *
+ * @param name_list The list is used to store keyboard ISEs.
+ *
+ * @return true if this operation is successful, otherwise return false.
+ */
+static bool slot_get_keyboard_ise_list (std::vector<String> &name_list)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ /* update ise list */
+ bool ret = isf_update_ise_list (ALL_ISE, _config);
+
+ std::vector<String> lang_list, uuid_list;
+ isf_get_all_languages (lang_list);
+ isf_get_keyboard_ises_in_languages (lang_list, uuid_list, name_list, false);
+
+ if (ret)
+ _panel_agent->update_ise_list (uuid_list);
+ return ret;
+}
+
+/**
+ * @brief Get enable languages list slot function for PanelAgent.
+ *
+ * @param list The list is used to store languages.
+ */
+static void slot_get_language_list (std::vector<String> &list)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ String lang_name;
+ MapStringVectorSizeT::iterator iter = _groups.begin ();
+
+ for (; iter != _groups.end (); iter++) {
+ lang_name = scim_get_language_name (iter->first);
+ list.push_back (lang_name);
+ }
+}
+
+/**
+ * @brief Get all languages list slot function for PanelAgent.
+ *
+ * @param lang The list is used to store languages.
+ */
+static void slot_get_all_language (std::vector<String> &lang)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ isf_get_all_languages (lang);
+}
+
+/**
+ * @brief Get specific ISE language list slot function for PanelAgent.
+ *
+ * @param name The ISE name.
+ * @param list The list is used to store ISE languages.
+ */
+static void slot_get_ise_language (char *name, std::vector<String> &list)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ if (name == NULL)
+ return;
+
+ unsigned int num = _names.size ();
+ std::vector<String> list_tmp;
+ list_tmp.clear ();
+ for (unsigned int i = 0; i < num; i++) {
+ if (!strcmp (_names[i].c_str (), name)) {
+ scim_split_string_list (list_tmp, _langs[i], ',');
+ for (i = 0; i < list_tmp.size (); i++)
+ list.push_back (scim_get_language_name (list_tmp[i]));
+ return;
+ }
+ }
+}
+
+/**
+ * @brief Get ISE information slot function for PanelAgent.
+ *
+ * @param uuid The ISE uuid.
+ * @param info The variable is used to store ISE information.
+ *
+ * @return true if this operation is successful, otherwise return false.
+ */
+static bool slot_get_ise_info (const String &uuid, ISE_INFO &info)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ for (unsigned int i = 0; i < _uuids.size (); i++) {
+ if (!uuid.compare (_uuids[i])) {
+ info.uuid = _uuids[i];
+ info.name = _names[i];
+ info.icon = _icons[i];
+ info.lang = _langs[i];
+ info.option = _options[i];
+ info.type = _modes[i];
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * @brief Set keyboard ISE slot function for PanelAgent.
+ *
+ * @param uuid The variable is ISE uuid.
+ */
+static void slot_set_keyboard_ise (const String &uuid)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " uuid = " << uuid << "\n";
+
+ if (uuid.length () <= 0 || std::find (_uuids.begin (), _uuids.end (), uuid) == _uuids.end ())
+ return;
+
+ String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
+ if (_modes[get_ise_index (default_uuid)] == TOOLBAR_KEYBOARD_MODE)
+ return;
+
+ uint32 ise_option = 0;
+ String ise_uuid, ise_name;
+ isf_get_keyboard_ise (_config, ise_uuid, ise_name, ise_option);
+ if (ise_uuid == uuid)
+ return;
+
+ String language = String ("~other");/*scim_get_locale_language (scim_get_current_locale ());*/
+ _config->write (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + language, uuid);
+ _config->flush ();
+ _config->reload ();
+
+ _panel_agent->change_factory (uuid);
+ _panel_agent->reload_config ();
+}
+
+/**
+ * @brief Get current keyboard ISE name and uuid slot function for PanelAgent.
+ *
+ * @param ise_name The variable is used to store ISE name.
+ * @param ise_uuid The variable is used to store ISE uuid.
+ */
+static void slot_get_keyboard_ise (String &ise_name, String &ise_uuid)
+{
+ uint32 ise_option = 0;
+ isf_get_keyboard_ise (_config, ise_uuid, ise_name, ise_option);
+
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " uuid = " << ise_uuid << "\n";
+}
+
+/**
+ * @brief Accept connection slot function for PanelAgent.
+ *
+ * @param fd The file descriptor to connect.
+ */
+static void slot_accept_connection (int fd)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ Ecore_Fd_Handler *panel_agent_read_handler = ecore_main_fd_handler_add (fd, ECORE_FD_READ, panel_agent_handler, NULL, NULL, NULL);
+ _read_handler_list.push_back (panel_agent_read_handler);
+}
+
+/**
+ * @brief Close connection slot function for PanelAgent.
+ *
+ * @param fd The file descriptor to connect.
+ */
+static void slot_close_connection (int fd)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+ int i = 0;
+ std::vector<Ecore_Fd_Handler *>::iterator IterPos;
+
+ for (IterPos = _read_handler_list.begin (); IterPos != _read_handler_list.end (); ++IterPos,++i) {
+ if (ecore_main_fd_handler_fd_get (_read_handler_list[i]) == fd) {
+ ecore_main_fd_handler_del (_read_handler_list[i]);
+ _read_handler_list.erase (IterPos);
+ break;
+ }
+ }
+}
+
+/**
+ * @brief Exit panel process slot function for PanelAgent.
+ */
+static void slot_exit (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ elm_exit ();
+}
+
+static void slot_register_helper_properties (int id, const PropertyList &props)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ /* WMSYNC, #2 Receiving X window ID from ISE */
+ /* FIXME : We should add an API to set window id of ISE */
+}
+
+static void slot_show_ise (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ /* If the candidate was already in SHOW state, respect the current angle */
+ if (_candidate_state != WINDOW_STATE_SHOW) {
+ /* FIXME : Need to check if candidate_angle and window_angle should be left as separated */
+ _candidate_angle = efl_get_angle_for_app_window ();
+ _window_angle = efl_get_angle_for_app_window ();
+ }
+
+ efl_set_transient_for_app_window (_ise_window);
+
+ /* If our ISE was already in SHOW state, skip state transition to WILL_SHOW */
+ if (_ise_state != WINDOW_STATE_SHOW) {
+ _ise_state = WINDOW_STATE_WILL_SHOW;
+ }
+}
+
+static void slot_hide_ise (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ /* Only if we are not already in HIDE state */
+ if (_ise_state != WINDOW_STATE_HIDE) {
+ _ise_state = WINDOW_STATE_WILL_HIDE;
+ }
+ _window_angle = -1;
+
+ if (_candidate_window) {
+ int hw_kbd_detect = _config->read (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 0);
+ if (hw_kbd_detect)
+ ui_candidate_hide (true, true, true);
+ }
+}
+
+static void slot_will_hide_ack (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ /* WMSYNC, #8 Let the Window Manager to actually hide keyboard window */
+ // WILL_HIDE_REQUEST_DONE Ack to WM
+ // FIXME:
+}
+
+static void slot_candidate_will_hide_ack (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ // FIXME:
+}
+
+static void slot_get_ise_state (int &state)
+{
+ if (_ise_state == WINDOW_STATE_SHOW ||
+ (hw_kbd_mode && _candidate_state == WINDOW_STATE_SHOW)) {
+ state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
+ } else {
+ /* Currently we don't have WILL_HIDE / HIDE state distinction in Ecore_IMF */
+ switch (_ise_state) {
+ case WINDOW_STATE_SHOW :
+ state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
+ break;
+ case WINDOW_STATE_WILL_SHOW :
+ state = ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW;
+ break;
+ case WINDOW_STATE_WILL_HIDE :
+ state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
+ break;
+ case WINDOW_STATE_HIDE :
+ state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
+ break;
+ default :
+ state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
+ };
+ }
+ LOGD ("state = %d", state);
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " state = " << state << "\n";
+}
+
+//////////////////////////////////////////////////////////////////////
+// End of PanelAgent-Functions
+//////////////////////////////////////////////////////////////////////
+
+
+/**
+ * @brief Callback function for ecore fd handler.
+ *
+ * @param data The data to pass to this callback.
+ * @param fd_handler The ecore fd handler.
+ *
+ * @return ECORE_CALLBACK_RENEW
+ */
+static Eina_Bool panel_agent_handler (void *data, Ecore_Fd_Handler *fd_handler)
+{
+ if (fd_handler == NULL)
+ return ECORE_CALLBACK_RENEW;
+
+ int fd = ecore_main_fd_handler_fd_get (fd_handler);
+ for (unsigned int i = 0; i < _read_handler_list.size (); i++) {
+ if (fd_handler == _read_handler_list [i]) {
+ if (!_panel_agent->filter_event (fd)) {
+ std::cerr << "_panel_agent->filter_event () is failed!!!\n";
+ ecore_main_fd_handler_del (fd_handler);
+ }
+ return ECORE_CALLBACK_RENEW;
+ }
+ }
+ std::cerr << "panel_agent_handler () has received exception event!!!\n";
+ _panel_agent->filter_exception_event (fd);
+ ecore_main_fd_handler_del (fd_handler);
+ return ECORE_CALLBACK_RENEW;
+}
+
+/**
+ * @brief Handler function for HelperManager input.
+ *
+ * @param data The data to pass to this callback.
+ * @param fd_handler The Ecore Fd handler.
+ *
+ * @return ECORE_CALLBACK_RENEW
+ */
+static Eina_Bool helper_manager_input_handler (void *data, Ecore_Fd_Handler *fd_handler)
+{
+ if (_panel_agent->has_helper_manager_pending_event ()) {
+ if (!_panel_agent->filter_helper_manager_event ()) {
+ std::cerr << "_panel_agent->filter_helper_manager_event () is failed!!!\n";
+ elm_exit ();
+ }
+ } else {
+ std::cerr << "_panel_agent->has_helper_manager_pending_event () is failed!!!\n";
+ elm_exit ();
+ }
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+/**
+ * @brief Callback function for abnormal signal.
+ *
+ * @param sig The signal.
+ */
+static void signalhandler (int sig)
+{
+ SCIM_DEBUG_MAIN (1) << __FUNCTION__ << " Signal=" << sig << "\n";
+
+ elm_exit ();
+}
+
+#if HAVE_VCONF
+/**
+ * @brief Update keyboard ISE name when display language is changed.
+ *
+ * @param module_name The keyboard ISE module name.
+ * @param index The index of _module_names.
+ *
+ * @return true if successful, otherwise return false.
+ */
+static bool update_keyboard_ise_locale (const String module_name, int index)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+ if (module_name.length () <= 0 || module_name == "socket")
+ return false;
+
+ IMEngineFactoryPointer factory;
+ IMEngineModule ime_module;
+ ime_module.load (module_name, _config);
+
+ if (ime_module.valid ()) {
+ for (size_t j = 0; j < ime_module.number_of_factories (); ++j) {
+ try {
+ factory = ime_module.create_factory (j);
+ } catch (...) {
+ factory.reset ();
+ }
+ if (!factory.null ()) {
+ _names[index+j] = utf8_wcstombs (factory->get_name ());
+ factory.reset ();
+ }
+ }
+ ime_module.unload ();
+ } else {
+ std::cerr << module_name << " can not be loaded!!!\n";
+ }
+
+ return true;
+}
+
+/**
+ * @brief Update helper ISE name when display language is changed.
+ *
+ * @param module_name The helper ISE module name.
+ * @param index The index of _module_names.
+ *
+ * @return true if successful, otherwise return false.
+ */
+static bool update_helper_ise_locale (const String module_name, int index)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+ if (module_name.length () <= 0)
+ return false;
+
+ HelperModule helper_module;
+ HelperInfo helper_info;
+ helper_module.load (module_name);
+ if (helper_module.valid ()) {
+ for (size_t j = 0; j < helper_module.number_of_helpers (); ++j) {
+ helper_module.get_helper_info (j, helper_info);
+ _names[index+j] = helper_info.name;
+ }
+ helper_module.unload ();
+ } else {
+ std::cerr << module_name << " can not be loaded!!!\n";
+ }
+
+ return true;
+}
+
+/**
+ * @brief Set language and locale.
+ *
+ * @return void
+ */
+static void set_language_and_locale (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ char *lang_str = vconf_get_str (VCONFKEY_LANGSET);
+
+ if (lang_str) {
+ setenv ("LANG", lang_str, 1);
+ setlocale (LC_MESSAGES, lang_str);
+ free (lang_str);
+ } else {
+ setenv ("LANG", "en_US.utf8", 1);
+ setlocale (LC_MESSAGES, "en_US.utf8");
+ }
+}
+
+/**
+ * @brief Callback function for display language change.
+ *
+ * @param key The key node.
+ * @param data The data to pass to this callback.
+ *
+ * @return void
+ */
+static void display_language_changed_cb (keynode_t *key, void* data)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ set_language_and_locale ();
+
+ /* Update all ISE names according to display language */
+ std::vector<String> module_list;
+ for (unsigned int i = 0; i < _module_names.size (); i++) {
+ if (std::find (module_list.begin (), module_list.end (), _module_names[i]) != module_list.end ())
+ continue;
+ module_list.push_back (_module_names[i]);
+ if (_module_names[i] == String (COMPOSE_KEY_MODULE)) {
+ IMEngineFactoryPointer factory;
+ factory = new ComposeKeyFactory ();
+ _names[i] = utf8_wcstombs (factory->get_name ());
+ factory.reset ();
+ } else if (_modes[i] == TOOLBAR_KEYBOARD_MODE) {
+ update_keyboard_ise_locale (_module_names[i], i);
+ } else if (_modes[i] == TOOLBAR_HELPER_MODE) {
+ update_helper_ise_locale (_module_names[i], i);
+ }
+ }
+ isf_save_ise_information ();
+
+ String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
+ String default_name = _names[get_ise_index (default_uuid)];
+ _panel_agent->set_current_ise_name (default_name);
+ _config->reload ();
+}
+#endif
+
+/**
+ * @brief Start default ISE.
+ *
+ * @return void
+ */
+static void start_default_ise (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
+ if (!set_active_ise (default_uuid)) {
+ std::cerr << __FUNCTION__ << " Failed to launch default ISE(" << default_uuid << ")\n";
+ LOGW ("Failed to launch default ISE (%s)\n", default_uuid.c_str ());
+
+ if (default_uuid != _initial_ise_uuid) {
+ std::cerr << __FUNCTION__ << " Launch initial ISE(" << _initial_ise_uuid << ")\n";
+ if (!set_active_ise (_initial_ise_uuid)) {
+ LOGW ("Failed to launch initial ISE (%s)\n", _initial_ise_uuid.c_str ());
+ } else {
+ LOGD ("Succeed to launch initial ISE (%s)\n", _initial_ise_uuid.c_str ());
+ }
+ }
+ } else {
+ LOGD ("Succeed to launch default ISE (%s)\n", default_uuid.c_str ());
+ }
+}
+
+/**
+ * @brief Check hardware keyboard.
+ *
+ * @return void
+ */
+static void check_hardware_keyboard (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ if (_off_prepare_done_timer) {
+ ecore_timer_del (_off_prepare_done_timer);
+ _off_prepare_done_timer = NULL;
+ }
+
+ unsigned int val = 0;
+
+ _config->write (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 0);
+
+ //FIXME:
+ uint32 option = 0;
+ String uuid, name;
+ String helper_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
+ String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
+
+ /* When switching back to S/W keyboard mode, let's hide candidate window first */
+ LOGD ("calling ui_candidate_hide (true, true, true)");
+ ui_candidate_hide (true, true, true);
+ uuid = helper_uuid.length () > 0 ? helper_uuid : _initial_ise_uuid;
+ hw_kbd_mode = false;
+ _panel_agent->reset_keyboard_ise ();
+
+ set_active_ise (uuid);
+}
+
+/**
+ * @brief : Checks whether the window manager is launched or not
+ * @return true if window manager launched, else false
+ */
+static bool check_wm_ready (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ return true;
+}
+
+/**
+ * @brief : Checks whether the system service is ready or not
+ * @return true if all system service are ready, else false
+ */
+static bool check_system_ready (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ int ret = 0;
+ int val = 0;
+ ret = vconf_get_int (ISF_SYSTEM_APPSERVICE_READY_VCONF, &val);
+
+ LOGD ("ret : %d, val : %d\n", ret, val);
+
+ if (ret == 0 && val >= ISF_SYSTEM_APPSERVICE_READY_STATE) {
+ LOGD ("Appservice was ready\n");
+ return true;
+ } else {
+ /* Register a call back function for checking system ready */
+ if (!_appsvc_callback_regist) {
+ if (vconf_notify_key_changed (ISF_SYSTEM_APPSERVICE_READY_VCONF, launch_default_soft_keyboard, NULL)) {
+ _appsvc_callback_regist = true;
+ }
+
+ if (!_system_ready_timer) {
+ _system_ready_timer = ecore_timer_add (5.0, system_ready_timeout_cb, NULL);
+ }
+ }
+
+ return false;
+ }
+}
+
+static void _launch_default_soft_keyboard (void)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ if (_appsvc_callback_regist)
+ vconf_ignore_key_changed (ISF_SYSTEM_APPSERVICE_READY_VCONF, launch_default_soft_keyboard);
+
+ if (_system_ready_timer) {
+ ecore_timer_del (_system_ready_timer);
+ _system_ready_timer = NULL;
+ }
+
+ /* Start default ISE */
+ start_default_ise ();
+ check_hardware_keyboard ();
+}
+
+/**
+ * @brief : Launches default soft keyboard for performance enhancement (It's not mandatory)
+ */
+static void launch_default_soft_keyboard (keynode_t *key, void* data)
+{
+ SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+
+ /* Soft keyboard will be started when all system service are ready */
+ if (check_system_ready ()) {
+ _launch_default_soft_keyboard ();
+ }
+}
+
+int main (int argc, char *argv [])
+{
+ struct tms tiks_buf;
+ _clock_start = times (&tiks_buf);
+
+ int i;
+ int ret = 0;
+
+ bool daemon = false;
+ bool should_resident = true;
+
+ int new_argc = 0;
+ char **new_argv = new char * [40];
+ ConfigModule *config_module = NULL;
+ String config_name = String ("socket");
+ String display_name = String ();
+
+ Ecore_Fd_Handler *panel_agent_read_handler = NULL;
+ Ecore_Fd_Handler *helper_manager_handler = NULL;
+
+ check_time ("\nStarting ISF WSM EFL...... ");
+ LOGD ("Starting ISF WSM EFL...... \n");
+
+ DebugOutput::disable_debug (SCIM_DEBUG_AllMask);
+ DebugOutput::enable_debug (SCIM_DEBUG_MainMask);
+
+ /* Parse command options */
+ i = 0;
+ while (i < argc) {
+ if (++i >= argc)
+ break;
+
+ if (String ("-c") == argv [i] || String ("--config") == argv [i]) {
+ if (++i >= argc) {
+ std::cerr << "no argument for option " << argv [i-1] << "\n";
+ ret = -1;
+ goto cleanup;
+ }
+ config_name = argv [i];
+ continue;
+ }
+
+ if (String ("-h") == argv [i] || String ("--help") == argv [i]) {
+ std::cout << "Usage: " << argv [0] << " [option]...\n\n"
+ << "The options are: \n"
+ << " --display DISPLAY Run on display DISPLAY.\n"
+ << " -c, --config NAME Uses specified Config module.\n"
+ << " -d, --daemon Run " << argv [0] << " as a daemon.\n"
+ << " -ns, --no-stay Quit if no connected client.\n"
+#if ENABLE_DEBUG
+ << " -v, --verbose LEVEL Enable debug info, to specific LEVEL.\n"
+ << " -o, --output FILE Output debug information into FILE.\n"
+#endif
+ << " -h, --help Show this help message.\n";
+ delete []new_argv;
+ return 0;
+ }
+
+ if (String ("-d") == argv [i] || String ("--daemon") == argv [i]) {
+ daemon = true;
+ continue;
+ }
+
+ if (String ("-ns") == argv [i] || String ("--no-stay") == argv [i]) {
+ should_resident = false;
+ continue;
+ }
+
+ if (String ("-v") == argv [i] || String ("--verbose") == argv [i]) {
+ if (++i >= argc) {
+ std::cerr << "no argument for option " << argv [i-1] << "\n";
+ ret = -1;
+ goto cleanup;
+ }
+ DebugOutput::set_verbose_level (atoi (argv [i]));
+ continue;
+ }
+
+ if (String ("-o") == argv [i] || String ("--output") == argv [i]) {
+ if (++i >= argc) {
+ std::cerr << "No argument for option " << argv [i-1] << "\n";
+ ret = -1;
+ goto cleanup;
+ }
+ DebugOutput::set_output (argv [i]);
+ continue;
+ }
+
+ if (String ("--display") == argv [i]) {
+ if (++i >= argc) {
+ std::cerr << "No argument for option " << argv [i-1] << "\n";
+ ret = -1;
+ goto cleanup;
+ }
+ display_name = argv [i];
+ continue;
+ }
+
+ if (String ("--") == argv [i])
+ break;
+
+ std::cerr << "Invalid command line option: " << argv [i] << "\n";
+ delete []new_argv;
+ return 0;
+ } /* End of command line parsing. */
+
+ new_argv [new_argc ++] = argv [0];
+
+ /* Store the rest argvs into new_argv. */
+ for (++i; i < argc && new_argc < 37; ++i) {
+ new_argv [new_argc ++] = argv [i];
+ }
+
+ /* Make up DISPLAY env. */
+ if (display_name.length ()) {
+ new_argv [new_argc ++] = const_cast <char*> ("--display");
+ new_argv [new_argc ++] = const_cast <char*> (display_name.c_str ());
+
+ setenv ("DISPLAY", display_name.c_str (), 1);
+ }
+
+ new_argv [new_argc] = 0;
+
+ if (!config_name.length ()) {
+ std::cerr << "No Config module is available!\n";
+ ret = -1;
+ goto cleanup;
+ }
+
+ if (config_name != "dummy") {
+ /* Load config module */
+ config_module = new ConfigModule (config_name);
+
+ if (!config_module || !config_module->valid ()) {
+ std::cerr << "Can not load " << config_name << " Config module.\n";
+ ret = -1;
+ goto cleanup;
+ }
+ } else {
+ _config = new DummyConfig ();
+ }
+
+ /* Get current display. */
+ {
+ const char *p = getenv ("DISPLAY");
+ if (p)
+ display_name = String (p);
+ }
+
+ char buf [256];
+ snprintf (buf, sizeof (buf), "config_name=%s display_name=%s", config_name.c_str (), display_name.c_str ());
+ check_time (buf);
+ try {
+ if (!initialize_panel_agent (config_name, display_name, should_resident)) {
+ check_time ("Failed to initialize Panel Agent!");
+ std::cerr << "Failed to initialize Panel Agent!\n";
+ ret = -1;
+ goto cleanup;
+ }
+ } catch (scim::Exception & e) {
+ std::cerr << e.what() << "\n";
+ ret = -1;
+ goto cleanup;
+ }
+ check_time ("initialize_panel_agent");
+
+ /* Create config instance */
+ if (_config.null () && config_module && config_module->valid ())
+ _config = config_module->create_config ();
+ if (_config.null ()) {
+ std::cerr << "Failed to create Config instance from " << config_name << " Config module.\n";
+ ret = -1;
+ goto cleanup;
+ }
+ check_time ("create config instance");
+
+ /* Initialize global variables and pointers for candidate items and etc. */
+ for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; i++) {
+ _candidate_0 [i] = NULL;
+ _candidate_items [i] = NULL;
+ _seperate_0 [i] = NULL;
+ _seperate_items [i] = NULL;
+ _line_0 [i] = NULL;
+ _line_items [i] = NULL;
+ }
+
+ try {
+ _panel_agent->send_display_name (display_name);
+ } catch (scim::Exception & e) {
+ std::cerr << e.what() << "\n";
+ ret = -1;
+ goto cleanup;
+ }
+
+ if (daemon) {
+ check_time ("ISF WSM EFL run as daemon");
+ scim_daemon ();
+ }
+
+ /* Connect the configuration reload signal. */
+ _config->signal_connect_reload (slot (config_reload_cb));
+
+ if (!check_wm_ready ()) {
+ std::cerr << "[ISF-PANEL-EFL] WM ready timeout\n";
+ LOGW ("Window Manager ready timeout\n");
+ } else {
+ LOGD ("Window Manager is in ready state\n");
+ }
+
+ elm_init (argc, argv);
+ check_time ("elm_init");
+
+ //elm_policy_set (ELM_POLICY_THROTTLE, ELM_POLICY_THROTTLE_NEVER);
+
+ if (!efl_create_control_window ()) {
+ LOGW ("Failed to create control window\n");
+ goto cleanup;
+ }
+
+ efl_get_screen_resolution (_screen_width, _screen_height);
+
+ _width_rate = (float)(_screen_width / 720.0);
+ _height_rate = (float)(_screen_height / 1280.0);
+ _blank_width = (int)(_blank_width * _width_rate);
+ _item_min_width = (int)(_item_min_width * _width_rate);
+ _item_min_height = (int)(_item_min_height * _height_rate);
+ _candidate_width = (int)(_candidate_port_width * _width_rate);
+ _candidate_height = (int)(_candidate_port_height_min * _height_rate);
+ _indicator_height = (int)(_indicator_height * _height_rate);
+
+ _aux_font_size = (int)(_aux_font_size * _width_rate);
+ _candidate_font_size = (int)(_candidate_font_size * _width_rate);
+
+ /* Load ISF configuration */
+ load_config ();
+ check_time ("load_config");
+
+ helper_manager_handler = ecore_main_fd_handler_add (_panel_agent->get_helper_manager_id (), ECORE_FD_READ, helper_manager_input_handler, NULL, NULL, NULL);
+ panel_agent_read_handler = ecore_main_fd_handler_add (_panel_agent->get_server_id (), ECORE_FD_READ, panel_agent_handler, NULL, NULL, NULL);
+ _read_handler_list.push_back (panel_agent_read_handler);
+ check_time ("run_panel_agent");
+
+ set_language_and_locale ();
+
+#if HAVE_VCONF
+ /* Add callback function for input language and display language */
+ vconf_notify_key_changed (VCONFKEY_LANGSET, display_language_changed_cb, NULL);
+#endif
+
+ try {
+ /* Update ISE list */
+ std::vector<String> list;
+ slot_get_ise_list (list);
+
+ /* Load initial ISE information */
+ _initial_ise_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_INITIAL_ISE_UUID), String (SCIM_COMPOSE_KEY_FACTORY_UUID));
+
+ /* Launches default soft keyboard when all conditions are satisfied */
+ launch_default_soft_keyboard ();
+ } catch (scim::Exception & e) {
+ std::cerr << e.what () << "\n";
+ }
+
+ // FIXME:
+
+ /* Set elementary scale */
+ if (_screen_width)
+ elm_config_scale_set (_screen_width / 720.0f);
+
+ signal (SIGQUIT, signalhandler);
+ signal (SIGTERM, signalhandler);
+ signal (SIGINT, signalhandler);
+ signal (SIGHUP, signalhandler);
+ signal (SIGABRT, signalhandler);
+
+ check_time ("EFL WSM launch time");
+
+ elm_run ();
+
+ _config->flush ();
+ ret = 0;
+
+ if (helper_manager_handler)
+ ecore_main_fd_handler_del (helper_manager_handler);
+ for (unsigned int ii = 0; ii < _read_handler_list.size (); ++ii) {
+ ecore_main_fd_handler_del (_read_handler_list[ii]);
+ }
+ _read_handler_list.clear ();
+
+#if HAVE_VCONF
+ /* Remove callback function for input language and display language */
+ vconf_ignore_key_changed (VCONFKEY_LANGSET, display_language_changed_cb);
+#endif
+
+cleanup:
+ ui_candidate_delete_check_size_timer ();
+ ui_candidate_delete_longpress_timer ();
+ ui_candidate_delete_destroy_timer ();
+ delete_ise_directory_em ();
+ ui_close_tts ();
+
+ if (!_config.null ())
+ _config.reset ();
+ if (config_module)
+ delete config_module;
+ if (_panel_agent) {
+ try {
+ _panel_agent->stop ();
+ } catch (scim::Exception & e) {
+ std::cerr << "Exception is thrown from _panel_agent->stop (), error is " << e.what () << "\n";
+ }
+ delete _panel_agent;
+ }
+
+ delete []new_argv;
+
+ if (ret == 0) {
+ std::cerr << "Successfully exited.\n";
+ return 0;
+ } else {
+ std::cerr << "Abnormally exited.\n";
+ return -1;
+ }
+}
+
+/*
+vi:ts=4:nowrap:expandtab
+*/
--- /dev/null
+/*
+ * ISF(Input Service Framework)
+ *
+ * ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable.
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * Contact: Yan Wang <yan.wang@intel.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#define Uses_SCIM_CONFIG_PATH
+#define Uses_SCIM_PANEL_AGENT
+#define Uses_SCIM_IMENGINE_MODULE
+#define Uses_SCIM_HELPER_MODULE
+#define Uses_SCIM_COMPOSE_KEY
+
+
+#include <string.h>
+#include "scim.h"
+#include "scim_stl_map.h"
+#include "isf_wsm_utility.h"
+#include "isf_query_utility.h"
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dlog.h>
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Declaration of macro.
+/////////////////////////////////////////////////////////////////////////////
+#ifdef LOG_TAG
+# undef LOG_TAG
+#endif
+#define LOG_TAG "ISF_WSM_EFL"
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Declaration of global variables.
+/////////////////////////////////////////////////////////////////////////////
+MapStringVectorSizeT _groups;
+std::vector<String> _uuids;
+std::vector<String> _names;
+std::vector<String> _module_names;
+std::vector<String> _langs;
+std::vector<String> _icons;
+std::vector<uint32> _options;
+std::vector<TOOLBAR_MODE_T> _modes;
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Declaration of internal variables.
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Declaration of internal functions.
+/////////////////////////////////////////////////////////////////////////////
+static bool add_keyboard_ise_module (const String ise_name, const ConfigPointer &config);
+static bool add_helper_ise_module (const String ise_name);
+
+
+/**
+ * @brief Get all ISEs support languages.
+ *
+ * @param all_langs The list to store all languages.
+ */
+void isf_get_all_languages (std::vector<String> &all_langs)
+{
+ String lang_name;
+
+ for (MapStringVectorSizeT::iterator it = _groups.begin (); it != _groups.end (); ++it) {
+ lang_name = scim_get_language_name_english (it->first);
+ all_langs.push_back (lang_name);
+ }
+}
+
+/**
+ * @brief Get all ISEs for the specific languages.
+ *
+ * @param lang_list The specific languages list.
+ * @param uuid_list The list to store ISEs' UUID.
+ * @param name_list The list to store ISEs' name.
+ */
+void isf_get_all_ises_in_languages (std::vector<String> lang_list, std::vector<String> &uuid_list, std::vector<String> &name_list)
+{
+ String lang_name;
+
+ for (MapStringVectorSizeT::iterator it = _groups.begin (); it != _groups.end (); ++it) {
+ lang_name = scim_get_language_name_english (it->first);
+ if (std::find (lang_list.begin (), lang_list.end (), lang_name) != lang_list.end ()) {
+ for (size_t i = 0; i < it->second.size (); i++) {
+ // Avoid to add the same ISE
+ if (std::find (uuid_list.begin (), uuid_list.end (), _uuids[it->second[i]]) == uuid_list.end ()) {
+ uuid_list.push_back (_uuids[it->second[i]]);
+ name_list.push_back (_names[it->second[i]]);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * @brief Get keyboard ISE
+ *
+ * @param config The config pointer for loading keyboard ISE.
+ * @param ise_uuid The keyboard ISE uuid.
+ * @param ise_name The keyboard ISE name.
+ * @param ise_option The keyboard ISE option.
+ */
+void isf_get_keyboard_ise (const ConfigPointer &config, String &ise_uuid, String &ise_name, uint32 &ise_option)
+{
+ String uuid = config->read (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + String ("~other"), String (""));
+ if (ise_uuid.length () > 0)
+ uuid = ise_uuid;
+ for (unsigned int i = 0; i < _uuids.size (); i++) {
+ if (uuid == _uuids[i]) {
+ ise_uuid = _uuids[i];
+ ise_name = _names[i];
+ ise_option = _options[i];
+ return;
+ }
+ }
+ ise_name = String ("");
+ ise_uuid = String ("");
+}
+
+/**
+ * @brief Get all keyboard ISEs for the specific languages.
+ *
+ * @param lang_list The specific languages list.
+ * @param uuid_list The list to store keyboard ISEs' UUID.
+ * @param name_list The list to store keyboard ISEs' name.
+ * @param bCheckOption The flag to check whether support hardware keyboard.
+ */
+void isf_get_keyboard_ises_in_languages (const std::vector<String> &lang_list,
+ std::vector<String> &uuid_list,
+ std::vector<String> &name_list,
+ bool bCheckOption)
+{
+ String lang_name;
+
+ for (MapStringVectorSizeT::iterator it = _groups.begin (); it != _groups.end (); ++it) {
+ lang_name = scim_get_language_name_english (it->first);
+
+ if (std::find (lang_list.begin (), lang_list.end (), lang_name) != lang_list.end ()) {
+ for (size_t i = 0; i < it->second.size (); i++) {
+ if (_modes[it->second[i]] != TOOLBAR_KEYBOARD_MODE)
+ continue;
+ if (bCheckOption && (_options[it->second[i]] & SCIM_IME_NOT_SUPPORT_HARDWARE_KEYBOARD))
+ continue;
+ if (std::find (uuid_list.begin (), uuid_list.end (), _uuids[it->second[i]]) == uuid_list.end ()) {
+ uuid_list.push_back (_uuids[it->second[i]]);
+ name_list.push_back (_names[it->second[i]]);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * @brief Get all helper ISEs for the specific languages.
+ *
+ * @param lang_list The specific languages list.
+ * @param uuid_list The list to store helper ISEs' UUID.
+ * @param name_list The list to store helper ISEs' name.
+ */
+void isf_get_helper_ises_in_languages (const std::vector<String> &lang_list, std::vector<String> &uuid_list, std::vector<String> &name_list)
+{
+ String lang_name;
+
+ for (MapStringVectorSizeT::iterator it = _groups.begin (); it != _groups.end (); ++it) {
+ lang_name = scim_get_language_name_english (it->first);
+ if (std::find (lang_list.begin (), lang_list.end (), lang_name) != lang_list.end ()) {
+ for (size_t i = 0; i < it->second.size (); i++) {
+
+ if (_modes[it->second[i]]!= TOOLBAR_HELPER_MODE)
+ continue;
+ // Avoid to add the same ISE
+ if (std::find (uuid_list.begin (), uuid_list.end (), _uuids[it->second[i]]) == uuid_list.end ()) {
+ uuid_list.push_back (_uuids[it->second[i]]);
+ name_list.push_back (_names[it->second[i]]);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * @brief Save all ISEs information into cache file.
+ *
+ * @return void
+ */
+void isf_save_ise_information (void)
+{
+ if (_module_names.size () <= 0)
+ return;
+
+ std::vector<ISEINFO> info_list;
+ for (size_t i = 0; i < _module_names.size (); ++i) {
+ if (_module_names[i] == COMPOSE_KEY_MODULE)
+ continue;
+ ISEINFO info;
+ info.name = _names[i];
+ info.uuid = _uuids[i];
+ info.module = _module_names[i];
+ info.language = _langs[i];
+ info.icon = _icons[i];
+ info.mode = _modes[i];
+ info.option = _options[i];
+ info.locales = "";
+ info_list.push_back (info);
+ }
+
+ String user_file_name = String (USER_ENGINE_FILE_NAME);
+ isf_write_ise_info_list (user_file_name.c_str (), info_list);
+}
+
+/**
+ * @brief Load all ISEs to initialize.
+ *
+ * @param type The loading ISE type.
+ * @param config The config pointer for loading keyboard ISE.
+ * @param uuids The ISE uuid list.
+ * @param names The ISE name list.
+ * @param module_names The ISE module name list.
+ * @param langs The ISE language list.
+ * @param icons The ISE icon list.
+ * @param modes The ISE type list.
+ * @param options The ISE option list.
+ */
+void isf_get_factory_list (LOAD_ISE_TYPE type,
+ const ConfigPointer &config,
+ std::vector<String> &uuids,
+ std::vector<String> &names,
+ std::vector<String> &module_names,
+ std::vector<String> &langs,
+ std::vector<String> &icons,
+ std::vector<TOOLBAR_MODE_T> &modes,
+ std::vector<uint32> &options)
+{
+ uuids.clear ();
+ names.clear ();
+ module_names.clear ();
+ langs.clear ();
+ icons.clear ();
+ modes.clear ();
+ options.clear ();
+ _groups.clear ();
+
+ if (type != HELPER_ONLY) {
+ /* Add ComposeKeyFactory first. */
+ IMEngineFactoryPointer factory = new ComposeKeyFactory ();
+ uuids.push_back (factory->get_uuid ());
+ names.push_back (utf8_wcstombs (factory->get_name ()));
+ module_names.push_back (COMPOSE_KEY_MODULE);
+ langs.push_back (isf_get_normalized_language (factory->get_language ()));
+ icons.push_back (factory->get_icon_file ());
+ modes.push_back (TOOLBAR_KEYBOARD_MODE);
+ options.push_back (factory->get_option ());
+ factory.reset ();
+ }
+
+ String user_file_name = String (USER_ENGINE_FILE_NAME);
+ FILE *engine_list_file = fopen (user_file_name.c_str (), "r");
+ if (engine_list_file == NULL) {
+ std::cerr << __func__ << " Failed to open(" << user_file_name << ")\n";
+ return;
+ }
+
+ char buf[MAXLINE];
+ while (fgets (buf, MAXLINE, engine_list_file) != NULL) {
+ ISEINFO info;
+ isf_get_ise_info_from_string (buf, info);
+ if (info.mode == TOOLBAR_HELPER_MODE || type != HELPER_ONLY) {
+ names.push_back (info.name);
+ uuids.push_back (info.uuid);
+ module_names.push_back (info.module);
+ langs.push_back (info.language);
+ icons.push_back (info.icon);
+ modes.push_back (info.mode);
+ options.push_back (info.option);
+ }
+ }
+
+ fclose (engine_list_file);
+}
+
+/**
+ * @brief Load all ISEs information and ISF default languages.
+ *
+ * @param type The load ISE type.
+ * @param config The config pointer for loading keyboard ISE.
+ */
+void isf_load_ise_information (LOAD_ISE_TYPE type, const ConfigPointer &config)
+{
+ /* Load ISE engine info */
+ isf_get_factory_list (type, config, _uuids, _names, _module_names, _langs, _icons, _modes, _options);
+
+ /* Update _groups */
+ std::vector<String> ise_langs;
+ for (size_t i = 0; i < _uuids.size (); ++i) {
+ scim_split_string_list (ise_langs, _langs[i]);
+ for (size_t j = 0; j < ise_langs.size (); j++) {
+ if (std::find (_groups[ise_langs[j]].begin (), _groups[ise_langs[j]].end (), i) == _groups[ise_langs[j]].end ())
+ _groups[ise_langs[j]].push_back (i);
+ }
+ ise_langs.clear ();
+ }
+}
+
+/**
+ * @brief Load one keyboard ISE module.
+ *
+ * @param module_name The keboard ISE module name.
+ * @param config The config pointer for loading keyboard ISE.
+ *
+ * @return true if load module is successful, otherwise return false.
+ */
+static bool add_keyboard_ise_module (const String module_name, const ConfigPointer &config)
+{
+ if (module_name.length () <= 0 || module_name == "socket")
+ return false;
+
+ IMEngineFactoryPointer factory;
+ IMEngineModule ime_module;
+
+ String filename = String (USER_ENGINE_FILE_NAME);
+ FILE *engine_list_file = fopen (filename.c_str (), "a");
+ if (engine_list_file == NULL) {
+ LOGD ("Failed to open %s!!!\n", filename.c_str ());
+ return false;
+ }
+
+ ime_module.load (module_name, config);
+ if (ime_module.valid ()) {
+ for (size_t j = 0; j < ime_module.number_of_factories (); ++j) {
+ try {
+ factory = ime_module.create_factory (j);
+ } catch (...) {
+ factory.reset ();
+ }
+
+ if (!factory.null ()) {
+ if (std::find (_uuids.begin (), _uuids.end (), factory->get_uuid ()) == _uuids.end ()) {
+ String uuid = factory->get_uuid ();
+ String name = utf8_wcstombs (factory->get_name ());
+ String language = isf_get_normalized_language (factory->get_language ());
+ String icon = factory->get_icon_file ();
+ char mode[12];
+ char option[12];
+
+ _uuids.push_back (uuid);
+ _names.push_back (name);
+ _module_names.push_back (module_name);
+ _langs.push_back (language);
+ _icons.push_back (icon);
+ _modes.push_back (TOOLBAR_KEYBOARD_MODE);
+ _options.push_back (factory->get_option ());
+
+ snprintf (mode, sizeof (mode), "%d", (int)TOOLBAR_KEYBOARD_MODE);
+ snprintf (option, sizeof (option), "%d", factory->get_option ());
+
+ String line = isf_combine_ise_info_string (name, uuid, module_name, language,
+ icon, String (mode), String (option), factory->get_locales ());
+ if (fputs (line.c_str (), engine_list_file) < 0) {
+ LOGD ("Failed to write (%s)!!!\n", line.c_str ());
+ break;
+ }
+ }
+ factory.reset ();
+ }
+ }
+ ime_module.unload ();
+ } else {
+ LOGD ("Failed to load (%s)!!!", module_name.c_str ());
+ fclose (engine_list_file);
+ return false;
+ }
+
+ int ret = fclose (engine_list_file);
+ if (ret != 0)
+ LOGD ("Failed to fclose %s!!!\n", filename.c_str ());
+
+ return true;
+}
+
+/**
+ * @brief Load one helper ISE module.
+ *
+ * @param module_name The helper ISE module name.
+ *
+ * @return true if load module is successful, otherwise return false.
+ */
+static bool add_helper_ise_module (const String module_name)
+{
+ if (module_name.length () <= 0)
+ return false;
+
+ HelperModule helper_module;
+ HelperInfo helper_info;
+
+ String filename = String (USER_ENGINE_FILE_NAME);
+ FILE *engine_list_file = fopen (filename.c_str (), "a");
+ if (engine_list_file == NULL) {
+ LOGD ("Failed to open %s!!!\n", filename.c_str ());
+ return false;
+ }
+
+ helper_module.load (module_name);
+ if (helper_module.valid ()) {
+ for (size_t j = 0; j < helper_module.number_of_helpers (); ++j) {
+ helper_module.get_helper_info (j, helper_info);
+ _uuids.push_back (helper_info.uuid);
+ _names.push_back (helper_info.name);
+ _langs.push_back (isf_get_normalized_language (helper_module.get_helper_lang (j)));
+ _module_names.push_back (module_name);
+ _icons.push_back (helper_info.icon);
+ _modes.push_back (TOOLBAR_HELPER_MODE);
+ _options.push_back (helper_info.option);
+
+ char mode[12];
+ char option[12];
+ snprintf (mode, sizeof (mode), "%d", (int)TOOLBAR_HELPER_MODE);
+ snprintf (option, sizeof (option), "%d", helper_info.option);
+
+ String line = isf_combine_ise_info_string (helper_info.name, helper_info.uuid, module_name, isf_get_normalized_language (helper_module.get_helper_lang (j)),
+ helper_info.icon, String (mode), String (option), String (""));
+ if (fputs (line.c_str (), engine_list_file) < 0) {
+ LOGD ("Failed to write (%s)!!!\n", line.c_str ());
+ break;
+ }
+ }
+ helper_module.unload ();
+ } else {
+ LOGD ("Failed to load (%s)!!!", module_name.c_str ());
+ fclose (engine_list_file);
+ return false;
+ }
+
+ int ret = fclose (engine_list_file);
+ if (ret != 0)
+ LOGD ("Failed to fclose %s!!!\n", filename.c_str ());
+
+ return true;
+}
+
+/**
+ * @brief Update ISEs information for ISE is added or removed.
+ *
+ * @param type The load ISE type.
+ * @param config The config pointer for loading keyboard ISE.
+ *
+ * @return true if ISEs list is changed, otherwise return false.
+ */
+bool isf_update_ise_list (LOAD_ISE_TYPE type, const ConfigPointer &config)
+{
+ bool ret = false;
+
+ std::vector<String> helper_list;
+ scim_get_helper_module_list (helper_list);
+
+ std::vector<String> install_modules, uninstall_modules;
+
+ /* Check keyboard ISEs */
+ if (type != HELPER_ONLY) {
+ install_modules.push_back (COMPOSE_KEY_MODULE);
+ std::vector<String> imengine_list;
+ scim_get_imengine_module_list (imengine_list);
+ for (size_t i = 0; i < imengine_list.size (); ++i) {
+ install_modules.push_back (imengine_list [i]);
+ if (std::find (_module_names.begin (), _module_names.end (), imengine_list [i]) == _module_names.end ()) {
+ if (add_keyboard_ise_module (imengine_list [i], config))
+ ret = true;
+ }
+ }
+ }
+
+ /* Check helper ISEs */
+ for (size_t i = 0; i < helper_list.size (); ++i) {
+ install_modules.push_back (helper_list [i]);
+ if (std::find (_module_names.begin (), _module_names.end (), helper_list [i]) == _module_names.end ()) {
+ if (add_helper_ise_module (helper_list [i]))
+ ret = true;
+ }
+ }
+
+ /* Try to find uninstall ISEs */
+ bool bFindUninstall = false;
+ for (size_t i = 0; i < _module_names.size (); ++i) {
+ if (std::find (install_modules.begin (), install_modules.end (), _module_names [i]) == install_modules.end ()) {
+ ret = true;
+ bFindUninstall = true;
+ /* Avoid to add the same module */
+ if (std::find (uninstall_modules.begin (), uninstall_modules.end (), _module_names [i]) == uninstall_modules.end ()) {
+ uninstall_modules.push_back (_module_names [i]);
+ String filename = String (USER_ENGINE_FILE_NAME);
+ if (isf_remove_ise_info_from_file (filename.c_str (), _module_names [i].c_str ()) == false)
+ LOGD ("Failed to remove %s from cache file : %s!!!", _module_names [i].c_str (), filename.c_str ());
+ }
+ }
+ }
+ if (bFindUninstall) {
+ std::vector<String> tmp_uuids = _uuids;
+ std::vector<String> tmp_names = _names;
+ std::vector<String> tmp_module_names = _module_names;
+ std::vector<String> tmp_langs = _langs;
+ std::vector<String> tmp_icons = _icons;
+ std::vector<uint32> tmp_options = _options;
+ std::vector<TOOLBAR_MODE_T> tmp_modes = _modes;
+
+ _uuids.clear ();
+ _names.clear ();
+ _module_names.clear ();
+ _langs.clear ();
+ _icons.clear ();
+ _options.clear ();
+ _modes.clear ();
+ _groups.clear ();
+
+ for (size_t i = 0; i < tmp_module_names.size (); ++i) {
+ if (std::find (uninstall_modules.begin (), uninstall_modules.end (), tmp_module_names [i]) == uninstall_modules.end ()) {
+ _uuids.push_back (tmp_uuids [i]);
+ _names.push_back (tmp_names [i]);
+ _module_names.push_back (tmp_module_names [i]);
+ _langs.push_back (tmp_langs [i]);
+ _icons.push_back (tmp_icons [i]);
+ _options.push_back (tmp_options [i]);
+ _modes.push_back (tmp_modes [i]);
+ }
+ }
+ }
+
+ /* Update _groups */
+ if (ret) {
+ std::vector<String> ise_langs;
+ for (size_t i = 0; i < _uuids.size (); ++i) {
+ scim_split_string_list (ise_langs, _langs[i]);
+ for (size_t j = 0; j < ise_langs.size (); j++) {
+ if (std::find (_groups[ise_langs[j]].begin (), _groups[ise_langs[j]].end (), i) == _groups[ise_langs[j]].end ())
+ _groups[ise_langs[j]].push_back (i);
+ }
+ ise_langs.clear ();
+ }
+ }
+
+ return ret;
+}
+
+bool isf_remove_ise_module (const String module_name, const ConfigPointer &config)
+{
+ if (std::find (_module_names.begin (), _module_names.end (), module_name) == _module_names.end ()) {
+ LOGD ("Cannot to find %s!!!", module_name.c_str ());
+ return true;
+ }
+
+ String filename = String (USER_ENGINE_FILE_NAME);
+ if (isf_remove_ise_info_from_file (filename.c_str (), module_name.c_str ())) {
+ isf_get_factory_list (ALL_ISE, config, _uuids, _names, _module_names, _langs, _icons, _modes, _options);
+
+ /* Update _groups */
+ _groups.clear ();
+ std::vector<String> ise_langs;
+ for (size_t i = 0; i < _uuids.size (); ++i) {
+ scim_split_string_list (ise_langs, _langs[i]);
+ for (size_t j = 0; j < ise_langs.size (); j++) {
+ if (std::find (_groups[ise_langs[j]].begin (), _groups[ise_langs[j]].end (), i) == _groups[ise_langs[j]].end ())
+ _groups[ise_langs[j]].push_back (i);
+ }
+ ise_langs.clear ();
+ }
+ return true;
+ } else {
+ LOGD ("Failed to remove %s from cache file : %s!!!", module_name.c_str (), filename.c_str ());
+ return false;
+ }
+}
+
+bool isf_update_ise_module (const String strModulePath, const ConfigPointer &config)
+{
+ bool ret = false;
+ struct stat filestat;
+ stat (strModulePath.c_str (), &filestat);
+ if (!S_ISDIR (filestat.st_mode)) {
+ int begin = strModulePath.find_last_of (SCIM_PATH_DELIM) + 1;
+ String mod_name = strModulePath.substr (begin, strModulePath.find_last_of ('.') - begin);
+ String path = strModulePath.substr (0, strModulePath.find_last_of (SCIM_PATH_DELIM));
+ LOGD ("module_name = %s, path = %s", mod_name.c_str (), path.c_str ());
+
+ if (mod_name.length () > 0 && path.length () > 1) {
+ if (isf_remove_ise_module (mod_name, config)) {
+ String type = path.substr (path.find_last_of (SCIM_PATH_DELIM) + 1);
+ LOGD ("type = %s", type.c_str ());
+ if (type == String ("Helper")) {
+ if (add_helper_ise_module (mod_name))
+ ret = true;
+ } else if (type == String ("IMEngine")) {
+ if (add_keyboard_ise_module (mod_name, config))
+ ret = true;
+ }
+ }
+ } else {
+ LOGD ("%s is not valid so file!!!", strModulePath.c_str ());
+ }
+ }
+
+ /* Update _groups */
+ if (ret) {
+ _groups.clear ();
+ std::vector<String> ise_langs;
+ for (size_t i = 0; i < _uuids.size (); ++i) {
+ scim_split_string_list (ise_langs, _langs[i]);
+ for (size_t j = 0; j < ise_langs.size (); j++) {
+ if (std::find (_groups[ise_langs[j]].begin (), _groups[ise_langs[j]].end (), i) == _groups[ise_langs[j]].end ())
+ _groups[ise_langs[j]].push_back (i);
+ }
+ ise_langs.clear ();
+ }
+ }
+
+ return ret;
+}
+
+/*
+vi:ts=4:nowrap:ai:expandtab
+*/
--- /dev/null
+/*
+ * ISF(Input Service Framework)
+ *
+ * ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable.
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * Contact: Yan Wang <yan.wang@intel.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __ISF_WSM_UTILITY_H
+#define __ISF_WSM_UTILITY_H
+
+using namespace scim;
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Declaration of macro.
+/////////////////////////////////////////////////////////////////////////////
+#define COMPOSE_KEY_MODULE "COMPOSE_KEY_MODULE"
+
+
+#if SCIM_USE_STL_EXT_HASH_MAP
+typedef __gnu_cxx::hash_map <String, std::vector <size_t>, scim_hash_string> MapStringVectorSizeT;
+typedef std::map <String, std::vector <String> > MapStringVectorString;
+typedef std::map <String ,String> MapStringString;
+#elif SCIM_USE_STL_HASH_MAP
+typedef std::hash_map <String, std::vector <size_t>, scim_hash_string> MapStringVectorSizeT;
+typedef std::map <String, std::vector <String> > MapStringVectorString;
+typedef std::map <String ,String> MapStringString;
+#else
+typedef std::map <String, std::vector <size_t> > MapStringVectorSizeT;
+typedef std::map <String, std::vector <String> > MapStringVectorString;
+typedef std::map <String ,String> MapStringString;
+#endif
+
+typedef enum {
+ ALL_ISE = 0,
+ HELPER_ONLY,
+ TYPE_END
+} LOAD_ISE_TYPE;
+
+void isf_get_all_languages (std::vector<String> &all_langs);
+void isf_get_all_ises_in_languages (std::vector<String> lang_list, std::vector<String> &uuid_list, std::vector<String> &name_list);
+
+void isf_get_keyboard_ise (const ConfigPointer &config, String &ise_uuid, String &ise_name, uint32 &ise_option);
+void isf_get_keyboard_ises_in_languages (const std::vector<String> &lang_list, std::vector<String> &uuid_list, std::vector<String> &name_list, bool bCheckOption = true);
+void isf_get_helper_ises_in_languages (const std::vector<String> &lang_list, std::vector<String> &uuid_list, std::vector<String> &name_list);
+
+void isf_save_ise_information (void);
+void isf_load_ise_information (LOAD_ISE_TYPE type, const ConfigPointer &config);
+bool isf_update_ise_list (LOAD_ISE_TYPE type, const ConfigPointer &config);
+bool isf_update_ise_module (const String strModulePath, const ConfigPointer &config);
+
+#endif /* __ISF_WSM_UTILITY_H */
+
+/*
+vi:ts=4:ai:nowrap:expandtab
+*/
@EFL_LIBS@ \
-lstdc++ \
-ltzplatform-config-1.0
+if HAVE_X
+libscim@SCIM_EPOCH@_la_CXXFLAGS += @ECOREX_CFLAGS@
+libscim@SCIM_EPOCH@_la_LDFLAGS += @ECOREX_LIBS@
+endif
libscim@SCIM_EPOCH@_la_LIBADD = libltdlc.la
scim_LDADD = libscim@SCIM_EPOCH@.la
scim_LDFLAGS = @LTLIBINTL@ @EFL_LIBS@ @PRIVILEGE_CONTROL_LIBS@ @VCONF_LIBS@
+if HAVE_X
+scim_CXXFLAGS += @ECOREX_CFLAGS@
+scim_LDFLAGS += @ECOREX_LIBS@
+endif
+
isf_log_SOURCES = isf_log.cpp
isf_log_LDADD = libscim@SCIM_EPOCH@.la
if SCIM_BUILD_GTK_UTILS
scim_helper_launcher_LDADD = libscim@SCIM_EPOCH@.la
scim_helper_launcher_LDFLAGS = @LTLIBINTL@ @PRIVILEGE_CONTROL_LIBS@ @AIL_LIBS@ @EFL_LIBS@
+if HAVE_X
+scim_helper_launcher_CXXFLAGS += @ECOREX_CFLAGS@
+scim_helper_launcher_LDFLAGS += @ECOREX_LIBS@
+endif
+
#define __ISE_CONTEXT_H
#include <Ecore_IMF.h>
+#ifndef WAYLAND
#include <Ecore_X.h>
+#endif
typedef struct {
Ecore_IMF_Input_Panel_Lang language;
Ecore_IMF_Input_Panel_Layout layout;
Ecore_IMF_Input_Panel_Return_Key_Type return_key_type;
+#ifndef WAYLAND
Ecore_X_Window client_window;
+#endif
int imdata_size;
int cursor_pos;
Eina_Bool return_key_disabled;
static inline int __set_dac ()
{
+#ifdef WAYLAND
+ return 0;
+#else
return perm_app_set_privilege("isf", NULL, NULL);
+#endif
}
static inline int __set_smack (char* path)
{
SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
+#ifndef WAYLAND
#ifdef WAIT_WM
int try_count = 0;
while (check_file (ISF_SYSTEM_WM_READY_FILE) == false) {
usleep (ISF_SYSTEM_WAIT_DELAY);
}
#endif
+#endif
return true;
}
#define SCIM_GLOBAL_CONFIG_DISABLED_IMENGINE_FACTORIES "/DisabledIMEngineFactories"
#define SCIM_GLOBAL_CONFIG_SUPPORTED_UNICODE_LOCALES "/SupportedUnicodeLocales"
#define SCIM_GLOBAL_CONFIG_DEFAULT_KEYBOARD_LAYOUT "/DefaultKeyboardLayout"
+#ifdef WAYLAND
+#define SCIM_GLOBAL_CONFIG_DEFAULT_PANEL_PROGRAM "/DefaultPanelProgram2"
+#else
#define SCIM_GLOBAL_CONFIG_DEFAULT_PANEL_PROGRAM "/DefaultPanelProgram"
+#endif
#define SCIM_GLOBAL_CONFIG_DEFAULT_CONFIG_MODULE "/DefaultConfigModule"
#define SCIM_GLOBAL_CONFIG_DEFAULT_SOCKET_FRONTEND_ADDRESS "/DefaultSocketFrontEndAddress"
#define SCIM_GLOBAL_CONFIG_DEFAULT_SOCKET_IMENGINE_ADDRESS "/DefaultSocketIMEngineAddress"
+%bcond_with wayland
Name: isf
Summary: Input Service Framework
Version: 2.4.7424
BuildRequires: pkgconfig(appcore-efl)
BuildRequires: pkgconfig(libprivilege-control)
BuildRequires: pkgconfig(elementary)
-BuildRequires: pkgconfig(utilX)
BuildRequires: pkgconfig(vconf)
+%if %{with wayland}
+BuildRequires: pkgconfig(ecore-wayland)
+BuildRequires: pkgconfig(xkbcommon) >= 0.3.0
+%else
+BuildRequires: pkgconfig(utilX)
%if "%{_repository}" != "wearable"
BuildRequires: pkgconfig(ui-gadget-1)
BuildRequires: pkgconfig(minicontrol-provider)
%endif
+BuildRequires: pkgconfig(x11)
+%endif
BuildRequires: pkgconfig(ecore)
BuildRequires: pkgconfig(edje)
-BuildRequires: pkgconfig(x11)
BuildRequires: pkgconfig(notification)
BuildRequires: pkgconfig(dlog)
BuildRequires: pkgconfig(tts)
CXXFLAGS+=" -D_MOBILE";
%endif
+%if %{with wayland}
+CFLAGS+=" -DWAYLAND"
+CXXFLAGS+=" -DWAYLAND"
+%endif
+
export GC_SECTIONS_FLAGS="-fdata-sections -ffunction-sections -Wl,--gc-sections"
+
+CFLAGS+=" -I/usr/include/elementary-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -I/usr/include/ecore-1 "
+CFLAGS+=" -I/usr/include/evas-1 -I/usr/include/eet-1 -I/usr/include/edje-1 -I/usr/include/e_dbus-1 "
+CFLAGS+=" -I/usr/include/eio-1 -I/usr/include/ethumb-1 -I/usr/include/efreet-1 -I/usr/include/emotion-1 -I/usr/include/embryo-1 "
+CFLAGS+=" -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include/ "
CFLAGS+=" -fvisibility=hidden ${GC_SECTIONS_FLAGS} "; export CFLAGS
+
+CXXFLAGS+=" -I/usr/include/elementary-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -I/usr/include/ecore-1 "
+CXXFLAGS+=" -I/usr/include/evas-1 -I/usr/include/eet-1 -I/usr/include/edje-1 -I/usr/include/e_dbus-1 "
+CXXFLAGS+=" -I/usr/include/eio-1 -I/usr/include/ethumb-1 -I/usr/include/efreet-1 -I/usr/include/emotion-1 -I/usr/include/embryo-1 "
+CXXFLAGS+=" -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include/ "
CXXFLAGS+=" -fvisibility=hidden -fvisibility-inlines-hidden ${GC_SECTIONS_FLAGS} ";export CXXFLAGS
%autogen
%configure --disable-static \
--disable-tray-icon \
--disable-filter-sctc \
+%if %{with wayland}
+ --disable-panel-efl \
+ --disable-setting-efl \
+ --disable-efl-immodule \
+%else
+ --disable-wsm-efl \
+ --disable-wsc-efl \
+%endif
--disable-frontend-x11
make %{?_smp_mflags}
mkdir -p %{buildroot}/opt/apps/scim/lib/scim-1.0/1.4.0/SetupUI
mkdir -p %{buildroot}/opt/apps/scim/lib/scim-1.0/1.4.0/IMEngine
+%if %{with wayland}
+%else
%if "%{_repository}" != "wearable"
install -d %{buildroot}%{_libdir}/systemd/system/graphical.target.wants
install -d %{buildroot}%{_libdir}/systemd/system
install -m0644 %{SOURCE1} %{buildroot}%{_libdir}/systemd/system/
ln -sf ../../system/scim.service %{buildroot}%{_libdir}/systemd/system/graphical.target.wants/scim.service
%endif
+%endif
%find_lang scim
%dir /opt/apps/scim/lib/scim-1.0/1.4.0/Helper
%dir /opt/apps/scim/lib/scim-1.0/1.4.0/SetupUI
%dir /opt/apps/scim/lib/scim-1.0/1.4.0/IMEngine
-%if "%{_repository}" == "wearable"
+%if "%{_repository}" == "wearable" || %{with wayland}
%dir /etc/scim/conf
%{_libdir}/systemd/user/core-efl.target.wants/scim.service
%{_libdir}/systemd/user/scim.service
%{_sysconfdir}/scim/config
%{_datadir}/scim/isf_candidate_theme1.edj
%{_datadir}/scim/icons/*
+%if %{with wayland}
+%{_bindir}/isf-wsm-efl
+%{_bindir}/isf-wsc-efl
+%else
%{_bindir}/isf-demo-efl
+%{_bindir}/isf-panel-efl
+%{_libdir}/*/immodules/*.so
+%endif
%{_bindir}/scim
%{_bindir}/isf-log
-%{_bindir}/isf-panel-efl
%{_bindir}/isf-query-engines
-%{_libdir}/*/immodules/*.so
%{_libdir}/scim-1.0/1.4.0/IMEngine/socket.so
%{_libdir}/scim-1.0/1.4.0/Config/simple.so
%{_libdir}/scim-1.0/1.4.0/Config/socket.so