enlightenment/src/modules/wl_text_input/e_mod_main.c

934 lines
29 KiB
C

#define E_COMP_WL
#include "e.h"
#include "text-protocol.h"
#include "input-method-protocol.h"
typedef struct _E_Text_Input E_Text_Input;
typedef struct _E_Input_Method E_Input_Method;
typedef struct _E_Input_Method_Context E_Input_Method_Context;
struct _E_Text_Input
{
struct wl_resource *resource;
E_Client *ec;
Eina_List *input_methods;
Eina_Rectangle *cursor_rect;
Eina_Bool input_panel_visible;
};
struct _E_Input_Method
{
struct wl_resource *resource;
E_Text_Input *model;
E_Input_Method_Context *context;
Eina_List *handlers;
};
struct _E_Input_Method_Context
{
struct wl_resource *resource;
E_Text_Input *model;
E_Input_Method *input_method;
struct
{
struct wl_resource *resource;
Eina_List *handlers;
Eina_Bool grabbed;
} kbd;
};
static struct wl_global *text_input_manager_global;
static void
_e_text_input_event_visible_change_send(Eina_Bool visible)
{
E_Event_Text_Input_Panel_Visibility_Change *ev;
ev = E_NEW(E_Event_Text_Input_Panel_Visibility_Change, 1);
ev->visible = visible;
ecore_event_add(E_EVENT_TEXT_INPUT_PANEL_VISIBILITY_CHANGE, ev, NULL, NULL);
}
static void
_e_text_input_method_context_key_send(E_Input_Method_Context *context, unsigned int keycode, unsigned int timestamp, enum wl_keyboard_key_state state)
{
uint32_t serial, nk;
nk = keycode - 8;
serial = wl_display_next_serial(e_comp->wl_comp_data->wl.disp);
wl_keyboard_send_key(context->kbd.resource, serial, timestamp, nk, state);
}
static Eina_Bool
_e_text_input_method_context_ecore_cb_key_down(void *data, int ev_type EINA_UNUSED, Ecore_Event_Key *ev)
{
E_Input_Method_Context *context = data;
_e_text_input_method_context_key_send(context, ev->keycode, ev->timestamp,
WL_KEYBOARD_KEY_STATE_PRESSED);
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_e_text_input_method_context_ecore_cb_key_up(void *data, int ev_type EINA_UNUSED, Ecore_Event_Key *ev)
{
E_Input_Method_Context *context = data;
_e_text_input_method_context_key_send(context, ev->keycode, ev->timestamp,
WL_KEYBOARD_KEY_STATE_RELEASED);
return ECORE_CALLBACK_RENEW;
}
static void
_e_text_input_method_context_grab_set(E_Input_Method_Context *context, Eina_Bool set)
{
if (set == context->kbd.grabbed)
return;
context->kbd.grabbed = set;
if (set)
{
E_LIST_HANDLER_APPEND(context->kbd.handlers, ECORE_EVENT_KEY_DOWN,
_e_text_input_method_context_ecore_cb_key_down,
context);
E_LIST_HANDLER_APPEND(context->kbd.handlers, ECORE_EVENT_KEY_UP,
_e_text_input_method_context_ecore_cb_key_up,
context);
e_comp_grab_input(0, 1);
}
else
{
E_FREE_LIST(context->kbd.handlers, ecore_event_handler_del);
e_comp_ungrab_input(0, 1);
}
}
static void
_e_text_input_deactivate(E_Text_Input *text_input, E_Input_Method *input_method)
{
if (input_method->model == text_input)
{
if ((input_method->context) && (input_method->resource))
{
if (input_method->context)
_e_text_input_method_context_grab_set(input_method->context,
EINA_FALSE);
wl_input_method_send_deactivate(input_method->resource,
input_method->context->resource);
}
input_method->model = NULL;
input_method->context = NULL;
text_input->input_methods = eina_list_remove(text_input->input_methods, input_method);
wl_text_input_send_leave(text_input->resource);
}
}
static void
_e_text_input_method_context_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
{
wl_resource_destroy(resource);
}
static void
_e_text_input_method_context_cb_string_commit(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, const char *text)
{
E_Input_Method_Context *context = wl_resource_get_user_data(resource);
if (!context)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Input Method Context For Resource");
return;
}
if (context->model)
wl_text_input_send_commit_string(context->model->resource,
serial, text);
}
static void
_e_text_input_method_context_cb_preedit_string(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, const char *text, const char *commit)
{
E_Input_Method_Context *context = wl_resource_get_user_data(resource);
if (!context)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Input Method Context For Resource");
return;
}
if (context->model)
wl_text_input_send_preedit_string(context->model->resource,
serial, text, commit);
}
static void
_e_text_input_method_context_cb_preedit_styling(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t index, uint32_t length, uint32_t style)
{
E_Input_Method_Context *context = wl_resource_get_user_data(resource);
if (!context)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Input Method Context For Resource");
return;
}
if (context->model)
wl_text_input_send_preedit_styling(context->model->resource,
index, length, style);
}
static void
_e_text_input_method_context_cb_preedit_cursor(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t cursor)
{
E_Input_Method_Context *context = wl_resource_get_user_data(resource);
if (!context)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Input Method Context For Resource");
return;
}
if (context->model)
wl_text_input_send_preedit_cursor(context->model->resource,
cursor);
}
static void
_e_text_input_method_context_cb_surrounding_text_delete(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t index, uint32_t length)
{
E_Input_Method_Context *context = wl_resource_get_user_data(resource);
if (!context)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Input Method Context For Resource");
return;
}
if (context->model)
wl_text_input_send_delete_surrounding_text(context->model->resource,
index, length);
}
static void
_e_text_input_method_context_cb_cursor_position(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t index, int32_t anchor)
{
E_Input_Method_Context *context = wl_resource_get_user_data(resource);
if (!context)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Input Method Context For Resource");
return;
}
if (context->model)
wl_text_input_send_cursor_position(context->model->resource,
index, anchor);
}
static void
_e_text_input_method_context_cb_modifiers_map(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_array *map)
{
E_Input_Method_Context *context = wl_resource_get_user_data(resource);
if (!context)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Input Method Context For Resource");
return;
}
if (context->model)
wl_text_input_send_modifiers_map(context->model->resource, map);
}
static void
_e_text_input_method_context_cb_keysym(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers)
{
E_Input_Method_Context *context = wl_resource_get_user_data(resource);
if (!context)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Input Method Context For Resource");
return;
}
if (context->model)
wl_text_input_send_keysym(context->model->resource,
serial, time, sym, state, modifiers);
}
static void
_e_text_input_method_context_keyboard_unbind(struct wl_resource *resource)
{
E_Input_Method_Context *context;
context = wl_resource_get_user_data(resource);
_e_text_input_method_context_grab_set(context, EINA_FALSE);
context->kbd.resource = NULL;
}
static void
_e_text_input_method_context_cb_keyboard_grab(struct wl_client *client, struct wl_resource *resource, uint32_t id)
{
E_Input_Method_Context *context;
struct wl_resource *new_resource;
DBG("Input Method Context - grab keyboard %d", wl_resource_get_id(resource));
context = wl_resource_get_user_data(resource);
if (!context)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Input Method Context For Resource");
return;
}
new_resource = wl_resource_create(client, &wl_keyboard_interface, 1, id);
if (!new_resource)
{
wl_resource_post_no_memory(resource);
return;
}
wl_resource_set_implementation(new_resource, NULL, context,
_e_text_input_method_context_keyboard_unbind);
wl_keyboard_send_keymap(new_resource, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
e_comp_wl->xkb.fd,
e_comp_wl->xkb.size);
context->kbd.resource = new_resource;
_e_text_input_method_context_grab_set(context, EINA_TRUE);
}
static void
_e_text_input_method_context_cb_key(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, uint32_t serial EINA_UNUSED, uint32_t time EINA_UNUSED, uint32_t key EINA_UNUSED, uint32_t state_w EINA_UNUSED)
{
DBG("Input Method Context - key %d", wl_resource_get_id(resource));
}
static void
_e_text_input_method_context_cb_modifiers(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, uint32_t serial EINA_UNUSED, uint32_t mods_depressed EINA_UNUSED, uint32_t mods_latched EINA_UNUSED, uint32_t mods_locked EINA_UNUSED, uint32_t group EINA_UNUSED)
{
DBG("Input Method Context - modifiers %d", wl_resource_get_id(resource));
}
static void
_e_text_input_method_context_cb_language(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, const char *language)
{
E_Input_Method_Context *context = wl_resource_get_user_data(resource);
if (!context)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Input Method Context For Resource");
return;
}
if (context->model)
wl_text_input_send_language(context->model->resource,
serial, language);
}
static void
_e_text_input_method_context_cb_text_direction(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, uint32_t direction)
{
E_Input_Method_Context *context = wl_resource_get_user_data(resource);
if (!context)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Input Method Context For Resource");
return;
}
if (context->model)
wl_text_input_send_text_direction(context->model->resource,
serial, direction);
}
static const struct wl_input_method_context_interface _e_text_input_method_context_implementation = {
_e_text_input_method_context_cb_destroy,
_e_text_input_method_context_cb_string_commit,
_e_text_input_method_context_cb_preedit_string,
_e_text_input_method_context_cb_preedit_styling,
_e_text_input_method_context_cb_preedit_cursor,
_e_text_input_method_context_cb_surrounding_text_delete,
_e_text_input_method_context_cb_cursor_position,
_e_text_input_method_context_cb_modifiers_map,
_e_text_input_method_context_cb_keysym,
_e_text_input_method_context_cb_keyboard_grab,
_e_text_input_method_context_cb_key,
_e_text_input_method_context_cb_modifiers,
_e_text_input_method_context_cb_language,
_e_text_input_method_context_cb_text_direction
};
static void
_e_text_input_method_context_cb_resource_destroy(struct wl_resource *resource)
{
E_Input_Method_Context *context = wl_resource_get_user_data(resource);
if (!context)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Input Method Context For Resource");
return;
}
if (context->kbd.resource)
wl_resource_destroy(context->kbd.resource);
free(context);
}
static Eina_Bool
_e_text_input_cb_event_client_focus_in(void *data, int type EINA_UNUSED, void *event)
{
E_Input_Method *input_method = data;
E_Event_Client *ev = event;
if (!input_method->model)
return ECORE_CALLBACK_RENEW;
if ((!ev->ec) ||
(input_method->model->ec != ev->ec))
{
_e_text_input_deactivate(input_method->model, input_method);
_e_text_input_event_visible_change_send(EINA_FALSE);
}
return ECORE_CALLBACK_RENEW;
}
static void
_e_text_input_cb_activate(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat, struct wl_resource *surface)
{
E_Text_Input *text_input;
E_Input_Method *input_method;
E_Text_Input *old;
E_Input_Method_Context *context;
text_input = wl_resource_get_user_data(resource);
if (!text_input)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Text Input For Resource");
return;
}
input_method =
wl_resource_get_user_data(e_comp->wl_comp_data->seat.im.resource);
if (!input_method)
{
wl_resource_post_error(seat,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Input Method For Seat");
return;
}
old = input_method->model;
if (old == text_input)
return;
if (old)
_e_text_input_deactivate(old, input_method);
input_method->model = text_input;
text_input->input_methods =
eina_list_append(text_input->input_methods, input_method);
text_input->ec = wl_resource_get_user_data(surface);
if (input_method->resource)
{
context = E_NEW(E_Input_Method_Context, 1);
if (!context)
{
wl_client_post_no_memory(client);
ERR("Could not allocate space for Input_Method_Context");
return;
}
context->resource =
wl_resource_create(wl_resource_get_client(input_method->resource),
&wl_input_method_context_interface, 1, 0);
wl_resource_set_implementation(context->resource,
&_e_text_input_method_context_implementation,
context, _e_text_input_method_context_cb_resource_destroy);
context->model = text_input;
context->input_method = input_method;
input_method->context = context;
wl_input_method_send_activate(input_method->resource, context->resource);
}
if (text_input->input_panel_visible)
_e_text_input_event_visible_change_send(EINA_TRUE);
wl_text_input_send_enter(text_input->resource, surface);
}
static void
_e_text_input_cb_deactivate(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *seat)
{
E_Text_Input *text_input;
E_Input_Method *input_method;
text_input = wl_resource_get_user_data(resource);
if (!text_input)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Text Input For Resource");
return;
}
input_method =
wl_resource_get_user_data(e_comp->wl_comp_data->seat.im.resource);
if (!input_method)
{
wl_resource_post_error(seat,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Input Method For Seat");
return;
}
_e_text_input_deactivate(text_input, input_method);
_e_text_input_event_visible_change_send(EINA_FALSE);
}
static void
_e_text_input_cb_input_panel_show(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
{
E_Text_Input *text_input = wl_resource_get_user_data(resource);
E_Input_Method *input_method;
Eina_List *l;
if (!text_input)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Text Input For Resource");
return;
}
text_input->input_panel_visible = 1;
EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
{
if (input_method->model == text_input)
_e_text_input_event_visible_change_send(EINA_TRUE);
}
}
static void
_e_text_input_cb_input_panel_hide(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
{
E_Text_Input *text_input = wl_resource_get_user_data(resource);
E_Input_Method *input_method;
Eina_List *l;
if (!text_input)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Text Input For Resource");
return;
}
text_input->input_panel_visible = 0;
EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
{
if (input_method->model == text_input)
_e_text_input_event_visible_change_send(EINA_FALSE);
}
}
static void
_e_text_input_cb_reset(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
{
E_Text_Input *text_input = wl_resource_get_user_data(resource);
E_Input_Method *input_method;
Eina_List *l;
if (!text_input)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Text Input For Resource");
return;
}
EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
{
if (!input_method->context) continue;
wl_input_method_context_send_reset(input_method->context->resource);
}
}
static void
_e_text_input_cb_surrounding_text_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *text, uint32_t cursor, uint32_t anchor)
{
E_Text_Input *text_input = wl_resource_get_user_data(resource);
E_Input_Method *input_method;
Eina_List *l;
if (!text_input)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Text Input For Resource");
return;
}
EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
{
if (!input_method->context) continue;
wl_input_method_context_send_surrounding_text(input_method->context->resource,
text, cursor, anchor);
}
}
static void
_e_text_input_cb_content_type_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t hint, uint32_t purpose)
{
E_Text_Input *text_input = wl_resource_get_user_data(resource);
E_Input_Method *input_method;
Eina_List *l;
if (!text_input)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Text Input For Resource");
return;
}
EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
{
if (!input_method->context) continue;
wl_input_method_context_send_content_type(input_method->context->resource,
hint, purpose);
}
}
static void
_e_text_input_cb_cursor_rectangle_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
{
E_Text_Input *text_input = wl_resource_get_user_data(resource);
if (!text_input)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Text Input For Resource");
return;
}
text_input->cursor_rect = eina_rectangle_new(x, y, width, height);
// TODO: issue event update input_panel
}
static void
_e_text_input_cb_preferred_language_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *language)
{
E_Text_Input *text_input = wl_resource_get_user_data(resource);
E_Input_Method *input_method;
Eina_List *l;
if (!text_input)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Text Input For Resource");
return;
}
EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
{
if (!input_method->context) continue;
wl_input_method_context_send_preferred_language(input_method->context->resource,
language);
}
}
static void
_e_text_input_cb_state_commit(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial)
{
E_Text_Input *text_input = wl_resource_get_user_data(resource);
E_Input_Method *input_method;
Eina_List *l;
if (!text_input)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Text Input For Resource");
return;
}
EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
{
if (!input_method->context) continue;
wl_input_method_context_send_commit_state(input_method->context->resource, serial);
}
}
static void
_e_text_input_cb_action_invoke(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t button, uint32_t index)
{
E_Text_Input *text_input = wl_resource_get_user_data(resource);
E_Input_Method *input_method;
Eina_List *l;
if (!text_input)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Text Input For Resource");
return;
}
EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
{
if (!input_method->context) continue;
wl_input_method_context_send_invoke_action(input_method->context->resource,
button, index);
}
}
static const struct wl_text_input_interface _e_text_input_implementation = {
_e_text_input_cb_activate,
_e_text_input_cb_deactivate,
_e_text_input_cb_input_panel_show,
_e_text_input_cb_input_panel_hide,
_e_text_input_cb_reset,
_e_text_input_cb_surrounding_text_set,
_e_text_input_cb_content_type_set,
_e_text_input_cb_cursor_rectangle_set,
_e_text_input_cb_preferred_language_set,
_e_text_input_cb_state_commit,
_e_text_input_cb_action_invoke
};
static void
_e_text_input_cb_destroy(struct wl_resource *resource)
{
E_Text_Input *text_input = wl_resource_get_user_data(resource);
E_Input_Method *input_method;
if (!text_input)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Text Input For Resource");
return;
}
EINA_LIST_FREE(text_input->input_methods, input_method)
_e_text_input_deactivate(text_input, input_method);
eina_rectangle_free(text_input->cursor_rect);
free(text_input);
}
static void
_e_text_input_manager_cb_text_input_create(struct wl_client *client, struct wl_resource *resource EINA_UNUSED, uint32_t id)
{
E_Text_Input *text_input;
text_input = E_NEW(E_Text_Input, 1);
if (!text_input)
{
wl_client_post_no_memory(client);
ERR("Could not allocate space for Text_Input");
return;
}
text_input->resource = wl_resource_create(client,
&wl_text_input_interface,
1, id);
if (!text_input->resource)
{
wl_client_post_no_memory(client);
ERR("could not create wl_resource for text input");
return;
}
wl_resource_set_implementation(text_input->resource,
&_e_text_input_implementation,
text_input, _e_text_input_cb_destroy);
}
static const struct wl_text_input_manager_interface _e_text_input_manager_implementation = {
_e_text_input_manager_cb_text_input_create
};
static void
_e_text_cb_bind_text_input_manager(struct wl_client *client, void *data EINA_UNUSED, uint32_t version EINA_UNUSED, uint32_t id)
{
struct wl_resource *resource;
resource = wl_resource_create(client, &wl_text_input_manager_interface, 1, id);
if (!resource)
{
wl_client_post_no_memory(client);
ERR("could not create resource for text input manager");
return;
}
wl_resource_set_implementation(resource, &_e_text_input_manager_implementation, NULL, NULL);
}
static void
_e_text_input_method_cb_unbind(struct wl_resource *resource)
{
E_Input_Method *input_method = wl_resource_get_user_data(resource);
e_comp->wl_comp_data->seat.im.resource = NULL;
input_method = wl_resource_get_user_data(resource);
if (!input_method)
{
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"No Input Method For Resource");
return;
}
if (input_method->model)
_e_text_input_deactivate(input_method->model, input_method);
E_FREE_FUNC(input_method->handlers, ecore_event_handler_del);
input_method->resource = NULL;
input_method->context = NULL;
free(input_method);
}
static void
_e_text_cb_bind_input_method(struct wl_client *client, void *data EINA_UNUSED, uint32_t version EINA_UNUSED, uint32_t id)
{
E_Input_Method *input_method;
struct wl_resource *resource;
resource = wl_resource_create(client, &wl_input_method_interface, 1, id);
if (!resource)
{
wl_client_post_no_memory(client);
ERR("could not create wl_resource for input method");
return;
}
if (e_comp->wl_comp_data->seat.im.resource)
{
wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
"interface object already bound");
wl_resource_destroy(resource);
return;
}
/* FIXME: we need to make sure the client attempting to bind
this interface really provides vkbd. */
input_method = E_NEW(E_Input_Method, 1);
if (!input_method)
{
wl_client_post_no_memory(client);
wl_resource_destroy(resource);
ERR("Could not allocate space for Input_Method");
return;
}
wl_resource_set_implementation(resource, NULL, input_method,
_e_text_input_method_cb_unbind);
input_method->model = NULL;
input_method->context = NULL;
input_method->resource = resource;
e_comp->wl_comp_data->seat.im.resource = resource;
E_LIST_HANDLER_APPEND(input_method->handlers, E_EVENT_CLIENT_FOCUS_IN,
_e_text_input_cb_event_client_focus_in, input_method);
}
EAPI E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Wl_Text_Input" };
EAPI void *
e_modapi_init(E_Module *m)
{
// FIXME: create only one input method object per seat.
e_comp->wl_comp_data->seat.im.global =
wl_global_create(e_comp->wl_comp_data->wl.disp, &wl_input_method_interface, 1,
NULL, _e_text_cb_bind_input_method);
if (!e_comp->wl_comp_data->seat.im.global)
{
ERR("failed to create wl_global for input method");
return NULL;
}
text_input_manager_global =
wl_global_create(e_comp->wl_comp_data->wl.disp, &wl_text_input_manager_interface, 1,
NULL, _e_text_cb_bind_text_input_manager);
if (!text_input_manager_global)
{
ERR("failed to create wl_global for text input manager");
wl_global_destroy(e_comp->wl_comp_data->seat.im.global);
return NULL;
}
return m;
}
EAPI int
e_modapi_shutdown(E_Module *m EINA_UNUSED)
{
E_FREE_FUNC(e_comp->wl_comp_data->seat.im.global, wl_global_destroy);
E_FREE_FUNC(text_input_manager_global, wl_global_destroy);
return 1;
}