ecore_imf: Add support for wayland

Add an input method module supporting the Wayland input method protocol.

In v2:
 - Missing call to ecore_wl_shutdown() in im_module_shutdown()
 - Access the already stored 'wayland globals' with ecore_wl_globals_get()
 - Fixed compilation by adding -I(top_srcdir)/src/efl to CFLAGS
 - EFL formatting fixes

Signed-off-by: Eduardo Lima (Etrunko) <eduardo.lima@intel.com>
This commit is contained in:
Jan Arne Petersen 2013-04-17 11:59:46 +02:00 committed by Eduardo Lima (Etrunko)
parent 1f298139d8
commit f656aa397f
7 changed files with 1684 additions and 0 deletions

View File

@ -2771,6 +2771,7 @@ want_ecore_imf="yes"
want_ecore_imf_xim="no"
want_ecore_imf_scim="no"
want_ecore_imf_ibus="no"
want_ecore_imf_wayland="no"
if test "${have_wince}" = "yes"; then
want_ecore_imf="no"
@ -2782,6 +2783,9 @@ else
want_ecore_imf_xim="yes"
want_ecore_imf_scim="yes"
want_ecore_imf_ibus="yes"
if test "${want_wayland}" = "yes"; then
want_ecore_imf_wayland="yes"
fi
fi
fi
@ -2851,6 +2855,20 @@ fi
AM_CONDITIONAL([BUILD_ECORE_IMF_XIM], [test "x${have_ecore_imf_xim}" = "xyes"])
EFL_ADD_FEATURE([ECORE_IMF], [xim])
# wayland
if test "x${want_ecore_imf_wayland}" = "xyes" ; then
PKG_CHECK_MODULES([WAYLAND],
[wayland-client],
[
have_ecore_imf_wayland="yes"
AC_DEFINE([BUILD_ECORE_IMF_WAYLAND], [1], [Ecore Imf Wayland Support])
],
[have_ecore_imf_wayland="no"])
fi
AM_CONDITIONAL([BUILD_ECORE_IMF_WAYLAND], [test "x${have_ecore_imf_wayland}" = "xyes"])
EFL_ADD_FEATURE([ECORE_IMF], [wayland], [${want_ecore_imf_wayland}])
### Checks for header files
### Checks for types

View File

@ -101,3 +101,29 @@ modules_ecore_imf_xim_module_la_DEPENDENCIES = \
modules_ecore_imf_xim_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
modules_ecore_imf_xim_module_la_LIBTOOLFLAGS = --tag=disable-static
endif
# Wayland
if BUILD_ECORE_IMF_WAYLAND
ecoreimfwaylandpkgdir = $(libdir)/ecore_imf/modules/wayland/$(MODULE_ARCH)
ecoreimfwaylandpkg_LTLIBRARIES = modules/ecore_imf/wayland/module.la
modules_ecore_imf_wayland_module_la_SOURCES = \
modules/ecore_imf/wayland/wayland_module.c \
modules/ecore_imf/wayland/wayland_imcontext.c \
modules/ecore_imf/wayland/wayland_imcontext.h \
modules/ecore_imf/wayland/text-client-protocol.h \
modules/ecore_imf/wayland/text-protocol.c
modules_ecore_imf_wayland_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
@ECORE_IMF_CFLAGS@ \
@ECORE_EVAS_CFLAGS@ \
@ECORE_WAYLAND_CFLAGS@
modules_ecore_imf_wayland_module_la_LIBADD = \
@USE_ECORE_IMF_LIBS@ \
@USE_ECORE_EVAS_LIBS@ \
@USE_ECORE_WAYLAND_LIBS@
modules_ecore_imf_wayland_module_la_DEPENDENCIES = \
@USE_ECORE_IMF_INTERNAL_LIBS@ \
@USE_ECORE_EVAS_INTERNAL_LIBS@ \
@USE_ECORE_WAYLAND_INTERNAL_LIBS@
modules_ecore_imf_wayland_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
modules_ecore_imf_wayland_module_la_LIBTOOLFLAGS = --tag=disable-static
endif

View File

@ -0,0 +1,544 @@
/*
* 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 Unicode
* characters.
*
* 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 Unicode characters from index relative to the
* beginning of the composing text (as Unicode character 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 Unicode
* character 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 Unicode characters).
* Length is the length of deleted text (in Unicode characters).
*
* 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

View File

@ -0,0 +1,94 @@
/*
* 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,
};

View File

@ -0,0 +1,778 @@
/*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <Ecore.h>
#include <Ecore_Evas.h>
#include <Ecore_Input.h>
#include <Ecore_Wayland.h>
#include "wayland_imcontext.h"
struct _WaylandIMContext
{
Ecore_IMF_Context *ctx;
struct wl_text_input_manager *text_input_manager;
struct wl_text_input *text_input;
Ecore_Wl_Window *window;
Evas *canvas;
char *preedit_text;
char *preedit_commit;
Eina_List *preedit_attrs;
int32_t preedit_cursor;
struct
{
Eina_List *attrs;
int32_t cursor;
} pending_preedit;
struct
{
int32_t cursor;
int32_t anchor;
uint32_t delete_index;
uint32_t delete_length;
} pending_commit;
struct
{
int x;
int y;
int width;
int height;
} cursor_location;
xkb_mod_mask_t control_mask;
xkb_mod_mask_t alt_mask;
xkb_mod_mask_t shift_mask;
uint32_t serial;
uint32_t reset_serial;
};
static unsigned int
utf8_offset_to_characters(const char *str, int offset)
{
int index = 0;
unsigned int i = 0;
for (; index < offset; i++)
eina_unicode_utf8_next_get(str, &index);
return i;
}
static void
update_state(WaylandIMContext *imcontext)
{
char *surrounding;
int cursor_pos;
Ecore_Evas *ee;
int canvas_x = 0, canvas_y = 0;
if (!imcontext->ctx)
return;
/* cursor_pos is a byte index */
if (ecore_imf_context_surrounding_get(imcontext->ctx, &surrounding, &cursor_pos))
{
wl_text_input_set_surrounding_text(imcontext->text_input,
surrounding,
cursor_pos,
cursor_pos);
free(surrounding);
}
if (imcontext->canvas)
{
ee = ecore_evas_ecore_evas_get(imcontext->canvas);
if (ee)
ecore_evas_geometry_get(ee, &canvas_x, &canvas_y, NULL, NULL);
}
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "canvas (x: %d, y: %d)", canvas_x, canvas_y);
wl_text_input_set_cursor_rectangle(imcontext->text_input,
imcontext->cursor_location.x + canvas_x,
imcontext->cursor_location.y + canvas_y,
imcontext->cursor_location.width,
imcontext->cursor_location.height);
wl_text_input_commit_state(imcontext->text_input, ++imcontext->serial);
}
static Eina_Bool
check_serial(WaylandIMContext *imcontext, uint32_t serial)
{
Ecore_IMF_Preedit_Attr *attr;
if ((imcontext->serial - serial) > (imcontext->serial - imcontext->reset_serial))
{
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
"outdated serial: %u, current: %u, reset: %u",
serial, imcontext->serial, imcontext->reset_serial);
/* Clear pending data */
imcontext->pending_commit.delete_index = 0;
imcontext->pending_commit.delete_length = 0;
imcontext->pending_commit.cursor = 0;
imcontext->pending_commit.anchor = 0;
imcontext->pending_preedit.cursor = 0;
EINA_LIST_FREE(imcontext->pending_preedit.attrs, attr) free(attr);
imcontext->pending_preedit.attrs = NULL;
return EINA_FALSE;
}
return EINA_TRUE;
}
static void
clear_preedit(WaylandIMContext *imcontext)
{
Ecore_IMF_Preedit_Attr *attr;
imcontext->preedit_cursor = 0;
free(imcontext->preedit_text);
imcontext->preedit_text = NULL;
free(imcontext->preedit_commit);
imcontext->preedit_commit = NULL;
EINA_LIST_FREE(imcontext->preedit_attrs, attr)
free(attr);
imcontext->preedit_attrs = NULL;
}
static void
text_input_commit_string(void *data,
struct wl_text_input *text_input EINA_UNUSED,
uint32_t serial,
const char *text)
{
WaylandIMContext *imcontext = (WaylandIMContext *)data;
Eina_Bool old_preedit = EINA_FALSE;
char *surrounding;
int cursor_pos, cursor;
Ecore_IMF_Event_Delete_Surrounding ev;
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
"commit event (text: `%s', current pre-edit: `%s')",
text,
imcontext->preedit_text ? imcontext->preedit_text : "");
old_preedit = imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
if (!imcontext->ctx)
return;
if (!check_serial(imcontext, serial))
return;
if (old_preedit)
{
ecore_imf_context_preedit_end_event_add(imcontext->ctx);
ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
}
clear_preedit(imcontext);
if (imcontext->pending_commit.delete_length > 0)
{
/* cursor_pos is a byte index */
if (ecore_imf_context_surrounding_get(imcontext->ctx, &surrounding, &cursor_pos))
{
ev.ctx = imcontext->ctx;
/* offset and n_chars are in characters */
ev.offset = utf8_offset_to_characters(surrounding, cursor_pos + imcontext->pending_commit.delete_index);
ev.n_chars = utf8_offset_to_characters(surrounding,
cursor_pos + imcontext->pending_commit.delete_index + imcontext->pending_commit.delete_length) - ev.offset;
/* cursor in characters */
cursor = utf8_offset_to_characters(surrounding, cursor_pos);
ev.offset -= cursor;
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
"delete on commit (text: `%s', offset `%d', length: `%d')",
surrounding, ev.offset, ev.n_chars);
ecore_imf_context_delete_surrounding_event_add(imcontext->ctx, ev.offset, ev.n_chars);
ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
}
}
imcontext->pending_commit.delete_index = 0;
imcontext->pending_commit.delete_length = 0;
imcontext->pending_commit.cursor = 0;
imcontext->pending_commit.anchor = 0;
ecore_imf_context_commit_event_add(imcontext->ctx, text);
ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)text);
}
static void
commit_preedit(WaylandIMContext *imcontext)
{
if (!imcontext->preedit_commit)
return;
if (!imcontext->ctx)
return;
ecore_imf_context_commit_event_add(imcontext->ctx, imcontext->preedit_commit);
ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)imcontext->preedit_commit);
}
static void
text_input_preedit_string(void *data,
struct wl_text_input *text_input EINA_UNUSED,
uint32_t serial,
const char *text,
const char *commit)
{
WaylandIMContext *imcontext = (WaylandIMContext *)data;
Eina_Bool old_preedit = EINA_FALSE;
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
"preedit event (text: `%s', current pre-edit: `%s')",
text,
imcontext->preedit_text ? imcontext->preedit_text : "");
if (!check_serial(imcontext, serial))
return;
old_preedit = imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
clear_preedit(imcontext);
imcontext->preedit_text = strdup(text);
imcontext->preedit_commit = strdup(commit);
imcontext->preedit_cursor = utf8_offset_to_characters(text, imcontext->pending_preedit.cursor);
imcontext->preedit_attrs = imcontext->pending_preedit.attrs;
imcontext->pending_preedit.attrs = NULL;
if (!old_preedit)
{
ecore_imf_context_preedit_start_event_add(imcontext->ctx);
ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
}
ecore_imf_context_preedit_changed_event_add(imcontext->ctx);
ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
if (strlen(imcontext->preedit_text) == 0)
{
ecore_imf_context_preedit_end_event_add(imcontext->ctx);
ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
}
}
static void
text_input_delete_surrounding_text(void *data,
struct wl_text_input *text_input EINA_UNUSED,
int32_t index,
uint32_t length)
{
WaylandIMContext *imcontext = (WaylandIMContext *)data;
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
"delete surrounding text (index: %d, length: %u)",
index,
length);
imcontext->pending_commit.delete_index = index;
imcontext->pending_commit.delete_length = length;
}
static void
text_input_cursor_position(void *data,
struct wl_text_input *text_input EINA_UNUSED,
int32_t index,
int32_t anchor)
{
WaylandIMContext *imcontext = (WaylandIMContext *)data;
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
"cursor_position for next commit (index: %d, anchor: %d)",
index,
anchor);
imcontext->pending_commit.cursor = index;
imcontext->pending_commit.anchor = anchor;
}
static void
text_input_preedit_styling(void *data,
struct wl_text_input *text_input EINA_UNUSED,
uint32_t index,
uint32_t length,
uint32_t style)
{
WaylandIMContext *imcontext = (WaylandIMContext *)data;
Ecore_IMF_Preedit_Attr *attr = calloc(1, sizeof(*attr));
switch (style)
{
case WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT:
case WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE:
case WL_TEXT_INPUT_PREEDIT_STYLE_INCORRECT:
case WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT:
case WL_TEXT_INPUT_PREEDIT_STYLE_ACTIVE:
case WL_TEXT_INPUT_PREEDIT_STYLE_INACTIVE:
attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
break;
case WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION:
attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
break;
}
attr->start_index = index;
attr->end_index = index + length;
imcontext->pending_preedit.attrs = eina_list_append(imcontext->pending_preedit.attrs, attr);
}
static void
text_input_preedit_cursor(void *data,
struct wl_text_input *text_input EINA_UNUSED,
int32_t index)
{
WaylandIMContext *imcontext = (WaylandIMContext *)data;
imcontext->pending_preedit.cursor = index;
}
static xkb_mod_index_t
modifiers_get_index(struct wl_array *modifiers_map,
const char *name)
{
xkb_mod_index_t index = 0;
char *p = modifiers_map->data;
while ((const char *)p < ((const char *)modifiers_map->data + modifiers_map->size))
{
if (strcmp(p, name) == 0)
return index;
index++;
p += strlen(p) + 1;
}
return XKB_MOD_INVALID;
}
static xkb_mod_mask_t
modifiers_get_mask(struct wl_array *modifiers_map,
const char *name)
{
xkb_mod_index_t index = modifiers_get_index(modifiers_map, name);
if (index == XKB_MOD_INVALID)
return XKB_MOD_INVALID;
return 1 << index;
}
static void
text_input_modifiers_map(void *data,
struct wl_text_input *text_input EINA_UNUSED,
struct wl_array *map)
{
WaylandIMContext *imcontext = (WaylandIMContext *)data;
imcontext->shift_mask = modifiers_get_mask(map, "Shift");
imcontext->control_mask = modifiers_get_mask(map, "Control");
imcontext->alt_mask = modifiers_get_mask(map, "Mod1");
}
static void
text_input_keysym(void *data,
struct wl_text_input *text_input EINA_UNUSED,
uint32_t serial EINA_UNUSED,
uint32_t time,
uint32_t sym,
uint32_t state,
uint32_t modifiers)
{
WaylandIMContext *imcontext = (WaylandIMContext *)data;
char string[32], key[32], keyname[32];
Ecore_Event_Key *e;
memset(key, 0, sizeof(key));
xkb_keysym_get_name(sym, key, sizeof(key));
memset(keyname, 0, sizeof(keyname));
xkb_keysym_get_name(sym, keyname, sizeof(keyname));
if (keyname[0] == '\0')
snprintf(keyname, sizeof(keyname), "Keysym-%u", sym);
memset(string, 0, sizeof(string));
xkb_keysym_to_utf8(sym, string, 32);
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
"key event (key: %s)",
keyname);
e = malloc(sizeof(Ecore_Event_Key) + strlen(key) + strlen(keyname) + strlen(string) + 3);
if (!e)
return;
e->keyname = (char *)(e + 1);
e->key = e->keyname + strlen(keyname) + 1;
e->string = e->key + strlen(key) + 1;
e->compose = e->string;
strcpy((char *)e->keyname, keyname);
strcpy((char *)e->key, key);
strcpy((char *)e->string, string);
e->window = imcontext->window->id;
e->event_window = imcontext->window->id;
e->timestamp = time;
e->modifiers = 0;
if (modifiers & imcontext->shift_mask)
e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
if (modifiers & imcontext->control_mask)
e->modifiers |= ECORE_EVENT_MODIFIER_CTRL;
if (modifiers & imcontext->alt_mask)
e->modifiers |= ECORE_EVENT_MODIFIER_ALT;
if (state)
ecore_event_add(ECORE_EVENT_KEY_DOWN, e, NULL, NULL);
else
ecore_event_add(ECORE_EVENT_KEY_UP, e, NULL, NULL);
}
static void
text_input_enter(void *data,
struct wl_text_input *text_input EINA_UNUSED,
struct wl_surface *surface EINA_UNUSED)
{
WaylandIMContext *imcontext = (WaylandIMContext *)data;
update_state(imcontext);
imcontext->reset_serial = imcontext->serial;
}
static void
text_input_leave(void *data,
struct wl_text_input *text_input)
{
WaylandIMContext *imcontext = (WaylandIMContext *)data;
wl_text_input_hide_input_panel(text_input);
/* clear preedit */
commit_preedit(imcontext);
clear_preedit(imcontext);
ecore_imf_context_preedit_changed_event_add(imcontext->ctx);
ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
ecore_imf_context_preedit_end_event_add(imcontext->ctx);
ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
}
static void
text_input_input_panel_state(void *data EINA_UNUSED,
struct wl_text_input *text_input EINA_UNUSED,
uint32_t state EINA_UNUSED)
{
}
static void
text_input_language(void *data EINA_UNUSED,
struct wl_text_input *text_input EINA_UNUSED,
uint32_t serial EINA_UNUSED,
const char *language EINA_UNUSED)
{
}
static void
text_input_text_direction(void *data EINA_UNUSED,
struct wl_text_input *text_input EINA_UNUSED,
uint32_t serial EINA_UNUSED,
uint32_t direction EINA_UNUSED)
{
}
static const struct wl_text_input_listener text_input_listener =
{
text_input_enter,
text_input_leave,
text_input_modifiers_map,
text_input_input_panel_state,
text_input_preedit_string,
text_input_preedit_styling,
text_input_preedit_cursor,
text_input_commit_string,
text_input_cursor_position,
text_input_delete_surrounding_text,
text_input_keysym,
text_input_language,
text_input_text_direction
};
EAPI void
wayland_im_context_add(Ecore_IMF_Context *ctx)
{
WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "context_add");
imcontext->ctx = ctx;
imcontext->text_input = wl_text_input_manager_create_text_input(imcontext->text_input_manager);
wl_text_input_add_listener(imcontext->text_input, &text_input_listener, imcontext);
}
EAPI void
wayland_im_context_del(Ecore_IMF_Context *ctx)
{
WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "context_del");
wl_text_input_destroy(imcontext->text_input);
clear_preedit(imcontext);
}
EAPI void
wayland_im_context_reset(Ecore_IMF_Context *ctx)
{
WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
commit_preedit(imcontext);
clear_preedit(imcontext);
wl_text_input_reset(imcontext->text_input);
update_state(imcontext);
imcontext->reset_serial = imcontext->serial;
}
EAPI void
wayland_im_context_focus_in(Ecore_IMF_Context *ctx)
{
WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
Ecore_Wl_Input *input;
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "focus-in");
if (!imcontext->window)
return;
input = imcontext->window->keyboard_device;
if (!input || !input->seat)
return;
wl_text_input_show_input_panel(imcontext->text_input);
wl_text_input_activate(imcontext->text_input,
input->seat,
ecore_wl_window_surface_get(imcontext->window));
}
EAPI void
wayland_im_context_focus_out(Ecore_IMF_Context *ctx)
{
WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "focus-out");
if (!imcontext->window)
return;
wl_text_input_deactivate(imcontext->text_input,
imcontext->window->display->input->seat);
}
EAPI void
wayland_im_context_preedit_string_get(Ecore_IMF_Context *ctx,
char **str,
int *cursor_pos)
{
WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
"pre-edit string requested (preedit: `%s')",
imcontext->preedit_text ? imcontext->preedit_text : "");
if (str)
*str = strdup(imcontext->preedit_text ? imcontext->preedit_text : "");
if (cursor_pos)
*cursor_pos = imcontext->preedit_cursor;
}
EAPI void
wayland_im_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx,
char **str,
Eina_List **attrs,
int *cursor_pos)
{
WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
"pre-edit string with attributes requested (preedit: `%s')",
imcontext->preedit_text ? imcontext->preedit_text : "");
if (str)
*str = strdup(imcontext->preedit_text ? imcontext->preedit_text : "");
if (attrs)
{
Eina_List *l;
Ecore_IMF_Preedit_Attr *a, *attr;
EINA_LIST_FOREACH(imcontext->preedit_attrs, l, a)
{
attr = malloc(sizeof(*attr));
attr = memcpy(attr, a, sizeof(*attr));
*attrs = eina_list_append(*attrs, attr);
}
}
if (cursor_pos)
*cursor_pos = imcontext->preedit_cursor;
}
EAPI void
wayland_im_context_cursor_position_set(Ecore_IMF_Context *ctx,
int cursor_pos)
{
WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
"set cursor position (cursor: %d)",
cursor_pos);
update_state(imcontext);
}
EAPI void
wayland_im_context_use_preedit_set(Ecore_IMF_Context *ctx EINA_UNUSED,
Eina_Bool use_preedit EINA_UNUSED)
{
}
EAPI void
wayland_im_context_client_window_set(Ecore_IMF_Context *ctx,
void *window)
{
WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "client window set (window: %p)", window);
if (window != NULL)
imcontext->window = ecore_wl_window_find((Ecore_Window)window);
}
EAPI void
wayland_im_context_client_canvas_set(Ecore_IMF_Context *ctx,
void *canvas)
{
WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "client canvas set (canvas: %p)", canvas);
if (canvas != NULL)
imcontext->canvas = canvas;
}
EAPI void
wayland_im_context_show(Ecore_IMF_Context *ctx)
{
WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "context_show");
wl_text_input_show_input_panel(imcontext->text_input);
}
EAPI void
wayland_im_context_hide(Ecore_IMF_Context *ctx)
{
WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "context_hide");
wl_text_input_hide_input_panel(imcontext->text_input);
}
EAPI Eina_Bool
wayland_im_context_filter_event(Ecore_IMF_Context *ctx EINA_UNUSED,
Ecore_IMF_Event_Type type EINA_UNUSED,
Ecore_IMF_Event *event EINA_UNUSED)
{
return EINA_FALSE;
}
EAPI void
wayland_im_context_cursor_location_set(Ecore_IMF_Context *ctx, int x, int y, int width, int height)
{
WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "cursor_location_set (x: %d, y: %d, w: %d, h: %d)", x, y, width, height);
if ((imcontext->cursor_location.x != x) ||
(imcontext->cursor_location.y != y) ||
(imcontext->cursor_location.width != width) ||
(imcontext->cursor_location.height != height))
{
imcontext->cursor_location.x = x;
imcontext->cursor_location.y = y;
imcontext->cursor_location.width = width;
imcontext->cursor_location.height = height;
update_state(imcontext);
}
}
WaylandIMContext *wayland_im_context_new (struct wl_text_input_manager *text_input_manager)
{
WaylandIMContext *context = calloc(1, sizeof(WaylandIMContext));
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "new context created");
context->text_input_manager = text_input_manager;
return context;
}
/* vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0
*/

View File

@ -0,0 +1,70 @@
/*
* 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 __WAYLAND_IM_CONTEXT_H_
#define __WAYLAND_IM_CONTEXT_H_
#include <Ecore_IMF.h>
#include "text-client-protocol.h"
typedef struct _WaylandIMContext WaylandIMContext;
EAPI void wayland_im_context_add (Ecore_IMF_Context *ctx);
EAPI void wayland_im_context_del (Ecore_IMF_Context *ctx);
EAPI void wayland_im_context_reset (Ecore_IMF_Context *ctx);
EAPI void wayland_im_context_focus_in (Ecore_IMF_Context *ctx);
EAPI void wayland_im_context_focus_out (Ecore_IMF_Context *ctx);
EAPI void wayland_im_context_preedit_string_get (Ecore_IMF_Context *ctx,
char **str,
int *cursor_pos);
EAPI void wayland_im_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx,
char **str,
Eina_List **attr,
int *cursor_pos);
EAPI void wayland_im_context_cursor_position_set(Ecore_IMF_Context *ctx,
int cursor_pos);
EAPI void wayland_im_context_use_preedit_set (Ecore_IMF_Context *ctx,
Eina_Bool use_preedit);
EAPI void wayland_im_context_client_window_set (Ecore_IMF_Context *ctx,
void *window);
EAPI void wayland_im_context_client_canvas_set (Ecore_IMF_Context *ctx,
void *canvas);
EAPI void wayland_im_context_show (Ecore_IMF_Context *ctx);
EAPI void wayland_im_context_hide (Ecore_IMF_Context *ctx);
EAPI Eina_Bool wayland_im_context_filter_event (Ecore_IMF_Context *ctx,
Ecore_IMF_Event_Type type,
Ecore_IMF_Event *event);
EAPI void wayland_im_context_cursor_location_set(Ecore_IMF_Context *ctx,
int x,
int y,
int width,
int height);
WaylandIMContext *wayland_im_context_new (struct wl_text_input_manager *text_input_manager);
extern int _ecore_imf_wayland_log_dom;
#endif
/* vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0
*/

View File

@ -0,0 +1,154 @@
/*
* 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 <Ecore.h>
#include <Ecore_IMF.h>
#include <Ecore_Wayland.h>
#include <stdio.h>
#include "wayland_imcontext.h"
#include "text-client-protocol.h"
int _ecore_imf_wayland_log_dom = -1;
static const Ecore_IMF_Context_Info wayland_im_info =
{
"wayland",
"Wayland",
"*",
NULL,
0
};
static Ecore_IMF_Context_Class wayland_imf_class =
{
wayland_im_context_add, /* add */
wayland_im_context_del, /* del */
wayland_im_context_client_window_set, /* client_window_set */
wayland_im_context_client_canvas_set, /* client_canvas_set */
wayland_im_context_show, /* show */
wayland_im_context_hide, /* hide */
wayland_im_context_preedit_string_get, /* get_preedit_string */
wayland_im_context_focus_in, /* focus_in */
wayland_im_context_focus_out, /* focus_out */
wayland_im_context_reset, /* reset */
wayland_im_context_cursor_position_set, /* cursor_position_set */
wayland_im_context_use_preedit_set, /* use_preedit_set */
NULL, /* input_mode_set */
wayland_im_context_filter_event, /* filter_event */
wayland_im_context_preedit_string_with_attributes_get, /* preedit_string_with_attribute_get */
NULL, /* prediction_allow_set */
NULL, /* autocapital_type_set */
NULL, /* control panel show */
NULL, /* control panel hide */
NULL, /* input_panel_layout_set */
NULL, /* input_panel_layout_get, */
NULL, /* input_panel_language_set, */
NULL, /* input_panel_language_get, */
wayland_im_context_cursor_location_set, /* cursor_location_set */
NULL, /* input_panel_imdata_set */
NULL, /* input_panel_imdata_get */
NULL, /* input_panel_return_key_type_set */
NULL, /* input_panel_return_key_disabled_set */
NULL, /* input_panel_caps_lock_mode_set */
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
static struct wl_text_input_manager *text_input_manager = NULL;
static Ecore_IMF_Context *
im_module_exit(void)
{
return NULL;
}
static Ecore_IMF_Context *
im_module_create()
{
Ecore_IMF_Context *ctx = NULL;
WaylandIMContext *ctxd = NULL;
ctxd = wayland_im_context_new(text_input_manager);
if (!ctxd)
{
return NULL;
}
ctx = ecore_imf_context_new(&wayland_imf_class);
if (!ctx)
{
free(ctxd);
return NULL;
}
ecore_imf_context_data_set(ctx, ctxd);
return ctx;
}
static Eina_Bool
im_module_init(void)
{
struct wl_registry *registry;
struct wl_list *globals;
Ecore_Wl_Global *global;
ecore_wl_init(NULL);
_ecore_imf_wayland_log_dom = eina_log_domain_register("ecore_imf_wayland", EINA_COLOR_YELLOW);
ecore_wl_display_iterate();
registry = ecore_wl_registry_get();
globals = ecore_wl_globals_get();
wl_list_for_each(global, globals, link)
{
if (!strcmp(global->interface, "wl_text_input_manager"))
{
text_input_manager = wl_registry_bind(registry, global->id, &wl_text_input_manager_interface, 1);
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "bound wl_text_input_manager interface");
}
}
ecore_imf_module_register(&wayland_im_info, im_module_create, im_module_exit);
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "im module initalized");
return EINA_TRUE;
}
static void
im_module_shutdown(void)
{
ecore_wl_shutdown();
EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "im module shutdown");
}
EINA_MODULE_INIT(im_module_init);
EINA_MODULE_SHUTDOWN(im_module_shutdown);
/* vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0
*/