X11 = x11
endif
+if ENABLE_WAYLAND
+WAYLAND = wayland
+endif
+
SUBDIRS = \
$(GTK2) \
$(GTK3) \
$(X11) \
+ $(WAYLAND) \
$(NULL)
-include $(top_srcdir)/git.mk
--- /dev/null
+# vim:set noet ts=4:
+#
+# ibus - The Input Bus
+#
+# Copyright (c) 2007-2013 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2007-2013 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.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.
+
+libibus = $(top_builddir)/src/libibus-@IBUS_API_VERSION@.la
+
+libexec_PROGRAMS = ibus-wayland
+
+protocol_sources = \
+ input-method-protocol.c \
+ input-method-client-protocol.h \
+ $(NULL)
+
+ibus_wayland_SOURCES = \
+ $(protocol_sources) \
+ main.c \
+ $(NULL)
+
+ibus_wayland_DEPENDENCIES = \
+ $(libibus) \
+ $(NULL)
+
+ibus_wayland_LDADD = \
+ $(libibus) \
+ $(GIO2_LIBS) \
+ $(WAYLAND_LIBS) \
+ $(NULL)
+
+ibus_wayland_CFLAGS = \
+ $(GIO2_CFLAGS) \
+ $(WAYLAND_CFLAGS) \
+ -I$(top_srcdir)/src \
+ -I$(top_builddir)/src \
+ $(NULL)
+
+$(libibus):
+ (cd $(top_builddir)/src; make)
+
+EXTRA_DIST = \
+ README \
+ $(protocol_sources) \
+ $(NULL)
+
+-include $(top_srcdir)/git.mk
--- /dev/null
+The following two files are generated with wayland-scanner:
+
+input-method-protocol.c
+input-method-client-protocol.h
+
+We include them in the distribution instead of generating them, since
+the Wayland protocol structure will unlikely change. Do not modify
+those files manually.
+
+To generate them, use the wayland-scanner command as follows. You can
+find input-method.xml in the Weston source code (maybe it will be
+moved to the Wayland source code later).
+
+$ wayland-scanner code < input-method.xml \
+ > input-method-protocol.c
+$ wayland-scanner client-header < input-method.xml \
+ > input-method-client-protocol.h
--- /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 */
+
+#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 },
+};
+
+WL_EXPORT const struct wl_interface wl_input_panel_surface_interface = {
+ "wl_input_panel_surface", 1,
+ 2, wl_input_panel_surface_requests,
+ 0, NULL,
+};
+
--- /dev/null
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/* vim:set et sts=4: */
+/* ibus - The Input Bus
+ * Copyright (C) 2013 Intel Corporation
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.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.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <ibus.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wayland-client.h>
+#include <xkbcommon/xkbcommon.h>
+
+#include "input-method-client-protocol.h"
+
+struct _IBusWaylandIM
+{
+ struct wl_input_method *input_method;
+ struct wl_input_method_context *context;
+ struct wl_keyboard *keyboard;
+
+ IBusInputContext *ibuscontext;
+ IBusText *preedit_text;
+ guint preedit_cursor_pos;
+ IBusModifierType modifiers;
+
+ struct xkb_context *xkb_context;
+
+ struct xkb_keymap *keymap;
+ struct xkb_state *state;
+
+ xkb_mod_mask_t shift_mask;
+ xkb_mod_mask_t lock_mask;
+ xkb_mod_mask_t control_mask;
+ xkb_mod_mask_t mod1_mask;
+ xkb_mod_mask_t mod2_mask;
+ xkb_mod_mask_t mod3_mask;
+ xkb_mod_mask_t mod4_mask;
+ xkb_mod_mask_t mod5_mask;
+ xkb_mod_mask_t super_mask;
+ xkb_mod_mask_t hyper_mask;
+ xkb_mod_mask_t meta_mask;
+
+ uint32_t serial;
+
+ GCancellable *cancellable;
+};
+typedef struct _IBusWaylandIM IBusWaylandIM;
+
+struct _IBusWaylandKeyEvent
+{
+ struct wl_input_method_context *context;
+ uint32_t serial;
+ uint32_t time;
+ uint32_t key;
+ enum wl_keyboard_key_state state;
+};
+typedef struct _IBusWaylandKeyEvent IBusWaylandKeyEvent;
+
+struct _IBusWaylandSource
+{
+ GSource source;
+ GPollFD pfd;
+ uint32_t mask;
+ struct wl_display *display;
+};
+typedef struct _IBusWaylandSource IBusWaylandSource;
+
+struct wl_display *_display = NULL;
+struct wl_registry *_registry = NULL;
+static IBusBus *_bus = NULL;
+
+static gboolean _use_sync_mode = FALSE;
+
+static gboolean
+_get_boolean_env (const gchar *name,
+ gboolean defval)
+{
+ const gchar *value = g_getenv (name);
+
+ if (value == NULL)
+ return defval;
+
+ if (g_strcmp0 (value, "") == 0 ||
+ g_strcmp0 (value, "0") == 0 ||
+ g_strcmp0 (value, "false") == 0 ||
+ g_strcmp0 (value, "False") == 0 ||
+ g_strcmp0 (value, "FALSE") == 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+ibus_wayland_source_prepare (GSource *base,
+ gint *timeout)
+{
+ IBusWaylandSource *source = (IBusWaylandSource *) base;
+
+ *timeout = -1;
+
+ wl_display_flush (source->display);
+
+ return FALSE;
+}
+
+static gboolean
+ibus_wayland_source_check (GSource *base)
+{
+ IBusWaylandSource *source = (IBusWaylandSource *) base;
+
+ if (source->pfd.revents & (G_IO_ERR | G_IO_HUP))
+ g_error ("Lost connection to wayland compositor");
+
+ return source->pfd.revents;
+}
+
+static gboolean
+ibus_wayland_source_dispatch (GSource *base,
+ GSourceFunc callback,
+ gpointer data)
+{
+ IBusWaylandSource *source = (IBusWaylandSource *) base;
+
+ if (source->pfd.revents) {
+ wl_display_dispatch (source->display);
+ source->pfd.revents = 0;
+ }
+
+ return TRUE;
+}
+
+static void
+ibus_wayland_source_finalize (GSource *source)
+{
+}
+
+static GSourceFuncs ibus_wayland_source_funcs = {
+ ibus_wayland_source_prepare,
+ ibus_wayland_source_check,
+ ibus_wayland_source_dispatch,
+ ibus_wayland_source_finalize
+};
+
+GSource *
+ibus_wayland_source_new (struct wl_display *display)
+{
+ GSource *source;
+ IBusWaylandSource *wlsource;
+
+ source = g_source_new (&ibus_wayland_source_funcs,
+ sizeof (IBusWaylandSource));
+ wlsource = (IBusWaylandSource *) source;
+
+ wlsource->display = display;
+ wlsource->pfd.fd = wl_display_get_fd (display);
+ wlsource->pfd.events = G_IO_IN | G_IO_ERR | G_IO_HUP;
+ g_source_add_poll (source, &wlsource->pfd);
+
+ return source;
+}
+
+static void
+_context_commit_text_cb (IBusInputContext *context,
+ IBusText *text,
+ IBusWaylandIM *wlim)
+{
+ wl_input_method_context_commit_string (wlim->context,
+ wlim->serial,
+ text->text);
+}
+
+static void
+_context_forward_key_event_cb (IBusInputContext *context,
+ guint keyval,
+ guint keycode,
+ guint modifiers,
+ IBusWaylandIM *wlim)
+{
+ uint32_t state;
+
+ if (modifiers & IBUS_RELEASE_MASK)
+ state = WL_KEYBOARD_KEY_STATE_RELEASED;
+ else
+ state = WL_KEYBOARD_KEY_STATE_PRESSED;
+
+ wl_input_method_context_keysym (wlim->context,
+ wlim->serial,
+ 0,
+ keyval,
+ state,
+ modifiers);
+}
+
+static void
+_context_show_preedit_text_cb (IBusInputContext *context,
+ IBusWaylandIM *wlim)
+{
+ /* CURSOR is byte offset. */
+ uint32_t cursor =
+ g_utf8_offset_to_pointer (wlim->preedit_text->text,
+ wlim->preedit_cursor_pos) -
+ wlim->preedit_text->text;
+
+ wl_input_method_context_preedit_cursor (wlim->context,
+ cursor);
+ wl_input_method_context_preedit_string (wlim->context,
+ wlim->serial,
+ wlim->preedit_text->text,
+ wlim->preedit_text->text);
+}
+
+static void
+_context_hide_preedit_text_cb (IBusInputContext *context,
+ IBusWaylandIM *wlim)
+{
+ wl_input_method_context_preedit_string (wlim->context,
+ wlim->serial,
+ "",
+ "");
+}
+
+static void
+_context_update_preedit_text_cb (IBusInputContext *context,
+ IBusText *text,
+ gint cursor_pos,
+ gboolean visible,
+ IBusWaylandIM *wlim)
+{
+ if (wlim->preedit_text)
+ g_object_unref (wlim->preedit_text);
+ wlim->preedit_text = g_object_ref_sink (text);
+ wlim->preedit_cursor_pos = cursor_pos;
+
+ if (visible)
+ _context_show_preedit_text_cb (context, wlim);
+ else
+ _context_hide_preedit_text_cb (context, wlim);
+}
+
+static void
+handle_surrounding_text (void *data,
+ struct wl_input_method_context *context,
+ const char *text,
+ uint32_t cursor,
+ uint32_t anchor)
+{
+#if ENABLE_SURROUNDING
+ IBusWaylandIM *wlim = data;
+
+ if (wlim->ibuscontext != NULL &&
+ ibus_input_context_needs_surrounding_text (wlim->ibuscontext)) {
+ /* CURSOR_POS and ANCHOR_POS are character offset. */
+ guint cursor_pos = g_utf8_pointer_to_offset (text, text + cursor);
+ guint anchor_pos = g_utf8_pointer_to_offset (text, text + anchor);
+ IBusText *ibustext = ibus_text_new_from_string (text);
+
+ ibus_input_context_set_surrounding_text (wlim->ibuscontext,
+ ibustext,
+ cursor_pos,
+ anchor_pos);
+ }
+#endif
+}
+
+static void
+handle_reset (void *data,
+ struct wl_input_method_context *context)
+{
+}
+
+static void
+handle_content_type (void *data,
+ struct wl_input_method_context *context,
+ uint32_t hint,
+ uint32_t purpose)
+{
+}
+
+static void
+handle_invoke_action (void *data,
+ struct wl_input_method_context *context,
+ uint32_t button,
+ uint32_t index)
+{
+}
+
+static void
+handle_commit_state (void *data,
+ struct wl_input_method_context *context,
+ uint32_t serial)
+{
+ IBusWaylandIM *wlim = data;
+
+ wlim->serial = serial;
+}
+
+static void
+handle_preferred_language (void *data,
+ struct wl_input_method_context *context,
+ const char *language)
+{
+}
+
+static const struct wl_input_method_context_listener context_listener = {
+ handle_surrounding_text,
+ handle_reset,
+ handle_content_type,
+ handle_invoke_action,
+ handle_commit_state,
+ handle_preferred_language
+};
+
+static void
+input_method_keyboard_keymap (void *data,
+ struct wl_keyboard *wl_keyboard,
+ uint32_t format,
+ int32_t fd,
+ uint32_t size)
+{
+ IBusWaylandIM *wlim = data;
+ GMappedFile *map;
+ GError *error;
+
+ if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
+ close(fd);
+ return;
+ }
+
+ error = NULL;
+ map = g_mapped_file_new_from_fd (fd, FALSE, &error);
+ if (map == NULL) {
+ close (fd);
+ return;
+ }
+
+ wlim->keymap =
+ xkb_map_new_from_string (wlim->xkb_context,
+ g_mapped_file_get_contents (map),
+ XKB_KEYMAP_FORMAT_TEXT_V1,
+ 0);
+
+ g_mapped_file_unref (map);
+ close(fd);
+
+ if (!wlim->keymap) {
+ return;
+ }
+
+ wlim->state = xkb_state_new (wlim->keymap);
+ if (!wlim->state) {
+ xkb_map_unref (wlim->keymap);
+ return;
+ }
+
+ wlim->shift_mask =
+ 1 << xkb_map_mod_get_index (wlim->keymap, "Shift");
+ wlim->lock_mask =
+ 1 << xkb_map_mod_get_index (wlim->keymap, "Lock");
+ wlim->control_mask =
+ 1 << xkb_map_mod_get_index (wlim->keymap, "Control");
+ wlim->mod1_mask =
+ 1 << xkb_map_mod_get_index (wlim->keymap, "Mod1");
+ wlim->mod2_mask =
+ 1 << xkb_map_mod_get_index (wlim->keymap, "Mod2");
+ wlim->mod3_mask =
+ 1 << xkb_map_mod_get_index (wlim->keymap, "Mod3");
+ wlim->mod4_mask =
+ 1 << xkb_map_mod_get_index (wlim->keymap, "Mod4");
+ wlim->mod5_mask =
+ 1 << xkb_map_mod_get_index (wlim->keymap, "Mod5");
+ wlim->super_mask =
+ 1 << xkb_map_mod_get_index (wlim->keymap, "Super");
+ wlim->hyper_mask =
+ 1 << xkb_map_mod_get_index (wlim->keymap, "Hyper");
+ wlim->meta_mask =
+ 1 << xkb_map_mod_get_index (wlim->keymap, "Meta");
+}
+
+static void
+_process_key_event_done (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ IBusInputContext *context = (IBusInputContext *)object;
+ IBusWaylandKeyEvent *event = (IBusWaylandKeyEvent *) user_data;
+
+ GError *error = NULL;
+ gboolean retval = ibus_input_context_process_key_event_async_finish (
+ context,
+ res,
+ &error);
+
+ if (error != NULL) {
+ g_warning ("Process Key Event failed: %s.", error->message);
+ g_error_free (error);
+ }
+
+ if (!retval) {
+ wl_input_method_context_key (event->context,
+ event->serial,
+ event->time,
+ event->key,
+ event->state);
+ }
+
+ g_free (event);
+}
+
+static void
+input_method_keyboard_key (void *data,
+ struct wl_keyboard *wl_keyboard,
+ uint32_t serial,
+ uint32_t time,
+ uint32_t key,
+ uint32_t state)
+{
+ IBusWaylandIM *wlim = data;
+ uint32_t code;
+ uint32_t num_syms;
+ const xkb_keysym_t *syms;
+ xkb_keysym_t sym;
+ guint32 modifiers;
+
+ if (!wlim->state)
+ return;
+
+ if (!wlim->ibuscontext) {
+ wl_input_method_context_key (wlim->context,
+ serial,
+ time,
+ key,
+ state);
+ return;
+ }
+
+ code = key + 8;
+ num_syms = xkb_key_get_syms (wlim->state, code, &syms);
+
+ sym = XKB_KEY_NoSymbol;
+ if (num_syms == 1)
+ sym = syms[0];
+
+ modifiers = wlim->modifiers;
+ if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
+ modifiers |= IBUS_RELEASE_MASK;
+
+ if (_use_sync_mode) {
+ gboolean retval =
+ ibus_input_context_process_key_event (wlim->ibuscontext,
+ sym,
+ code,
+ modifiers);
+ if (!retval) {
+ wl_input_method_context_key (wlim->context,
+ serial,
+ time,
+ key,
+ state);
+ }
+ } else {
+ IBusWaylandKeyEvent *event = g_new (IBusWaylandKeyEvent, 1);
+ event->context = wlim->context;
+ event->serial = serial;
+ event->time = time;
+ event->key = key;
+ event->state = state;
+ ibus_input_context_process_key_event_async (wlim->ibuscontext,
+ sym,
+ code,
+ modifiers,
+ -1,
+ NULL,
+ _process_key_event_done,
+ event);
+ }
+}
+
+static void
+input_method_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)
+{
+ IBusWaylandIM *wlim = data;
+ struct wl_input_method_context *context = wlim->context;
+ xkb_mod_mask_t mask;
+
+ xkb_state_update_mask (wlim->state, mods_depressed,
+ mods_latched, mods_locked, 0, 0, group);
+ mask = xkb_state_serialize_mods (wlim->state,
+ XKB_STATE_DEPRESSED |
+ XKB_STATE_LATCHED);
+
+ wlim->modifiers = 0;
+ if (mask & wlim->shift_mask)
+ wlim->modifiers |= IBUS_SHIFT_MASK;
+ if (mask & wlim->lock_mask)
+ wlim->modifiers |= IBUS_LOCK_MASK;
+ if (mask & wlim->control_mask)
+ wlim->modifiers |= IBUS_CONTROL_MASK;
+ if (mask & wlim->mod1_mask)
+ wlim->modifiers |= IBUS_MOD1_MASK;
+ if (mask & wlim->mod2_mask)
+ wlim->modifiers |= IBUS_MOD2_MASK;
+ if (mask & wlim->mod3_mask)
+ wlim->modifiers |= IBUS_MOD3_MASK;
+ if (mask & wlim->mod4_mask)
+ wlim->modifiers |= IBUS_MOD4_MASK;
+ if (mask & wlim->mod5_mask)
+ wlim->modifiers |= IBUS_MOD5_MASK;
+ if (mask & wlim->super_mask)
+ wlim->modifiers |= IBUS_SUPER_MASK;
+ if (mask & wlim->hyper_mask)
+ wlim->modifiers |= IBUS_HYPER_MASK;
+ if (mask & wlim->meta_mask)
+ wlim->modifiers |= IBUS_META_MASK;
+
+ wl_input_method_context_modifiers (context, serial,
+ mods_depressed, mods_depressed,
+ mods_latched, group);
+}
+
+static const struct wl_keyboard_listener keyboard_listener = {
+ input_method_keyboard_keymap,
+ NULL, /* enter */
+ NULL, /* leave */
+ input_method_keyboard_key,
+ input_method_keyboard_modifiers
+};
+
+static void
+_create_input_context_done (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ IBusWaylandIM *wlim = (IBusWaylandIM *) user_data;
+
+ GError *error = NULL;
+ IBusInputContext *context = ibus_bus_create_input_context_async_finish (
+ _bus, res, &error);
+
+ if (wlim->cancellable != NULL) {
+ g_object_unref (wlim->cancellable);
+ wlim->cancellable = NULL;
+ }
+
+ if (context == NULL) {
+ g_warning ("Create input context failed: %s.", error->message);
+ g_error_free (error);
+ }
+ else {
+ wlim->ibuscontext = context;
+
+ g_signal_connect (wlim->ibuscontext, "commit-text",
+ G_CALLBACK (_context_commit_text_cb),
+ wlim);
+ g_signal_connect (wlim->ibuscontext, "forward-key-event",
+ G_CALLBACK (_context_forward_key_event_cb),
+ wlim);
+
+ g_signal_connect (wlim->ibuscontext, "update-preedit-text",
+ G_CALLBACK (_context_update_preedit_text_cb),
+ wlim);
+ g_signal_connect (wlim->ibuscontext, "show-preedit-text",
+ G_CALLBACK (_context_show_preedit_text_cb),
+ wlim);
+ g_signal_connect (wlim->ibuscontext, "hide-preedit-text",
+ G_CALLBACK (_context_hide_preedit_text_cb),
+ wlim);
+
+#ifdef ENABLE_SURROUNDING
+ ibus_input_context_set_capabilities (wlim->ibuscontext,
+ IBUS_CAP_FOCUS |
+ IBUS_CAP_PREEDIT_TEXT |
+ IBUS_CAP_SURROUNDING_TEXT);
+#else
+ ibus_input_context_set_capabilities (wlim->ibuscontext,
+ IBUS_CAP_FOCUS |
+ IBUS_CAP_PREEDIT_TEXT);
+#endif
+
+ ibus_input_context_focus_in (wlim->ibuscontext);
+ }
+}
+
+static void
+input_method_activate (void *data,
+ struct wl_input_method *input_method,
+ struct wl_input_method_context *context)
+{
+ IBusWaylandIM *wlim = data;
+
+ if (wlim->context) {
+ wl_input_method_context_destroy (wlim->context);
+ wlim->context = NULL;
+ }
+
+ wlim->serial = 0;
+ wlim->context = context;
+
+ wl_input_method_context_add_listener (context, &context_listener, wlim);
+ wlim->keyboard = wl_input_method_context_grab_keyboard (context);
+ wl_keyboard_add_listener(wlim->keyboard,
+ &keyboard_listener,
+ wlim);
+
+ if (wlim->ibuscontext) {
+ g_object_unref (wlim->ibuscontext);
+ wlim->ibuscontext = NULL;
+ }
+
+ wlim->cancellable = g_cancellable_new ();
+ ibus_bus_create_input_context_async (_bus,
+ "wayland",
+ -1,
+ wlim->cancellable,
+ _create_input_context_done,
+ wlim);
+}
+
+static void
+input_method_deactivate (void *data,
+ struct wl_input_method *input_method,
+ struct wl_input_method_context *context)
+{
+ IBusWaylandIM *wlim = data;
+
+ if (wlim->cancellable) {
+ /* Cancel any ongoing create input context request. */
+ g_cancellable_cancel (wlim->cancellable);
+ g_object_unref (wlim->cancellable);
+ wlim->cancellable = NULL;
+ }
+
+ if (wlim->ibuscontext) {
+ ibus_input_context_focus_out (wlim->ibuscontext);
+ g_object_unref (wlim->ibuscontext);
+ wlim->ibuscontext = NULL;
+ }
+
+ if (wlim->preedit_text) {
+ g_object_unref (wlim->preedit_text);
+ wlim->preedit_text = NULL;
+ }
+
+ if (wlim->context) {
+ wl_input_method_context_destroy (wlim->context);
+ wlim->context = NULL;
+ }
+}
+
+static const struct wl_input_method_listener input_method_listener = {
+ input_method_activate,
+ input_method_deactivate
+};
+
+static void
+registry_handle_global (void *data,
+ struct wl_registry *registry,
+ uint32_t name,
+ const char *interface,
+ uint32_t version)
+{
+ IBusWaylandIM *wlim = data;
+
+ if (!g_strcmp0 (interface, "wl_input_method")) {
+ wlim->input_method =
+ wl_registry_bind (registry, name, &wl_input_method_interface, 1);
+ wl_input_method_add_listener (wlim->input_method,
+ &input_method_listener, wlim);
+ }
+}
+
+static void
+registry_handle_global_remove (void *data,
+ struct wl_registry *registry,
+ uint32_t name)
+{
+}
+
+static const struct wl_registry_listener registry_listener = {
+ registry_handle_global,
+ registry_handle_global_remove
+};
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+ IBusWaylandIM wlim;
+ GSource *source;
+
+ ibus_init ();
+
+ _bus = ibus_bus_new ();
+ if (!ibus_bus_is_connected (_bus)) {
+ g_printerr ("Cannot connect to ibus-daemon\n");
+ return EXIT_FAILURE;
+ }
+
+ _display = wl_display_connect (NULL);
+ if (_display == NULL) {
+ g_printerr ("Failed to connect to Wayland server: %s\n",
+ g_strerror (errno));
+ return EXIT_FAILURE;
+ }
+
+ _registry = wl_display_get_registry (_display);
+ memset (&wlim, 0, sizeof (wlim));
+ wl_registry_add_listener (_registry, ®istry_listener, &wlim);
+ wl_display_roundtrip (_display);
+ if (wlim.input_method == NULL) {
+ g_printerr ("No input_method global\n");
+ return EXIT_FAILURE;
+ }
+
+ wlim.xkb_context = xkb_context_new (0);
+ if (wlim.xkb_context == NULL) {
+ g_printerr ("Failed to create XKB context\n");
+ return EXIT_FAILURE;
+ }
+
+ _use_sync_mode = _get_boolean_env ("IBUS_ENABLE_SYNC_MODE", FALSE);
+
+ source = ibus_wayland_source_new (_display);
+ g_source_set_priority (source, G_PRIORITY_DEFAULT);
+ g_source_set_can_recurse (source, TRUE);
+ g_source_attach (source, NULL);
+
+ ibus_main ();
+
+ return EXIT_SUCCESS;
+}
)
AM_CONDITIONAL([ENABLE_XIM], [test x"$enable_xim" = x"yes"])
+# --enable-wayland option.
+AC_ARG_ENABLE(wayland,
+ AS_HELP_STRING([--enable-wayland],
+ [Build wayland support]),
+ [enable_wayland=$enableval],
+ [enable_wayland=no]
+)
+AM_CONDITIONAL([ENABLE_WAYLAND], [test x"$enable_wayland" = x"yes"])
+
if test x"$enable_gtk2" = x"yes" -o x"$enable_xim" = x"yes" ; then
# check for gtk2
PKG_CHECK_MODULES(GTK2, [
enable_xim="no (disabled, use --enable-xim to enable)"
fi
+if test x"$enable_wayland" = x"yes"; then
+ # Check for wayland
+ PKG_CHECK_MODULES(WAYLAND, [
+ wayland-client >= 1.2.0
+ xkbcommon
+ ])
+else
+ enable_wayland="no (disabled, use --enable-wayland to enable)"
+fi
+
# GObject introspection
GOBJECT_INTROSPECTION_CHECK([0.6.8])
client/gtk2/Makefile
client/gtk3/Makefile
client/x11/Makefile
+client/wayland/Makefile
src/Makefile
src/ibusversion.h
src/tests/Makefile
Build gtk2 immodule $enable_gtk2
Build gtk3 immodule $enable_gtk3
Build XIM agent server $enable_xim
+ Build wayland support $enable_wayland
Build python library $enable_python_library
Build gconf modules $enable_gconf
Build memconf modules $enable_memconf