|
Packit |
3ff832 |
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
|
|
Packit |
3ff832 |
/* vim:set et sts=4: */
|
|
Packit |
3ff832 |
/* ibus - The Input Bus
|
|
Packit |
3ff832 |
* Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
|
|
Packit Service |
fd1217 |
* Copyright (C) 2015-2019 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
Packit Service |
fd1217 |
* Copyright (C) 2008-2019 Red Hat, Inc.
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
3ff832 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
3ff832 |
* License as published by the Free Software Foundation; either
|
|
Packit |
3ff832 |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
3ff832 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
3ff832 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
3ff832 |
* Lesser General Public License for more details.
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
3ff832 |
* License along with this library; if not, write to the Free Software
|
|
Packit |
3ff832 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
Packit |
3ff832 |
* USA
|
|
Packit |
3ff832 |
*/
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
3ff832 |
# include <config.h>
|
|
Packit |
3ff832 |
#endif
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
#include <string.h>
|
|
Packit |
3ff832 |
#include <gtk/gtk.h>
|
|
Packit |
3ff832 |
#include <gdk/gdkkeysyms.h>
|
|
Packit |
3ff832 |
#include <ibus.h>
|
|
Packit |
3ff832 |
#include "ibusimcontext.h"
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
#ifdef GDK_WINDOWING_WAYLAND
|
|
Packit |
3ff832 |
#include <gdk/gdkwayland.h>
|
|
Packit |
3ff832 |
#endif
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
#if !GTK_CHECK_VERSION (2, 91, 0)
|
|
Packit |
3ff832 |
# define DEPRECATED_GDK_KEYSYMS 1
|
|
Packit |
3ff832 |
#endif
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
#ifdef DEBUG
|
|
Packit |
3ff832 |
# define IDEBUG g_debug
|
|
Packit |
3ff832 |
#else
|
|
Packit |
3ff832 |
# define IDEBUG(a...)
|
|
Packit |
3ff832 |
#endif
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
#define MAX_QUEUED_EVENTS 20
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
struct _IBusIMContext {
|
|
Packit |
3ff832 |
GtkIMContext parent;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* instance members */
|
|
Packit |
3ff832 |
GtkIMContext *slave;
|
|
Packit |
3ff832 |
GdkWindow *client_window;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
IBusInputContext *ibuscontext;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* preedit status */
|
|
Packit |
3ff832 |
gchar *preedit_string;
|
|
Packit |
3ff832 |
PangoAttrList *preedit_attrs;
|
|
Packit |
3ff832 |
gint preedit_cursor_pos;
|
|
Packit |
3ff832 |
gboolean preedit_visible;
|
|
Packit Service |
fd1217 |
guint preedit_mode;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
GdkRectangle cursor_area;
|
|
Packit |
3ff832 |
gboolean has_focus;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
guint32 time;
|
|
Packit |
3ff832 |
gint caps;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* cancellable */
|
|
Packit |
3ff832 |
GCancellable *cancellable;
|
|
Packit |
3ff832 |
GQueue *events_queue;
|
|
Packit Service |
fd1217 |
|
|
Packit Service |
fd1217 |
#if !GTK_CHECK_VERSION (3, 93, 0)
|
|
Packit Service |
fd1217 |
gboolean use_button_press_event;
|
|
Packit Service |
fd1217 |
#endif
|
|
Packit |
3ff832 |
};
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
struct _IBusIMContextClass {
|
|
Packit |
3ff832 |
GtkIMContextClass parent;
|
|
Packit |
3ff832 |
/* class members */
|
|
Packit |
3ff832 |
};
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static guint _signal_commit_id = 0;
|
|
Packit |
3ff832 |
static guint _signal_preedit_changed_id = 0;
|
|
Packit |
3ff832 |
static guint _signal_preedit_start_id = 0;
|
|
Packit |
3ff832 |
static guint _signal_preedit_end_id = 0;
|
|
Packit |
3ff832 |
static guint _signal_delete_surrounding_id = 0;
|
|
Packit |
3ff832 |
static guint _signal_retrieve_surrounding_id = 0;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static const gchar *_no_snooper_apps = NO_SNOOPER_APPS;
|
|
Packit |
3ff832 |
static gboolean _use_key_snooper = ENABLE_SNOOPER;
|
|
Packit |
3ff832 |
static guint _key_snooper_id = 0;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gboolean _use_sync_mode = FALSE;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static const gchar *_discard_password_apps = "";
|
|
Packit |
3ff832 |
static gboolean _use_discard_password = FALSE;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static GtkIMContext *_focus_im_context = NULL;
|
|
Packit |
3ff832 |
static IBusInputContext *_fake_context = NULL;
|
|
Packit |
3ff832 |
static GdkWindow *_input_window = NULL;
|
|
Packit |
3ff832 |
static GtkWidget *_input_widget = NULL;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* functions prototype */
|
|
Packit |
3ff832 |
static void ibus_im_context_class_init (IBusIMContextClass *class);
|
|
Packit |
3ff832 |
static void ibus_im_context_class_fini (IBusIMContextClass *class);
|
|
Packit |
3ff832 |
static void ibus_im_context_init (GObject *obj);
|
|
Packit |
3ff832 |
static void ibus_im_context_notify (GObject *obj,
|
|
Packit |
3ff832 |
GParamSpec *pspec);
|
|
Packit |
3ff832 |
static void ibus_im_context_finalize (GObject *obj);
|
|
Packit |
3ff832 |
static void ibus_im_context_reset (GtkIMContext *context);
|
|
Packit |
3ff832 |
static gboolean ibus_im_context_filter_keypress
|
|
Packit |
3ff832 |
(GtkIMContext *context,
|
|
Packit |
3ff832 |
GdkEventKey *key);
|
|
Packit |
3ff832 |
static void ibus_im_context_focus_in (GtkIMContext *context);
|
|
Packit |
3ff832 |
static void ibus_im_context_focus_out (GtkIMContext *context);
|
|
Packit |
3ff832 |
static void ibus_im_context_get_preedit_string
|
|
Packit |
3ff832 |
(GtkIMContext *context,
|
|
Packit |
3ff832 |
gchar **str,
|
|
Packit |
3ff832 |
PangoAttrList **attrs,
|
|
Packit |
3ff832 |
gint *cursor_pos);
|
|
Packit |
3ff832 |
static void ibus_im_context_set_client_window
|
|
Packit |
3ff832 |
(GtkIMContext *context,
|
|
Packit |
3ff832 |
GdkWindow *client);
|
|
Packit |
3ff832 |
static void ibus_im_context_set_cursor_location
|
|
Packit |
3ff832 |
(GtkIMContext *context,
|
|
Packit |
3ff832 |
GdkRectangle *area);
|
|
Packit |
3ff832 |
static void ibus_im_context_set_use_preedit
|
|
Packit |
3ff832 |
(GtkIMContext *context,
|
|
Packit |
3ff832 |
gboolean use_preedit);
|
|
Packit |
3ff832 |
static void ibus_im_context_set_surrounding
|
|
Packit |
3ff832 |
(GtkIMContext *slave,
|
|
Packit |
3ff832 |
const gchar *text,
|
|
Packit |
3ff832 |
gint len,
|
|
Packit |
3ff832 |
gint cursor_index);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* static methods*/
|
|
Packit Service |
fd1217 |
static void _ibus_context_update_preedit_text_cb
|
|
Packit Service |
fd1217 |
(IBusInputContext *ibuscontext,
|
|
Packit Service |
fd1217 |
IBusText *text,
|
|
Packit Service |
fd1217 |
gint cursor_pos,
|
|
Packit Service |
fd1217 |
gboolean visible,
|
|
Packit Service |
fd1217 |
guint mode,
|
|
Packit Service |
fd1217 |
IBusIMContext *ibusimcontext);
|
|
Packit |
3ff832 |
static void _create_input_context (IBusIMContext *context);
|
|
Packit |
3ff832 |
static gboolean _set_cursor_location_internal
|
|
Packit |
3ff832 |
(IBusIMContext *context);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void _bus_connected_cb (IBusBus *bus,
|
|
Packit |
3ff832 |
IBusIMContext *context);
|
|
Packit |
3ff832 |
/* callback functions for slave context */
|
|
Packit |
3ff832 |
static void _slave_commit_cb (GtkIMContext *slave,
|
|
Packit |
3ff832 |
gchar *string,
|
|
Packit |
3ff832 |
IBusIMContext *context);
|
|
Packit |
3ff832 |
static void _slave_preedit_changed_cb (GtkIMContext *slave,
|
|
Packit |
3ff832 |
IBusIMContext *context);
|
|
Packit |
3ff832 |
static void _slave_preedit_start_cb (GtkIMContext *slave,
|
|
Packit |
3ff832 |
IBusIMContext *context);
|
|
Packit |
3ff832 |
static void _slave_preedit_end_cb (GtkIMContext *slave,
|
|
Packit |
3ff832 |
IBusIMContext *context);
|
|
Packit |
3ff832 |
static gboolean _slave_retrieve_surrounding_cb
|
|
Packit |
3ff832 |
(GtkIMContext *slave,
|
|
Packit |
3ff832 |
IBusIMContext *context);
|
|
Packit |
3ff832 |
static gboolean _slave_delete_surrounding_cb
|
|
Packit |
3ff832 |
(GtkIMContext *slave,
|
|
Packit |
3ff832 |
gint offset_from_cursor,
|
|
Packit |
3ff832 |
guint nchars,
|
|
Packit |
3ff832 |
IBusIMContext *context);
|
|
Packit |
3ff832 |
static void _request_surrounding_text (IBusIMContext *context);
|
|
Packit |
3ff832 |
static void _create_fake_input_context (void);
|
|
Packit |
3ff832 |
static gboolean _set_content_type (IBusIMContext *context);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static GType _ibus_type_im_context = 0;
|
|
Packit |
3ff832 |
static GtkIMContextClass *parent_class = NULL;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static IBusBus *_bus = NULL;
|
|
Packit |
3ff832 |
static guint _daemon_name_watch_id = 0;
|
|
Packit |
3ff832 |
static gboolean _daemon_is_running = FALSE;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
void
|
|
Packit |
3ff832 |
ibus_im_context_register_type (GTypeModule *type_module)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static const GTypeInfo ibus_im_context_info = {
|
|
Packit |
3ff832 |
sizeof (IBusIMContextClass),
|
|
Packit |
3ff832 |
(GBaseInitFunc) NULL,
|
|
Packit |
3ff832 |
(GBaseFinalizeFunc) NULL,
|
|
Packit |
3ff832 |
(GClassInitFunc) ibus_im_context_class_init,
|
|
Packit |
3ff832 |
(GClassFinalizeFunc) ibus_im_context_class_fini,
|
|
Packit |
3ff832 |
NULL, /* class data */
|
|
Packit |
3ff832 |
sizeof (IBusIMContext),
|
|
Packit |
3ff832 |
0,
|
|
Packit |
3ff832 |
(GInstanceInitFunc) ibus_im_context_init,
|
|
Packit |
3ff832 |
};
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (!_ibus_type_im_context) {
|
|
Packit |
3ff832 |
if (type_module) {
|
|
Packit |
3ff832 |
_ibus_type_im_context =
|
|
Packit |
3ff832 |
g_type_module_register_type (type_module,
|
|
Packit |
3ff832 |
GTK_TYPE_IM_CONTEXT,
|
|
Packit |
3ff832 |
"IBusIMContext",
|
|
Packit |
3ff832 |
&ibus_im_context_info,
|
|
Packit |
3ff832 |
(GTypeFlags)0);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
else {
|
|
Packit |
3ff832 |
_ibus_type_im_context =
|
|
Packit |
3ff832 |
g_type_register_static (GTK_TYPE_IM_CONTEXT,
|
|
Packit |
3ff832 |
"IBusIMContext",
|
|
Packit |
3ff832 |
&ibus_im_context_info,
|
|
Packit |
3ff832 |
(GTypeFlags)0);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
GType
|
|
Packit |
3ff832 |
ibus_im_context_get_type (void)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (_ibus_type_im_context == 0) {
|
|
Packit |
3ff832 |
ibus_im_context_register_type (NULL);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_assert (_ibus_type_im_context != 0);
|
|
Packit |
3ff832 |
return _ibus_type_im_context;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
IBusIMContext *
|
|
Packit |
3ff832 |
ibus_im_context_new (void)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
GObject *obj = g_object_new (IBUS_TYPE_IM_CONTEXT, NULL);
|
|
Packit |
3ff832 |
return IBUS_IM_CONTEXT (obj);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gboolean
|
|
Packit |
3ff832 |
_focus_in_cb (GtkWidget *widget,
|
|
Packit |
3ff832 |
GdkEventFocus *event,
|
|
Packit |
3ff832 |
gpointer user_data)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
if (_focus_im_context == NULL && _fake_context != NULL) {
|
|
Packit |
3ff832 |
ibus_input_context_focus_in (_fake_context);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gboolean
|
|
Packit |
3ff832 |
_focus_out_cb (GtkWidget *widget,
|
|
Packit |
3ff832 |
GdkEventFocus *event,
|
|
Packit |
3ff832 |
gpointer user_data)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
if (_focus_im_context == NULL && _fake_context != NULL) {
|
|
Packit |
3ff832 |
ibus_input_context_focus_out (_fake_context);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gboolean
|
|
Packit |
3ff832 |
ibus_im_context_commit_event (IBusIMContext *ibusimcontext,
|
|
Packit |
3ff832 |
GdkEventKey *event)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
int i;
|
|
Packit |
3ff832 |
GdkModifierType no_text_input_mask;
|
|
Packit |
3ff832 |
gunichar ch;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (event->type == GDK_KEY_RELEASE)
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
/* Ignore modifier key presses */
|
|
Packit |
3ff832 |
for (i = 0; i < G_N_ELEMENTS (IBUS_COMPOSE_IGNORE_KEYLIST); i++)
|
|
Packit |
3ff832 |
if (event->keyval == IBUS_COMPOSE_IGNORE_KEYLIST[i])
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
#if GTK_CHECK_VERSION (3, 4, 0)
|
|
Packit |
3ff832 |
no_text_input_mask = gdk_keymap_get_modifier_mask (
|
|
Packit |
3ff832 |
gdk_keymap_get_for_display (gdk_display_get_default ()),
|
|
Packit |
3ff832 |
GDK_MODIFIER_INTENT_NO_TEXT_INPUT);
|
|
Packit |
3ff832 |
#else
|
|
Packit |
3ff832 |
# ifndef GDK_WINDOWING_QUARTZ
|
|
Packit |
3ff832 |
# define _IBUS_NO_TEXT_INPUT_MOD_MASK (GDK_MOD1_MASK | GDK_CONTROL_MASK)
|
|
Packit |
3ff832 |
# else
|
|
Packit |
3ff832 |
# define _IBUS_NO_TEXT_INPUT_MOD_MASK (GDK_MOD2_MASK | GDK_CONTROL_MASK)
|
|
Packit |
3ff832 |
# endif
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
no_text_input_mask = _IBUS_NO_TEXT_INPUT_MOD_MASK;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
# undef _IBUS_NO_TEXT_INPUT_MOD_MASK
|
|
Packit |
3ff832 |
#endif
|
|
Packit |
3ff832 |
if (event->state & no_text_input_mask ||
|
|
Packit |
3ff832 |
event->keyval == GDK_KEY_Return ||
|
|
Packit |
3ff832 |
event->keyval == GDK_KEY_ISO_Enter ||
|
|
Packit |
3ff832 |
event->keyval == GDK_KEY_KP_Enter) {
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
ch = ibus_keyval_to_unicode (event->keyval);
|
|
Packit |
3ff832 |
if (ch != 0 && !g_unichar_iscntrl (ch)) {
|
|
Packit |
3ff832 |
IBusText *text = ibus_text_new_from_unichar (ch);
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_commit_id, 0, text->text);
|
|
Packit |
3ff832 |
g_object_unref (text);
|
|
Packit Service |
fd1217 |
_request_surrounding_text (ibusimcontext);
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_process_key_event_done (GObject *object,
|
|
Packit |
3ff832 |
GAsyncResult *res,
|
|
Packit |
3ff832 |
gpointer user_data)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IBusInputContext *context = (IBusInputContext *)object;
|
|
Packit |
3ff832 |
GdkEventKey *event = (GdkEventKey *) user_data;
|
|
Packit |
3ff832 |
GError *error = NULL;
|
|
Packit |
3ff832 |
gboolean retval = ibus_input_context_process_key_event_async_finish (
|
|
Packit |
3ff832 |
context,
|
|
Packit |
3ff832 |
res,
|
|
Packit |
3ff832 |
&error);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (error != NULL) {
|
|
Packit |
3ff832 |
g_warning ("Process Key Event failed: %s.", error->message);
|
|
Packit |
3ff832 |
g_error_free (error);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (retval == FALSE) {
|
|
Packit |
3ff832 |
event->state |= IBUS_IGNORED_MASK;
|
|
Packit |
3ff832 |
gdk_event_put ((GdkEvent *)event);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
gdk_event_free ((GdkEvent *)event);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gboolean
|
|
Packit |
3ff832 |
_process_key_event (IBusInputContext *context,
|
|
Packit |
3ff832 |
GdkEventKey *event)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
guint state = event->state;
|
|
Packit |
3ff832 |
gboolean retval = FALSE;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (event->type == GDK_KEY_RELEASE) {
|
|
Packit |
3ff832 |
state |= IBUS_RELEASE_MASK;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (_use_sync_mode) {
|
|
Packit |
3ff832 |
retval = ibus_input_context_process_key_event (context,
|
|
Packit |
3ff832 |
event->keyval,
|
|
Packit |
3ff832 |
event->hardware_keycode - 8,
|
|
Packit |
3ff832 |
state);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
else {
|
|
Packit |
3ff832 |
ibus_input_context_process_key_event_async (context,
|
|
Packit |
3ff832 |
event->keyval,
|
|
Packit |
3ff832 |
event->hardware_keycode - 8,
|
|
Packit |
3ff832 |
state,
|
|
Packit |
3ff832 |
-1,
|
|
Packit |
3ff832 |
NULL,
|
|
Packit |
3ff832 |
_process_key_event_done,
|
|
Packit |
3ff832 |
gdk_event_copy ((GdkEvent *) event));
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
retval = TRUE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit Service |
fd1217 |
if (retval)
|
|
Packit |
3ff832 |
event->state |= IBUS_HANDLED_MASK;
|
|
Packit Service |
fd1217 |
else
|
|
Packit |
3ff832 |
event->state |= IBUS_IGNORED_MASK;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
return retval;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* emit "retrieve-surrounding" glib signal of GtkIMContext, if
|
|
Packit |
3ff832 |
* context->caps has IBUS_CAP_SURROUNDING_TEXT and the current IBus
|
|
Packit |
3ff832 |
* engine needs surrounding-text.
|
|
Packit |
3ff832 |
*/
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_request_surrounding_text (IBusIMContext *context)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
if (context &&
|
|
Packit |
3ff832 |
(context->caps & IBUS_CAP_SURROUNDING_TEXT) != 0 &&
|
|
Packit |
3ff832 |
context->ibuscontext != NULL &&
|
|
Packit |
3ff832 |
ibus_input_context_needs_surrounding_text (context->ibuscontext)) {
|
|
Packit |
3ff832 |
gboolean return_value;
|
|
Packit |
3ff832 |
IDEBUG ("requesting surrounding text");
|
|
Packit |
3ff832 |
g_signal_emit (context, _signal_retrieve_surrounding_id, 0,
|
|
Packit |
3ff832 |
&return_value);
|
|
Packit |
3ff832 |
if (!return_value) {
|
|
Packit Service |
fd1217 |
/* #2054 firefox::IMContextWrapper::GetCurrentParagraph() could
|
|
Packit Service |
fd1217 |
* fail with the first typing on firefox but it succeeds with
|
|
Packit Service |
fd1217 |
* the second typing.
|
|
Packit Service |
fd1217 |
*/
|
|
Packit Service |
fd1217 |
g_warning ("%s has no capability of surrounding-text feature",
|
|
Packit Service |
fd1217 |
g_get_prgname ());
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gboolean
|
|
Packit |
3ff832 |
_set_content_type (IBusIMContext *context)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
#if GTK_CHECK_VERSION (3, 6, 0)
|
|
Packit |
3ff832 |
if (context->ibuscontext != NULL) {
|
|
Packit |
3ff832 |
GtkInputPurpose purpose;
|
|
Packit |
3ff832 |
GtkInputHints hints;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_object_get (G_OBJECT (context),
|
|
Packit |
3ff832 |
"input-purpose", &purpose,
|
|
Packit |
3ff832 |
"input-hints", &hints,
|
|
Packit |
3ff832 |
NULL);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (_use_discard_password) {
|
|
Packit |
3ff832 |
if (purpose == GTK_INPUT_PURPOSE_PASSWORD ||
|
|
Packit |
3ff832 |
purpose == GTK_INPUT_PURPOSE_PIN) {
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
ibus_input_context_set_content_type (context->ibuscontext,
|
|
Packit |
3ff832 |
purpose,
|
|
Packit |
3ff832 |
hints);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
#endif
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gint
|
|
Packit |
3ff832 |
_key_snooper_cb (GtkWidget *widget,
|
|
Packit |
3ff832 |
GdkEventKey *event,
|
|
Packit |
3ff832 |
gpointer user_data)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
gboolean retval = FALSE;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext = NULL;
|
|
Packit |
3ff832 |
IBusInputContext *ibuscontext = NULL;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (!_use_key_snooper)
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (_focus_im_context != NULL &&
|
|
Packit |
3ff832 |
((IBusIMContext *) _focus_im_context)->has_focus == TRUE) {
|
|
Packit |
3ff832 |
ibusimcontext = (IBusIMContext *) _focus_im_context;
|
|
Packit |
3ff832 |
/* has IC with focus */
|
|
Packit |
3ff832 |
ibuscontext = ibusimcontext->ibuscontext;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
else {
|
|
Packit |
3ff832 |
/* If no IC has focus, and fake IC has been created, then pass key events to fake IC. */
|
|
Packit |
3ff832 |
ibuscontext = _fake_context;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibuscontext == NULL)
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (G_UNLIKELY (event->state & IBUS_HANDLED_MASK))
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (G_UNLIKELY (event->state & IBUS_IGNORED_MASK))
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
do {
|
|
Packit |
3ff832 |
if (_fake_context != ibuscontext)
|
|
Packit |
3ff832 |
break;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* window has input focus is not changed */
|
|
Packit |
3ff832 |
if (_input_window == event->window)
|
|
Packit |
3ff832 |
break;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (_input_window != NULL) {
|
|
Packit |
3ff832 |
g_object_remove_weak_pointer ((GObject *) _input_window,
|
|
Packit |
3ff832 |
(gpointer *) &_input_window);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
if (event->window != NULL) {
|
|
Packit |
3ff832 |
g_object_add_weak_pointer ((GObject *) event->window,
|
|
Packit |
3ff832 |
(gpointer *) &_input_window);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
_input_window = event->window;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* Trace widget has input focus, and listen focus events of it.
|
|
Packit |
3ff832 |
* It is workaround for Alt+Shift+Tab shortcut key issue(crosbug.com/8855).
|
|
Packit |
3ff832 |
* gtk_get_event_widget returns the widget that is associated with the
|
|
Packit |
3ff832 |
* GdkWindow of the GdkEvent.
|
|
Packit |
3ff832 |
* */
|
|
Packit |
3ff832 |
GtkWidget *widget = gtk_get_event_widget ((GdkEvent *)event);
|
|
Packit |
3ff832 |
/* g_assert (_input_widget != widget). */
|
|
Packit |
3ff832 |
if (_input_widget == widget)
|
|
Packit |
3ff832 |
break;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (_input_widget != NULL) {
|
|
Packit |
3ff832 |
g_signal_handlers_disconnect_by_func (_input_widget,
|
|
Packit |
3ff832 |
(GCallback) _focus_in_cb,
|
|
Packit |
3ff832 |
NULL);
|
|
Packit |
3ff832 |
g_signal_handlers_disconnect_by_func (_input_widget,
|
|
Packit |
3ff832 |
(GCallback) _focus_out_cb,
|
|
Packit |
3ff832 |
NULL);
|
|
Packit |
3ff832 |
g_object_remove_weak_pointer ((GObject *) _input_widget,
|
|
Packit |
3ff832 |
(gpointer *) &_input_widget);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (widget != NULL) {
|
|
Packit |
3ff832 |
g_signal_connect (widget,
|
|
Packit |
3ff832 |
"focus-in-event",
|
|
Packit |
3ff832 |
(GCallback) _focus_in_cb,
|
|
Packit |
3ff832 |
NULL);
|
|
Packit |
3ff832 |
g_signal_connect (widget,
|
|
Packit |
3ff832 |
"focus-out-event",
|
|
Packit |
3ff832 |
(GCallback) _focus_out_cb,
|
|
Packit |
3ff832 |
NULL);
|
|
Packit |
3ff832 |
g_object_add_weak_pointer ((GObject *) widget,
|
|
Packit |
3ff832 |
(gpointer *) &_input_widget);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
_input_widget = widget;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
} while (0);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext != NULL) {
|
|
Packit |
3ff832 |
/* "retrieve-surrounding" signal sometimes calls unref by
|
|
Packit |
3ff832 |
* gtk_im_multicontext_get_slave() because priv->context_id is not
|
|
Packit |
3ff832 |
* the latest than global_context_id in GtkIMMulticontext.
|
|
Packit |
3ff832 |
* Since _focus_im_context is gotten by the focus_in event,
|
|
Packit |
3ff832 |
* it would be good to call ref here.
|
|
Packit |
3ff832 |
*/
|
|
Packit |
3ff832 |
g_object_ref (ibusimcontext);
|
|
Packit |
3ff832 |
_request_surrounding_text (ibusimcontext);
|
|
Packit |
3ff832 |
ibusimcontext->time = event->time;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
retval = _process_key_event (ibuscontext, event);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext != NULL) {
|
|
Packit |
3ff832 |
/* unref ibusimcontext could call ibus_im_context_finalize here
|
|
Packit |
3ff832 |
* because "retrieve-surrounding" signal could call unref.
|
|
Packit |
3ff832 |
*/
|
|
Packit |
3ff832 |
g_object_unref (ibusimcontext);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
return retval;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gboolean
|
|
Packit |
3ff832 |
_get_boolean_env(const gchar *name,
|
|
Packit |
3ff832 |
gboolean defval)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
const gchar *value = g_getenv (name);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (value == NULL)
|
|
Packit |
3ff832 |
return defval;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (g_strcmp0 (value, "") == 0 ||
|
|
Packit |
3ff832 |
g_strcmp0 (value, "0") == 0 ||
|
|
Packit |
3ff832 |
g_strcmp0 (value, "false") == 0 ||
|
|
Packit |
3ff832 |
g_strcmp0 (value, "False") == 0 ||
|
|
Packit |
3ff832 |
g_strcmp0 (value, "FALSE") == 0)
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
daemon_name_appeared (GDBusConnection *connection,
|
|
Packit |
3ff832 |
const gchar *name,
|
|
Packit |
3ff832 |
const gchar *owner,
|
|
Packit |
3ff832 |
gpointer data)
|
|
Packit |
3ff832 |
{
|
|
Packit Service |
fd1217 |
if (!g_strcmp0 (ibus_bus_get_service_name (_bus), IBUS_SERVICE_PORTAL)) {
|
|
Packit Service |
fd1217 |
_daemon_is_running = TRUE;
|
|
Packit Service |
fd1217 |
return;
|
|
Packit Service |
fd1217 |
}
|
|
Packit |
3ff832 |
/* If ibus-daemon is running and run ssh -X localhost,
|
|
Packit |
3ff832 |
* daemon_name_appeared() is called but ibus_get_address() == NULL
|
|
Packit |
3ff832 |
* because the hostname and display number are different between
|
|
Packit |
3ff832 |
* ibus-daemon and clients. So IBusBus would not be connected and
|
|
Packit |
3ff832 |
* ibusimcontext->ibuscontext == NULL and ibusimcontext->events_queue
|
|
Packit |
3ff832 |
* could go beyond MAX_QUEUED_EVENTS . */
|
|
Packit |
3ff832 |
_daemon_is_running = (ibus_get_address () != NULL);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
daemon_name_vanished (GDBusConnection *connection,
|
|
Packit |
3ff832 |
const gchar *name,
|
|
Packit |
3ff832 |
gpointer data)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
_daemon_is_running = FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_im_context_class_init (IBusIMContextClass *class)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
GtkIMContextClass *im_context_class = GTK_IM_CONTEXT_CLASS (class);
|
|
Packit |
3ff832 |
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
parent_class = (GtkIMContextClass *) g_type_class_peek_parent (class);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
im_context_class->reset = ibus_im_context_reset;
|
|
Packit |
3ff832 |
im_context_class->focus_in = ibus_im_context_focus_in;
|
|
Packit |
3ff832 |
im_context_class->focus_out = ibus_im_context_focus_out;
|
|
Packit |
3ff832 |
im_context_class->filter_keypress = ibus_im_context_filter_keypress;
|
|
Packit |
3ff832 |
im_context_class->get_preedit_string = ibus_im_context_get_preedit_string;
|
|
Packit |
3ff832 |
im_context_class->set_client_window = ibus_im_context_set_client_window;
|
|
Packit |
3ff832 |
im_context_class->set_cursor_location = ibus_im_context_set_cursor_location;
|
|
Packit |
3ff832 |
im_context_class->set_use_preedit = ibus_im_context_set_use_preedit;
|
|
Packit |
3ff832 |
im_context_class->set_surrounding = ibus_im_context_set_surrounding;
|
|
Packit |
3ff832 |
gobject_class->notify = ibus_im_context_notify;
|
|
Packit |
3ff832 |
gobject_class->finalize = ibus_im_context_finalize;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
_signal_commit_id =
|
|
Packit |
3ff832 |
g_signal_lookup ("commit", G_TYPE_FROM_CLASS (class));
|
|
Packit |
3ff832 |
g_assert (_signal_commit_id != 0);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
_signal_preedit_changed_id =
|
|
Packit |
3ff832 |
g_signal_lookup ("preedit-changed", G_TYPE_FROM_CLASS (class));
|
|
Packit |
3ff832 |
g_assert (_signal_preedit_changed_id != 0);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
_signal_preedit_start_id =
|
|
Packit |
3ff832 |
g_signal_lookup ("preedit-start", G_TYPE_FROM_CLASS (class));
|
|
Packit |
3ff832 |
g_assert (_signal_preedit_start_id != 0);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
_signal_preedit_end_id =
|
|
Packit |
3ff832 |
g_signal_lookup ("preedit-end", G_TYPE_FROM_CLASS (class));
|
|
Packit |
3ff832 |
g_assert (_signal_preedit_end_id != 0);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
_signal_delete_surrounding_id =
|
|
Packit |
3ff832 |
g_signal_lookup ("delete-surrounding", G_TYPE_FROM_CLASS (class));
|
|
Packit |
3ff832 |
g_assert (_signal_delete_surrounding_id != 0);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
_signal_retrieve_surrounding_id =
|
|
Packit |
3ff832 |
g_signal_lookup ("retrieve-surrounding", G_TYPE_FROM_CLASS (class));
|
|
Packit |
3ff832 |
g_assert (_signal_retrieve_surrounding_id != 0);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
_use_key_snooper = !_get_boolean_env ("IBUS_DISABLE_SNOOPER",
|
|
Packit |
3ff832 |
!(ENABLE_SNOOPER));
|
|
Packit |
3ff832 |
_use_sync_mode = _get_boolean_env ("IBUS_ENABLE_SYNC_MODE", FALSE);
|
|
Packit |
3ff832 |
_use_discard_password = _get_boolean_env ("IBUS_DISCARD_PASSWORD", FALSE);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
#define CHECK_APP_IN_CSV_ENV_VARIABLES(retval, \
|
|
Packit |
3ff832 |
env_apps, \
|
|
Packit |
3ff832 |
fallback_apps, \
|
|
Packit |
3ff832 |
value_if_found) \
|
|
Packit |
3ff832 |
{ \
|
|
Packit |
3ff832 |
const gchar * prgname = g_get_prgname (); \
|
|
Packit |
3ff832 |
gchar **p; \
|
|
Packit |
3ff832 |
gchar ** apps; \
|
|
Packit |
3ff832 |
if (g_getenv ((#env_apps))) { \
|
|
Packit |
3ff832 |
fallback_apps = g_getenv (#env_apps); \
|
|
Packit |
3ff832 |
} \
|
|
Packit |
3ff832 |
apps = g_strsplit ((fallback_apps), ",", 0); \
|
|
Packit |
3ff832 |
for (p = apps; *p != NULL; p++) { \
|
|
Packit |
3ff832 |
if (g_regex_match_simple (*p, prgname, 0, 0)) { \
|
|
Packit |
3ff832 |
retval = (value_if_found); \
|
|
Packit |
3ff832 |
break; \
|
|
Packit |
3ff832 |
} \
|
|
Packit |
3ff832 |
} \
|
|
Packit |
3ff832 |
g_strfreev (apps); \
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* env IBUS_DISABLE_SNOOPER does not exist */
|
|
Packit |
3ff832 |
if (_use_key_snooper) {
|
|
Packit |
3ff832 |
/* disable snooper if app is in _no_snooper_apps */
|
|
Packit |
3ff832 |
CHECK_APP_IN_CSV_ENV_VARIABLES (_use_key_snooper,
|
|
Packit |
3ff832 |
IBUS_NO_SNOOPER_APPS,
|
|
Packit |
3ff832 |
_no_snooper_apps,
|
|
Packit |
3ff832 |
FALSE);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
if (!_use_discard_password) {
|
|
Packit |
3ff832 |
CHECK_APP_IN_CSV_ENV_VARIABLES (_use_discard_password,
|
|
Packit |
3ff832 |
IBUS_DISCARD_PASSWORD_APPS,
|
|
Packit |
3ff832 |
_discard_password_apps,
|
|
Packit |
3ff832 |
TRUE);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
#undef CHECK_APP_IN_CSV_ENV_VARIABLES
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* init bus object */
|
|
Packit |
3ff832 |
if (_bus == NULL) {
|
|
Packit |
3ff832 |
_bus = ibus_bus_new_async_client ();
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* init the global fake context */
|
|
Packit |
3ff832 |
if (ibus_bus_is_connected (_bus)) {
|
|
Packit |
3ff832 |
_create_fake_input_context ();
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_signal_connect (_bus, "connected", G_CALLBACK (_bus_connected_cb), NULL);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* always install snooper */
|
|
Packit |
3ff832 |
if (_key_snooper_id == 0) {
|
|
Packit |
3ff832 |
#pragma GCC diagnostic push
|
|
Packit |
3ff832 |
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
Packit |
3ff832 |
_key_snooper_id = gtk_key_snooper_install (_key_snooper_cb, NULL);
|
|
Packit |
3ff832 |
#pragma GCC diagnostic pop
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
_daemon_name_watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
|
|
Packit |
3ff832 |
ibus_bus_get_service_name (_bus),
|
|
Packit |
3ff832 |
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
|
Packit |
3ff832 |
daemon_name_appeared,
|
|
Packit |
3ff832 |
daemon_name_vanished,
|
|
Packit |
3ff832 |
NULL,
|
|
Packit |
3ff832 |
NULL);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_im_context_class_fini (IBusIMContextClass *class)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
if (_key_snooper_id != 0) {
|
|
Packit |
3ff832 |
IDEBUG ("snooper is terminated.");
|
|
Packit |
3ff832 |
#pragma GCC diagnostic push
|
|
Packit |
3ff832 |
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
Packit |
3ff832 |
gtk_key_snooper_remove (_key_snooper_id);
|
|
Packit |
3ff832 |
#pragma GCC diagnostic pop
|
|
Packit |
3ff832 |
_key_snooper_id = 0;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_bus_unwatch_name (_daemon_name_watch_id);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* Copied from gtk+2.0-2.20.1/modules/input/imcedilla.c to fix crosbug.com/11421.
|
|
Packit |
3ff832 |
* Overwrite the original Gtk+'s compose table in gtk+-2.x.y/gtk/gtkimcontextsimple.c. */
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* The difference between this and the default input method is the handling
|
|
Packit |
3ff832 |
* of C+acute - this method produces C WITH CEDILLA rather than C WITH ACUTE.
|
|
Packit |
3ff832 |
* For languages that use CCedilla and not acute, this is the preferred mapping,
|
|
Packit |
3ff832 |
* and is particularly important for pt_BR, where the us-intl keyboard is
|
|
Packit |
3ff832 |
* used extensively.
|
|
Packit |
3ff832 |
*/
|
|
Packit |
3ff832 |
static guint16 cedilla_compose_seqs[] = {
|
|
Packit |
3ff832 |
#ifdef DEPRECATED_GDK_KEYSYMS
|
|
Packit |
3ff832 |
GDK_dead_acute, GDK_C, 0, 0, 0, 0x00C7, /* LATIN_CAPITAL_LETTER_C_WITH_CEDILLA */
|
|
Packit |
3ff832 |
GDK_dead_acute, GDK_c, 0, 0, 0, 0x00E7, /* LATIN_SMALL_LETTER_C_WITH_CEDILLA */
|
|
Packit |
3ff832 |
GDK_Multi_key, GDK_apostrophe, GDK_C, 0, 0, 0x00C7, /* LATIN_CAPITAL_LETTER_C_WITH_CEDILLA */
|
|
Packit |
3ff832 |
GDK_Multi_key, GDK_apostrophe, GDK_c, 0, 0, 0x00E7, /* LATIN_SMALL_LETTER_C_WITH_CEDILLA */
|
|
Packit |
3ff832 |
GDK_Multi_key, GDK_C, GDK_apostrophe, 0, 0, 0x00C7, /* LATIN_CAPITAL_LETTER_C_WITH_CEDILLA */
|
|
Packit |
3ff832 |
GDK_Multi_key, GDK_c, GDK_apostrophe, 0, 0, 0x00E7, /* LATIN_SMALL_LETTER_C_WITH_CEDILLA */
|
|
Packit |
3ff832 |
#else
|
|
Packit |
3ff832 |
GDK_KEY_dead_acute, GDK_KEY_C, 0, 0, 0, 0x00C7, /* LATIN_CAPITAL_LETTER_C_WITH_CEDILLA */
|
|
Packit |
3ff832 |
GDK_KEY_dead_acute, GDK_KEY_c, 0, 0, 0, 0x00E7, /* LATIN_SMALL_LETTER_C_WITH_CEDILLA */
|
|
Packit |
3ff832 |
GDK_KEY_Multi_key, GDK_KEY_apostrophe, GDK_KEY_C, 0, 0, 0x00C7, /* LATIN_CAPITAL_LETTER_C_WITH_CEDILLA */
|
|
Packit |
3ff832 |
GDK_KEY_Multi_key, GDK_KEY_apostrophe, GDK_KEY_c, 0, 0, 0x00E7, /* LATIN_SMALL_LETTER_C_WITH_CEDILLA */
|
|
Packit |
3ff832 |
GDK_KEY_Multi_key, GDK_KEY_C, GDK_KEY_apostrophe, 0, 0, 0x00C7, /* LATIN_CAPITAL_LETTER_C_WITH_CEDILLA */
|
|
Packit |
3ff832 |
GDK_KEY_Multi_key, GDK_KEY_c, GDK_KEY_apostrophe, 0, 0, 0x00E7, /* LATIN_SMALL_LETTER_C_WITH_CEDILLA */
|
|
Packit |
3ff832 |
#endif
|
|
Packit |
3ff832 |
};
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_im_context_init (GObject *obj)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (obj);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
ibusimcontext->client_window = NULL;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
// Init preedit status
|
|
Packit |
3ff832 |
ibusimcontext->preedit_string = NULL;
|
|
Packit |
3ff832 |
ibusimcontext->preedit_attrs = NULL;
|
|
Packit |
3ff832 |
ibusimcontext->preedit_cursor_pos = 0;
|
|
Packit |
3ff832 |
ibusimcontext->preedit_visible = FALSE;
|
|
Packit Service |
fd1217 |
ibusimcontext->preedit_mode = IBUS_ENGINE_PREEDIT_CLEAR;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
// Init cursor area
|
|
Packit |
3ff832 |
ibusimcontext->cursor_area.x = -1;
|
|
Packit |
3ff832 |
ibusimcontext->cursor_area.y = -1;
|
|
Packit |
3ff832 |
ibusimcontext->cursor_area.width = 0;
|
|
Packit |
3ff832 |
ibusimcontext->cursor_area.height = 0;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
ibusimcontext->ibuscontext = NULL;
|
|
Packit |
3ff832 |
ibusimcontext->has_focus = FALSE;
|
|
Packit |
3ff832 |
ibusimcontext->time = GDK_CURRENT_TIME;
|
|
Packit |
3ff832 |
#ifdef ENABLE_SURROUNDING
|
|
Packit |
3ff832 |
ibusimcontext->caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS | IBUS_CAP_SURROUNDING_TEXT;
|
|
Packit |
3ff832 |
#else
|
|
Packit |
3ff832 |
ibusimcontext->caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS;
|
|
Packit |
3ff832 |
#endif
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
ibusimcontext->events_queue = g_queue_new ();
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
// Create slave im context
|
|
Packit |
3ff832 |
ibusimcontext->slave = gtk_im_context_simple_new ();
|
|
Packit |
3ff832 |
gtk_im_context_simple_add_table (GTK_IM_CONTEXT_SIMPLE (ibusimcontext->slave),
|
|
Packit |
3ff832 |
cedilla_compose_seqs,
|
|
Packit |
3ff832 |
4,
|
|
Packit |
3ff832 |
G_N_ELEMENTS (cedilla_compose_seqs) / (4 + 2));
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_signal_connect (ibusimcontext->slave,
|
|
Packit |
3ff832 |
"commit",
|
|
Packit |
3ff832 |
G_CALLBACK (_slave_commit_cb),
|
|
Packit |
3ff832 |
ibusimcontext);
|
|
Packit |
3ff832 |
g_signal_connect (ibusimcontext->slave,
|
|
Packit |
3ff832 |
"preedit-start",
|
|
Packit |
3ff832 |
G_CALLBACK (_slave_preedit_start_cb),
|
|
Packit |
3ff832 |
ibusimcontext);
|
|
Packit |
3ff832 |
g_signal_connect (ibusimcontext->slave,
|
|
Packit |
3ff832 |
"preedit-end",
|
|
Packit |
3ff832 |
G_CALLBACK (_slave_preedit_end_cb),
|
|
Packit |
3ff832 |
ibusimcontext);
|
|
Packit |
3ff832 |
g_signal_connect (ibusimcontext->slave,
|
|
Packit |
3ff832 |
"preedit-changed",
|
|
Packit |
3ff832 |
G_CALLBACK (_slave_preedit_changed_cb),
|
|
Packit |
3ff832 |
ibusimcontext);
|
|
Packit |
3ff832 |
g_signal_connect (ibusimcontext->slave,
|
|
Packit |
3ff832 |
"retrieve-surrounding",
|
|
Packit |
3ff832 |
G_CALLBACK (_slave_retrieve_surrounding_cb),
|
|
Packit |
3ff832 |
ibusimcontext);
|
|
Packit |
3ff832 |
g_signal_connect (ibusimcontext->slave,
|
|
Packit |
3ff832 |
"delete-surrounding",
|
|
Packit |
3ff832 |
G_CALLBACK (_slave_delete_surrounding_cb),
|
|
Packit |
3ff832 |
ibusimcontext);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibus_bus_is_connected (_bus)) {
|
|
Packit |
3ff832 |
_create_input_context (ibusimcontext);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_signal_connect (_bus, "connected", G_CALLBACK (_bus_connected_cb), obj);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_im_context_notify (GObject *obj,
|
|
Packit |
3ff832 |
GParamSpec *pspec)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (g_strcmp0 (pspec->name, "input-purpose") == 0 ||
|
|
Packit |
3ff832 |
g_strcmp0 (pspec->name, "input-hints") == 0) {
|
|
Packit |
3ff832 |
_set_content_type (IBUS_IM_CONTEXT (obj));
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_im_context_finalize (GObject *obj)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (obj);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_signal_handlers_disconnect_by_func (_bus, G_CALLBACK (_bus_connected_cb), obj);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->cancellable != NULL) {
|
|
Packit |
3ff832 |
/* Cancel any ongoing create input context request */
|
|
Packit |
3ff832 |
g_cancellable_cancel (ibusimcontext->cancellable);
|
|
Packit |
3ff832 |
g_object_unref (ibusimcontext->cancellable);
|
|
Packit |
3ff832 |
ibusimcontext->cancellable = NULL;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->ibuscontext) {
|
|
Packit |
3ff832 |
ibus_proxy_destroy ((IBusProxy *)ibusimcontext->ibuscontext);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
ibus_im_context_set_client_window ((GtkIMContext *)ibusimcontext, NULL);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->slave) {
|
|
Packit |
3ff832 |
g_object_unref (ibusimcontext->slave);
|
|
Packit |
3ff832 |
ibusimcontext->slave = NULL;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
// release preedit
|
|
Packit |
3ff832 |
if (ibusimcontext->preedit_string) {
|
|
Packit |
3ff832 |
g_free (ibusimcontext->preedit_string);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
if (ibusimcontext->preedit_attrs) {
|
|
Packit |
3ff832 |
pango_attr_list_unref (ibusimcontext->preedit_attrs);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_queue_free_full (ibusimcontext->events_queue,
|
|
Packit |
3ff832 |
(GDestroyNotify)gdk_event_free);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
G_OBJECT_CLASS(parent_class)->finalize (obj);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit Service |
fd1217 |
static void
|
|
Packit Service |
fd1217 |
ibus_im_context_clear_preedit_text (IBusIMContext *ibusimcontext)
|
|
Packit Service |
fd1217 |
{
|
|
Packit Service |
fd1217 |
gchar *preedit_string = NULL;
|
|
Packit Service |
fd1217 |
g_assert (ibusimcontext->ibuscontext);
|
|
Packit Service |
fd1217 |
if (ibusimcontext->preedit_visible &&
|
|
Packit Service |
fd1217 |
ibusimcontext->preedit_mode == IBUS_ENGINE_PREEDIT_COMMIT) {
|
|
Packit Service |
fd1217 |
preedit_string = g_strdup (ibusimcontext->preedit_string);
|
|
Packit Service |
fd1217 |
}
|
|
Packit Service |
fd1217 |
|
|
Packit Service |
fd1217 |
/* Clear the preedit_string but keep the preedit_cursor_pos and
|
|
Packit Service |
fd1217 |
* preedit_visible because a time lag could happen, firefox commit
|
|
Packit Service |
fd1217 |
* the preedit text before the preedit text is cleared and it cause
|
|
Packit Service |
fd1217 |
* a double commits of the Hangul preedit in firefox if the preedit
|
|
Packit Service |
fd1217 |
* would be located on the URL bar and click on anywhere of firefox
|
|
Packit Service |
fd1217 |
* out of the URL bar.
|
|
Packit Service |
fd1217 |
*/
|
|
Packit Service |
fd1217 |
_ibus_context_update_preedit_text_cb (ibusimcontext->ibuscontext,
|
|
Packit Service |
fd1217 |
ibus_text_new_from_string (""),
|
|
Packit Service |
fd1217 |
ibusimcontext->preedit_cursor_pos,
|
|
Packit Service |
fd1217 |
ibusimcontext->preedit_visible,
|
|
Packit Service |
fd1217 |
IBUS_ENGINE_PREEDIT_CLEAR,
|
|
Packit Service |
fd1217 |
ibusimcontext);
|
|
Packit Service |
fd1217 |
if (preedit_string) {
|
|
Packit Service |
fd1217 |
g_signal_emit (ibusimcontext, _signal_commit_id, 0, preedit_string);
|
|
Packit Service |
fd1217 |
g_free (preedit_string);
|
|
Packit Service |
fd1217 |
_request_surrounding_text (ibusimcontext);
|
|
Packit Service |
fd1217 |
}
|
|
Packit Service |
fd1217 |
}
|
|
Packit Service |
fd1217 |
|
|
Packit |
3ff832 |
static gboolean
|
|
Packit |
3ff832 |
ibus_im_context_filter_keypress (GtkIMContext *context,
|
|
Packit |
3ff832 |
GdkEventKey *event)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (context);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (!_daemon_is_running)
|
|
Packit |
3ff832 |
return gtk_im_context_filter_keypress (ibusimcontext->slave, event);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* If context does not have focus, ibus will process key event in
|
|
Packit |
3ff832 |
* sync mode. It is a workaround for increase search in treeview.
|
|
Packit |
3ff832 |
*/
|
|
Packit |
3ff832 |
if (!ibusimcontext->has_focus)
|
|
Packit |
3ff832 |
return gtk_im_context_filter_keypress (ibusimcontext->slave, event);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (event->state & IBUS_HANDLED_MASK)
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* Do not call gtk_im_context_filter_keypress() because
|
|
Packit |
3ff832 |
* gtk_im_context_simple_filter_keypress() binds Ctrl-Shift-u
|
|
Packit |
3ff832 |
*/
|
|
Packit |
3ff832 |
if (event->state & IBUS_IGNORED_MASK)
|
|
Packit |
3ff832 |
return ibus_im_context_commit_event (ibusimcontext, event);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* XXX it is a workaround for some applications do not set client
|
|
Packit |
3ff832 |
* window. */
|
|
Packit |
3ff832 |
if (ibusimcontext->client_window == NULL && event->window != NULL)
|
|
Packit |
3ff832 |
gtk_im_context_set_client_window ((GtkIMContext *)ibusimcontext,
|
|
Packit |
3ff832 |
event->window);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
_request_surrounding_text (ibusimcontext);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
ibusimcontext->time = event->time;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->ibuscontext) {
|
|
Packit |
3ff832 |
if (_process_key_event (ibusimcontext->ibuscontext, event))
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
else
|
|
Packit |
3ff832 |
return gtk_im_context_filter_keypress (ibusimcontext->slave,
|
|
Packit |
3ff832 |
event);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* At this point we _should_ be waiting for the IBus context to be
|
|
Packit |
3ff832 |
* created or the connection to IBus to be established. If that's
|
|
Packit |
3ff832 |
* the case we queue events to be processed when the IBus context
|
|
Packit |
3ff832 |
* is ready. */
|
|
Packit |
3ff832 |
g_return_val_if_fail (ibusimcontext->cancellable != NULL ||
|
|
Packit |
3ff832 |
ibus_bus_is_connected (_bus) == FALSE,
|
|
Packit |
3ff832 |
FALSE);
|
|
Packit |
3ff832 |
g_queue_push_tail (ibusimcontext->events_queue,
|
|
Packit |
3ff832 |
gdk_event_copy ((GdkEvent *)event));
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (g_queue_get_length (ibusimcontext->events_queue) > MAX_QUEUED_EVENTS) {
|
|
Packit |
3ff832 |
g_warning ("Events queue growing too big, will start to drop.");
|
|
Packit |
3ff832 |
gdk_event_free ((GdkEvent *)
|
|
Packit |
3ff832 |
g_queue_pop_head (ibusimcontext->events_queue));
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_im_context_focus_in (GtkIMContext *context)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext = (IBusIMContext *) context;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->has_focus)
|
|
Packit |
3ff832 |
return;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* don't set focus on password entry */
|
|
Packit |
3ff832 |
if (ibusimcontext->client_window != NULL) {
|
|
Packit |
3ff832 |
GtkWidget *widget;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
gdk_window_get_user_data (ibusimcontext->client_window,
|
|
Packit |
3ff832 |
(gpointer *)&widget);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (GTK_IS_ENTRY (widget) &&
|
|
Packit |
3ff832 |
!gtk_entry_get_visibility (GTK_ENTRY (widget))) {
|
|
Packit |
3ff832 |
return;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* Do not call gtk_im_context_focus_out() here.
|
|
Packit |
3ff832 |
* google-chrome's notification popup window (Pushbullet)
|
|
Packit |
3ff832 |
* takes the focus and the popup window disappears.
|
|
Packit |
3ff832 |
* So other applications lose the focus because
|
|
Packit |
3ff832 |
* ibusimcontext->has_focus is FALSE if
|
|
Packit |
3ff832 |
* gtk_im_context_focus_out() is called here when
|
|
Packit |
3ff832 |
* _focus_im_context != context.
|
|
Packit |
3ff832 |
*/
|
|
Packit |
3ff832 |
if (_focus_im_context == NULL) {
|
|
Packit |
3ff832 |
/* focus out fake context */
|
|
Packit |
3ff832 |
if (_fake_context != NULL) {
|
|
Packit |
3ff832 |
ibus_input_context_focus_out (_fake_context);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
ibusimcontext->has_focus = TRUE;
|
|
Packit |
3ff832 |
if (ibusimcontext->ibuscontext) {
|
|
Packit |
3ff832 |
if (!_set_content_type (ibusimcontext)) {
|
|
Packit |
3ff832 |
ibusimcontext->has_focus = FALSE;
|
|
Packit |
3ff832 |
return;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
ibus_input_context_focus_in (ibusimcontext->ibuscontext);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
gtk_im_context_focus_in (ibusimcontext->slave);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* set_cursor_location_internal() will get origin from X server,
|
|
Packit |
3ff832 |
* it blocks UI. So delay it to idle callback. */
|
|
Packit |
3ff832 |
gdk_threads_add_idle_full (G_PRIORITY_DEFAULT_IDLE,
|
|
Packit |
3ff832 |
(GSourceFunc) _set_cursor_location_internal,
|
|
Packit |
3ff832 |
g_object_ref (ibusimcontext),
|
|
Packit |
3ff832 |
(GDestroyNotify) g_object_unref);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* retrieve the initial surrounding-text (regardless of whether
|
|
Packit |
3ff832 |
* the current IBus engine needs surrounding-text) */
|
|
Packit |
3ff832 |
_request_surrounding_text (ibusimcontext);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_object_add_weak_pointer ((GObject *) context,
|
|
Packit |
3ff832 |
(gpointer *) &_focus_im_context);
|
|
Packit |
3ff832 |
_focus_im_context = context;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_im_context_focus_out (GtkIMContext *context)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext = (IBusIMContext *) context;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->has_focus == FALSE) {
|
|
Packit |
3ff832 |
return;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* If _use_discard_password is TRUE or GtkEntry has no visibility,
|
|
Packit |
3ff832 |
* _focus_im_context is NULL.
|
|
Packit |
3ff832 |
*/
|
|
Packit |
3ff832 |
if (_focus_im_context) {
|
|
Packit |
3ff832 |
g_object_remove_weak_pointer ((GObject *) context,
|
|
Packit |
3ff832 |
(gpointer *) &_focus_im_context);
|
|
Packit |
3ff832 |
_focus_im_context = NULL;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
ibusimcontext->has_focus = FALSE;
|
|
Packit |
3ff832 |
if (ibusimcontext->ibuscontext) {
|
|
Packit Service |
fd1217 |
ibus_im_context_clear_preedit_text (ibusimcontext);
|
|
Packit |
3ff832 |
ibus_input_context_focus_out (ibusimcontext->ibuscontext);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
gtk_im_context_focus_out (ibusimcontext->slave);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* focus in the fake ic */
|
|
Packit |
3ff832 |
if (_fake_context != NULL) {
|
|
Packit |
3ff832 |
ibus_input_context_focus_in (_fake_context);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_im_context_reset (GtkIMContext *context)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (context);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->ibuscontext) {
|
|
Packit Service |
fd1217 |
/* Commented out ibus_im_context_clear_preedit_text().
|
|
Packit Service |
fd1217 |
* Hangul needs to receive the reset callback with button press
|
|
Packit Service |
fd1217 |
* but other IMEs should avoid to receive the reset callback
|
|
Packit Service |
fd1217 |
* by themselves.
|
|
Packit Service |
fd1217 |
* IBus uses button-press-event instead until GTK is fixed.
|
|
Packit Service |
fd1217 |
* https://gitlab.gnome.org/GNOME/gtk/issues/1534
|
|
Packit Service |
fd1217 |
*/
|
|
Packit |
3ff832 |
ibus_input_context_reset (ibusimcontext->ibuscontext);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
gtk_im_context_reset (ibusimcontext->slave);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_im_context_get_preedit_string (GtkIMContext *context,
|
|
Packit |
3ff832 |
gchar **str,
|
|
Packit |
3ff832 |
PangoAttrList **attrs,
|
|
Packit |
3ff832 |
gint *cursor_pos)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (context);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->preedit_visible) {
|
|
Packit |
3ff832 |
if (str) {
|
|
Packit |
3ff832 |
*str = g_strdup (ibusimcontext->preedit_string ? ibusimcontext->preedit_string: "");
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (attrs) {
|
|
Packit |
3ff832 |
*attrs = ibusimcontext->preedit_attrs ?
|
|
Packit |
3ff832 |
pango_attr_list_ref (ibusimcontext->preedit_attrs):
|
|
Packit |
3ff832 |
pango_attr_list_new ();
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (cursor_pos) {
|
|
Packit |
3ff832 |
*cursor_pos = ibusimcontext->preedit_cursor_pos;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
else {
|
|
Packit |
3ff832 |
if (str) {
|
|
Packit |
3ff832 |
*str = g_strdup ("");
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
if (attrs) {
|
|
Packit |
3ff832 |
*attrs = pango_attr_list_new ();
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
if (cursor_pos) {
|
|
Packit |
3ff832 |
*cursor_pos = 0;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
IDEBUG ("str=%s", *str);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
|
|
Packit Service |
fd1217 |
#if !GTK_CHECK_VERSION (3, 93, 0)
|
|
Packit Service |
fd1217 |
/* Use the button-press-event signal until GtkIMContext always emits the reset
|
|
Packit Service |
fd1217 |
* signal.
|
|
Packit Service |
fd1217 |
* https://gitlab.gnome.org/GNOME/gtk/merge_requests/460
|
|
Packit Service |
fd1217 |
*/
|
|
Packit Service |
fd1217 |
static gboolean
|
|
Packit Service |
fd1217 |
ibus_im_context_button_press_event_cb (GtkWidget *widget,
|
|
Packit Service |
fd1217 |
GdkEventButton *event,
|
|
Packit Service |
fd1217 |
IBusIMContext *ibusimcontext)
|
|
Packit Service |
fd1217 |
{
|
|
Packit Service |
fd1217 |
if (event->button != 1)
|
|
Packit Service |
fd1217 |
return FALSE;
|
|
Packit Service |
fd1217 |
|
|
Packit Service |
fd1217 |
if (ibusimcontext->ibuscontext) {
|
|
Packit Service |
fd1217 |
ibus_im_context_clear_preedit_text (ibusimcontext);
|
|
Packit Service |
fd1217 |
ibus_input_context_reset (ibusimcontext->ibuscontext);
|
|
Packit Service |
fd1217 |
}
|
|
Packit Service |
fd1217 |
return FALSE;
|
|
Packit Service |
fd1217 |
}
|
|
Packit Service |
fd1217 |
|
|
Packit Service |
fd1217 |
static void
|
|
Packit Service |
fd1217 |
_connect_button_press_event (IBusIMContext *ibusimcontext,
|
|
Packit Service |
fd1217 |
gboolean do_connect)
|
|
Packit Service |
fd1217 |
{
|
|
Packit Service |
fd1217 |
GtkWidget *widget = NULL;
|
|
Packit Service |
fd1217 |
|
|
Packit Service |
fd1217 |
g_assert (ibusimcontext->client_window);
|
|
Packit Service |
fd1217 |
gdk_window_get_user_data (ibusimcontext->client_window,
|
|
Packit Service |
fd1217 |
(gpointer *)&widget);
|
|
Packit Service |
fd1217 |
/* firefox needs GtkWidget instead of GtkWindow */
|
|
Packit Service |
fd1217 |
if (GTK_IS_WIDGET (widget)) {
|
|
Packit Service |
fd1217 |
if (do_connect) {
|
|
Packit Service |
fd1217 |
g_signal_connect (
|
|
Packit Service |
fd1217 |
widget,
|
|
Packit Service |
fd1217 |
"button-press-event",
|
|
Packit Service |
fd1217 |
G_CALLBACK (ibus_im_context_button_press_event_cb),
|
|
Packit Service |
fd1217 |
ibusimcontext);
|
|
Packit Service |
fd1217 |
ibusimcontext->use_button_press_event = TRUE;
|
|
Packit Service |
fd1217 |
} else {
|
|
Packit Service |
fd1217 |
g_signal_handlers_disconnect_by_func (
|
|
Packit Service |
fd1217 |
widget,
|
|
Packit Service |
fd1217 |
G_CALLBACK (ibus_im_context_button_press_event_cb),
|
|
Packit Service |
fd1217 |
ibusimcontext);
|
|
Packit Service |
fd1217 |
ibusimcontext->use_button_press_event = FALSE;
|
|
Packit Service |
fd1217 |
}
|
|
Packit Service |
fd1217 |
}
|
|
Packit Service |
fd1217 |
}
|
|
Packit Service |
fd1217 |
#endif
|
|
Packit Service |
fd1217 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_im_context_set_client_window (GtkIMContext *context, GdkWindow *client)
|
|
Packit |
3ff832 |
{
|
|
Packit Service |
fd1217 |
IBusIMContext *ibusimcontext;
|
|
Packit Service |
fd1217 |
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit Service |
fd1217 |
ibusimcontext = IBUS_IM_CONTEXT (context);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->client_window) {
|
|
Packit Service |
fd1217 |
#if !GTK_CHECK_VERSION (3, 93, 0)
|
|
Packit Service |
fd1217 |
if (ibusimcontext->use_button_press_event)
|
|
Packit Service |
fd1217 |
_connect_button_press_event (ibusimcontext, FALSE);
|
|
Packit Service |
fd1217 |
#endif
|
|
Packit |
3ff832 |
g_object_unref (ibusimcontext->client_window);
|
|
Packit |
3ff832 |
ibusimcontext->client_window = NULL;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit Service |
fd1217 |
if (client != NULL) {
|
|
Packit |
3ff832 |
ibusimcontext->client_window = g_object_ref (client);
|
|
Packit Service |
fd1217 |
#if !GTK_CHECK_VERSION (3, 93, 0)
|
|
Packit Service |
fd1217 |
if (!ibusimcontext->use_button_press_event)
|
|
Packit Service |
fd1217 |
_connect_button_press_event (ibusimcontext, TRUE);
|
|
Packit Service |
fd1217 |
#endif
|
|
Packit Service |
fd1217 |
}
|
|
Packit |
3ff832 |
if (ibusimcontext->slave)
|
|
Packit |
3ff832 |
gtk_im_context_set_client_window (ibusimcontext->slave, client);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_set_rect_scale_factor_with_window (GdkRectangle *area,
|
|
Packit |
3ff832 |
GdkWindow *window)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
#if GTK_CHECK_VERSION (3, 10, 0)
|
|
Packit |
3ff832 |
int scale_factor;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_assert (area);
|
|
Packit |
3ff832 |
g_assert (GDK_IS_WINDOW (window));
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
scale_factor = gdk_window_get_scale_factor (window);
|
|
Packit |
3ff832 |
area->x *= scale_factor;
|
|
Packit |
3ff832 |
area->y *= scale_factor;
|
|
Packit |
3ff832 |
area->width *= scale_factor;
|
|
Packit |
3ff832 |
area->height *= scale_factor;
|
|
Packit |
3ff832 |
#endif
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gboolean
|
|
Packit |
3ff832 |
_set_cursor_location_internal (IBusIMContext *ibusimcontext)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
GdkRectangle area;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if(ibusimcontext->client_window == NULL ||
|
|
Packit |
3ff832 |
ibusimcontext->ibuscontext == NULL) {
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
area = ibusimcontext->cursor_area;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
#ifdef GDK_WINDOWING_WAYLAND
|
|
Packit |
3ff832 |
if (GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ())) {
|
|
Packit |
3ff832 |
gdouble px, py;
|
|
Packit |
3ff832 |
GdkWindow *parent;
|
|
Packit |
3ff832 |
GdkWindow *window = ibusimcontext->client_window;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
while ((parent = gdk_window_get_effective_parent (window)) != NULL) {
|
|
Packit |
3ff832 |
gdk_window_coords_to_parent (window, area.x, area.y, &px, &py;;
|
|
Packit |
3ff832 |
area.x = px;
|
|
Packit |
3ff832 |
area.y = py;
|
|
Packit |
3ff832 |
window = parent;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
_set_rect_scale_factor_with_window (&area,
|
|
Packit |
3ff832 |
ibusimcontext->client_window);
|
|
Packit |
3ff832 |
ibus_input_context_set_cursor_location_relative (
|
|
Packit |
3ff832 |
ibusimcontext->ibuscontext,
|
|
Packit |
3ff832 |
area.x,
|
|
Packit |
3ff832 |
area.y,
|
|
Packit |
3ff832 |
area.width,
|
|
Packit |
3ff832 |
area.height);
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
#endif
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (area.x == -1 && area.y == -1 && area.width == 0 && area.height == 0) {
|
|
Packit |
3ff832 |
#if GTK_CHECK_VERSION (2, 91, 0)
|
|
Packit |
3ff832 |
area.x = 0;
|
|
Packit |
3ff832 |
area.y += gdk_window_get_height (ibusimcontext->client_window);
|
|
Packit |
3ff832 |
#else
|
|
Packit |
3ff832 |
gint w, h;
|
|
Packit |
3ff832 |
gdk_drawable_get_size (ibusimcontext->client_window, &w, &h);
|
|
Packit |
3ff832 |
area.y += h;
|
|
Packit |
3ff832 |
area.x = 0;
|
|
Packit |
3ff832 |
#endif
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
gdk_window_get_root_coords (ibusimcontext->client_window,
|
|
Packit |
3ff832 |
area.x, area.y,
|
|
Packit |
3ff832 |
&area.x, &area.y);
|
|
Packit |
3ff832 |
_set_rect_scale_factor_with_window (&area, ibusimcontext->client_window);
|
|
Packit |
3ff832 |
ibus_input_context_set_cursor_location (ibusimcontext->ibuscontext,
|
|
Packit |
3ff832 |
area.x,
|
|
Packit |
3ff832 |
area.y,
|
|
Packit |
3ff832 |
area.width,
|
|
Packit |
3ff832 |
area.height);
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_im_context_set_cursor_location (GtkIMContext *context, GdkRectangle *area)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (context);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->cursor_area.x == area->x &&
|
|
Packit |
3ff832 |
ibusimcontext->cursor_area.y == area->y &&
|
|
Packit |
3ff832 |
ibusimcontext->cursor_area.width == area->width &&
|
|
Packit |
3ff832 |
ibusimcontext->cursor_area.height == area->height) {
|
|
Packit |
3ff832 |
return;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
ibusimcontext->cursor_area = *area;
|
|
Packit |
3ff832 |
_set_cursor_location_internal (ibusimcontext);
|
|
Packit |
3ff832 |
gtk_im_context_set_cursor_location (ibusimcontext->slave, area);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_im_context_set_use_preedit (GtkIMContext *context, gboolean use_preedit)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (context);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (use_preedit) {
|
|
Packit |
3ff832 |
ibusimcontext->caps |= IBUS_CAP_PREEDIT_TEXT;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
else {
|
|
Packit |
3ff832 |
ibusimcontext->caps &= ~IBUS_CAP_PREEDIT_TEXT;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
if(ibusimcontext->ibuscontext) {
|
|
Packit |
3ff832 |
ibus_input_context_set_capabilities (ibusimcontext->ibuscontext,
|
|
Packit |
3ff832 |
ibusimcontext->caps);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
gtk_im_context_set_use_preedit (ibusimcontext->slave, use_preedit);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static guint
|
|
Packit |
3ff832 |
get_selection_anchor_point (IBusIMContext *ibusimcontext,
|
|
Packit |
3ff832 |
guint cursor_pos,
|
|
Packit |
3ff832 |
guint surrounding_text_len)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
GtkWidget *widget;
|
|
Packit |
3ff832 |
if (ibusimcontext->client_window == NULL) {
|
|
Packit |
3ff832 |
return cursor_pos;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
gdk_window_get_user_data (ibusimcontext->client_window, (gpointer *)&widget);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (!GTK_IS_TEXT_VIEW (widget)){
|
|
Packit |
3ff832 |
return cursor_pos;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
GtkTextView *text_view = GTK_TEXT_VIEW (widget);
|
|
Packit |
3ff832 |
GtkTextBuffer *buffer = gtk_text_view_get_buffer (text_view);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (!gtk_text_buffer_get_has_selection (buffer)) {
|
|
Packit |
3ff832 |
return cursor_pos;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
GtkTextIter start_iter, end_iter, cursor_iter;
|
|
Packit |
3ff832 |
if (!gtk_text_buffer_get_selection_bounds (buffer, &start_iter, &end_iter)) {
|
|
Packit |
3ff832 |
return cursor_pos;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
gtk_text_buffer_get_iter_at_mark (buffer,
|
|
Packit |
3ff832 |
&cursor_iter,
|
|
Packit |
3ff832 |
gtk_text_buffer_get_insert (buffer));
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
guint start_index = gtk_text_iter_get_offset (&start_iter);
|
|
Packit |
3ff832 |
guint end_index = gtk_text_iter_get_offset (&end_iter);
|
|
Packit |
3ff832 |
guint cursor_index = gtk_text_iter_get_offset (&cursor_iter);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
guint anchor;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (start_index == cursor_index) {
|
|
Packit |
3ff832 |
anchor = end_index;
|
|
Packit |
3ff832 |
} else if (end_index == cursor_index) {
|
|
Packit |
3ff832 |
anchor = start_index;
|
|
Packit |
3ff832 |
} else {
|
|
Packit |
3ff832 |
return cursor_pos;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
// Change absolute index to relative position.
|
|
Packit |
3ff832 |
guint relative_origin = cursor_index - cursor_pos;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (anchor < relative_origin) {
|
|
Packit |
3ff832 |
return cursor_pos;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
anchor -= relative_origin;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (anchor > surrounding_text_len) {
|
|
Packit |
3ff832 |
return cursor_pos;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
return anchor;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_im_context_set_surrounding (GtkIMContext *context,
|
|
Packit |
3ff832 |
const gchar *text,
|
|
Packit |
3ff832 |
gint len,
|
|
Packit |
3ff832 |
gint cursor_index)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
g_return_if_fail (context != NULL);
|
|
Packit |
3ff832 |
g_return_if_fail (IBUS_IS_IM_CONTEXT (context));
|
|
Packit |
3ff832 |
g_return_if_fail (text != NULL);
|
|
Packit |
3ff832 |
g_return_if_fail (strlen (text) >= len);
|
|
Packit |
3ff832 |
g_return_if_fail (0 <= cursor_index && cursor_index <= len);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (context);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->ibuscontext) {
|
|
Packit |
3ff832 |
IBusText *ibustext;
|
|
Packit |
3ff832 |
guint cursor_pos;
|
|
Packit |
3ff832 |
guint utf8_len;
|
|
Packit |
3ff832 |
gchar *p;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
p = g_strndup (text, len);
|
|
Packit |
3ff832 |
cursor_pos = g_utf8_strlen (p, cursor_index);
|
|
Packit |
3ff832 |
utf8_len = g_utf8_strlen(p, len);
|
|
Packit |
3ff832 |
ibustext = ibus_text_new_from_string (p);
|
|
Packit |
3ff832 |
g_free (p);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
guint anchor_pos = get_selection_anchor_point (ibusimcontext,
|
|
Packit |
3ff832 |
cursor_pos,
|
|
Packit |
3ff832 |
utf8_len);
|
|
Packit |
3ff832 |
ibus_input_context_set_surrounding_text (ibusimcontext->ibuscontext,
|
|
Packit |
3ff832 |
ibustext,
|
|
Packit |
3ff832 |
cursor_pos,
|
|
Packit |
3ff832 |
anchor_pos);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
gtk_im_context_set_surrounding (ibusimcontext->slave,
|
|
Packit |
3ff832 |
text,
|
|
Packit |
3ff832 |
len,
|
|
Packit |
3ff832 |
cursor_index);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_bus_connected_cb (IBusBus *bus,
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
if (ibusimcontext)
|
|
Packit |
3ff832 |
_create_input_context (ibusimcontext);
|
|
Packit |
3ff832 |
else
|
|
Packit |
3ff832 |
_create_fake_input_context ();
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_ibus_context_commit_text_cb (IBusInputContext *ibuscontext,
|
|
Packit |
3ff832 |
IBusText *text,
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_commit_id, 0, text->text);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
_request_surrounding_text (ibusimcontext);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gboolean
|
|
Packit |
3ff832 |
_key_is_modifier (guint keyval)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
/* See gdkkeys-x11.c:_gdk_keymap_key_is_modifier() for how this
|
|
Packit |
3ff832 |
* really should be implemented */
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
switch (keyval) {
|
|
Packit |
3ff832 |
#ifdef DEPRECATED_GDK_KEYSYMS
|
|
Packit |
3ff832 |
case GDK_Shift_L:
|
|
Packit |
3ff832 |
case GDK_Shift_R:
|
|
Packit |
3ff832 |
case GDK_Control_L:
|
|
Packit |
3ff832 |
case GDK_Control_R:
|
|
Packit |
3ff832 |
case GDK_Caps_Lock:
|
|
Packit |
3ff832 |
case GDK_Shift_Lock:
|
|
Packit |
3ff832 |
case GDK_Meta_L:
|
|
Packit |
3ff832 |
case GDK_Meta_R:
|
|
Packit |
3ff832 |
case GDK_Alt_L:
|
|
Packit |
3ff832 |
case GDK_Alt_R:
|
|
Packit |
3ff832 |
case GDK_Super_L:
|
|
Packit |
3ff832 |
case GDK_Super_R:
|
|
Packit |
3ff832 |
case GDK_Hyper_L:
|
|
Packit |
3ff832 |
case GDK_Hyper_R:
|
|
Packit |
3ff832 |
case GDK_ISO_Lock:
|
|
Packit |
3ff832 |
case GDK_ISO_Level2_Latch:
|
|
Packit |
3ff832 |
case GDK_ISO_Level3_Shift:
|
|
Packit |
3ff832 |
case GDK_ISO_Level3_Latch:
|
|
Packit |
3ff832 |
case GDK_ISO_Level3_Lock:
|
|
Packit |
3ff832 |
case GDK_ISO_Level5_Shift:
|
|
Packit |
3ff832 |
case GDK_ISO_Level5_Latch:
|
|
Packit |
3ff832 |
case GDK_ISO_Level5_Lock:
|
|
Packit |
3ff832 |
case GDK_ISO_Group_Shift:
|
|
Packit |
3ff832 |
case GDK_ISO_Group_Latch:
|
|
Packit |
3ff832 |
case GDK_ISO_Group_Lock:
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
#else
|
|
Packit |
3ff832 |
case GDK_KEY_Shift_L:
|
|
Packit |
3ff832 |
case GDK_KEY_Shift_R:
|
|
Packit |
3ff832 |
case GDK_KEY_Control_L:
|
|
Packit |
3ff832 |
case GDK_KEY_Control_R:
|
|
Packit |
3ff832 |
case GDK_KEY_Caps_Lock:
|
|
Packit |
3ff832 |
case GDK_KEY_Shift_Lock:
|
|
Packit |
3ff832 |
case GDK_KEY_Meta_L:
|
|
Packit |
3ff832 |
case GDK_KEY_Meta_R:
|
|
Packit |
3ff832 |
case GDK_KEY_Alt_L:
|
|
Packit |
3ff832 |
case GDK_KEY_Alt_R:
|
|
Packit |
3ff832 |
case GDK_KEY_Super_L:
|
|
Packit |
3ff832 |
case GDK_KEY_Super_R:
|
|
Packit |
3ff832 |
case GDK_KEY_Hyper_L:
|
|
Packit |
3ff832 |
case GDK_KEY_Hyper_R:
|
|
Packit |
3ff832 |
case GDK_KEY_ISO_Lock:
|
|
Packit |
3ff832 |
case GDK_KEY_ISO_Level2_Latch:
|
|
Packit |
3ff832 |
case GDK_KEY_ISO_Level3_Shift:
|
|
Packit |
3ff832 |
case GDK_KEY_ISO_Level3_Latch:
|
|
Packit |
3ff832 |
case GDK_KEY_ISO_Level3_Lock:
|
|
Packit |
3ff832 |
case GDK_KEY_ISO_Level5_Shift:
|
|
Packit |
3ff832 |
case GDK_KEY_ISO_Level5_Latch:
|
|
Packit |
3ff832 |
case GDK_KEY_ISO_Level5_Lock:
|
|
Packit |
3ff832 |
case GDK_KEY_ISO_Group_Shift:
|
|
Packit |
3ff832 |
case GDK_KEY_ISO_Group_Latch:
|
|
Packit |
3ff832 |
case GDK_KEY_ISO_Group_Lock:
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
#endif
|
|
Packit |
3ff832 |
default:
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit Service |
fd1217 |
|
|
Packit |
3ff832 |
/* Copy from gdk */
|
|
Packit |
3ff832 |
static GdkEventKey *
|
|
Packit |
3ff832 |
_create_gdk_event (IBusIMContext *ibusimcontext,
|
|
Packit |
3ff832 |
guint keyval,
|
|
Packit |
3ff832 |
guint keycode,
|
|
Packit |
3ff832 |
guint state)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
gunichar c = 0;
|
|
Packit |
3ff832 |
gchar buf[8];
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
GdkEventKey *event = (GdkEventKey *)gdk_event_new ((state & IBUS_RELEASE_MASK) ? GDK_KEY_RELEASE : GDK_KEY_PRESS);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext && ibusimcontext->client_window)
|
|
Packit |
3ff832 |
event->window = g_object_ref (ibusimcontext->client_window);
|
|
Packit |
3ff832 |
else if (_input_window)
|
|
Packit |
3ff832 |
event->window = g_object_ref (_input_window);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* The time is copied the latest value from the previous
|
|
Packit |
3ff832 |
* GdkKeyEvent in filter_keypress().
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* We understand the best way would be to pass the all time value
|
|
Packit |
3ff832 |
* to IBus functions process_key_event() and IBus DBus functions
|
|
Packit |
3ff832 |
* ProcessKeyEvent() in IM clients and IM engines so that the
|
|
Packit |
3ff832 |
* _create_gdk_event() could get the correct time values.
|
|
Packit |
3ff832 |
* However it would causes to change many functions and the time value
|
|
Packit |
3ff832 |
* would not provide the useful meanings for each IBus engines but just
|
|
Packit |
3ff832 |
* pass the original value to ForwardKeyEvent().
|
|
Packit |
3ff832 |
* We use the saved value at the moment.
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* Another idea might be to have the time implementation in X servers
|
|
Packit |
3ff832 |
* but some Xorg uses clock_gettime() and others use gettimeofday()
|
|
Packit |
3ff832 |
* and the values would be different in each implementation and
|
|
Packit |
3ff832 |
* locale/remote X server. So probably that idea would not work. */
|
|
Packit |
3ff832 |
if (ibusimcontext) {
|
|
Packit |
3ff832 |
event->time = ibusimcontext->time;
|
|
Packit |
3ff832 |
} else {
|
|
Packit |
3ff832 |
event->time = GDK_CURRENT_TIME;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
event->send_event = FALSE;
|
|
Packit |
3ff832 |
event->state = state;
|
|
Packit |
3ff832 |
event->keyval = keyval;
|
|
Packit |
3ff832 |
event->string = NULL;
|
|
Packit |
3ff832 |
event->length = 0;
|
|
Packit |
3ff832 |
event->hardware_keycode = (keycode != 0) ? keycode + 8 : 0;
|
|
Packit |
3ff832 |
event->group = 0;
|
|
Packit |
3ff832 |
event->is_modifier = _key_is_modifier (keyval);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
#ifdef DEPRECATED_GDK_KEYSYMS
|
|
Packit |
3ff832 |
if (keyval != GDK_VoidSymbol)
|
|
Packit |
3ff832 |
#else
|
|
Packit |
3ff832 |
if (keyval != GDK_KEY_VoidSymbol)
|
|
Packit |
3ff832 |
#endif
|
|
Packit |
3ff832 |
c = gdk_keyval_to_unicode (keyval);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (c) {
|
|
Packit |
3ff832 |
gsize bytes_written;
|
|
Packit |
3ff832 |
gint len;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* Apply the control key - Taken from Xlib
|
|
Packit |
3ff832 |
*/
|
|
Packit |
3ff832 |
if (event->state & GDK_CONTROL_MASK) {
|
|
Packit |
3ff832 |
if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
|
|
Packit |
3ff832 |
else if (c == '2') {
|
|
Packit |
3ff832 |
event->string = g_memdup ("\0\0", 2);
|
|
Packit |
3ff832 |
event->length = 1;
|
|
Packit |
3ff832 |
buf[0] = '\0';
|
|
Packit |
3ff832 |
goto out;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
else if (c >= '3' && c <= '7') c -= ('3' - '\033');
|
|
Packit |
3ff832 |
else if (c == '8') c = '\177';
|
|
Packit |
3ff832 |
else if (c == '/') c = '_' & 0x1F;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
len = g_unichar_to_utf8 (c, buf);
|
|
Packit |
3ff832 |
buf[len] = '\0';
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
event->string = g_locale_from_utf8 (buf, len,
|
|
Packit |
3ff832 |
NULL, &bytes_written,
|
|
Packit |
3ff832 |
NULL);
|
|
Packit |
3ff832 |
if (event->string)
|
|
Packit |
3ff832 |
event->length = bytes_written;
|
|
Packit |
3ff832 |
#ifdef DEPRECATED_GDK_KEYSYMS
|
|
Packit |
3ff832 |
} else if (keyval == GDK_Escape) {
|
|
Packit |
3ff832 |
#else
|
|
Packit |
3ff832 |
} else if (keyval == GDK_KEY_Escape) {
|
|
Packit |
3ff832 |
#endif
|
|
Packit |
3ff832 |
event->length = 1;
|
|
Packit |
3ff832 |
event->string = g_strdup ("\033");
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
#ifdef DEPRECATED_GDK_KEYSYMS
|
|
Packit |
3ff832 |
else if (keyval == GDK_Return ||
|
|
Packit |
3ff832 |
keyval == GDK_KP_Enter) {
|
|
Packit |
3ff832 |
#else
|
|
Packit |
3ff832 |
else if (keyval == GDK_KEY_Return ||
|
|
Packit |
3ff832 |
keyval == GDK_KEY_KP_Enter) {
|
|
Packit |
3ff832 |
#endif
|
|
Packit |
3ff832 |
event->length = 1;
|
|
Packit |
3ff832 |
event->string = g_strdup ("\r");
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (!event->string) {
|
|
Packit |
3ff832 |
event->length = 0;
|
|
Packit |
3ff832 |
event->string = g_strdup ("");
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
out:
|
|
Packit |
3ff832 |
return event;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_ibus_context_forward_key_event_cb (IBusInputContext *ibuscontext,
|
|
Packit |
3ff832 |
guint keyval,
|
|
Packit |
3ff832 |
guint keycode,
|
|
Packit |
3ff832 |
guint state,
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
GdkEventKey *event = _create_gdk_event (ibusimcontext, keyval, keycode, state);
|
|
Packit |
3ff832 |
gdk_event_put ((GdkEvent *)event);
|
|
Packit |
3ff832 |
gdk_event_free ((GdkEvent *)event);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_ibus_context_delete_surrounding_text_cb (IBusInputContext *ibuscontext,
|
|
Packit |
3ff832 |
gint offset_from_cursor,
|
|
Packit |
3ff832 |
guint nchars,
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
gboolean return_value;
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_delete_surrounding_id, 0, offset_from_cursor, nchars, &return_value);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_ibus_context_update_preedit_text_cb (IBusInputContext *ibuscontext,
|
|
Packit |
3ff832 |
IBusText *text,
|
|
Packit |
3ff832 |
gint cursor_pos,
|
|
Packit |
3ff832 |
gboolean visible,
|
|
Packit Service |
fd1217 |
guint mode,
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
const gchar *str;
|
|
Packit |
3ff832 |
gboolean flag;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->preedit_string) {
|
|
Packit |
3ff832 |
g_free (ibusimcontext->preedit_string);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
if (ibusimcontext->preedit_attrs) {
|
|
Packit |
3ff832 |
pango_attr_list_unref (ibusimcontext->preedit_attrs);
|
|
Packit |
3ff832 |
ibusimcontext->preedit_attrs = NULL;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit Service |
fd1217 |
#if !GTK_CHECK_VERSION (3, 93, 0)
|
|
Packit Service |
fd1217 |
if (!ibusimcontext->use_button_press_event &&
|
|
Packit Service |
fd1217 |
mode == IBUS_ENGINE_PREEDIT_COMMIT) {
|
|
Packit Service |
fd1217 |
if (ibusimcontext->client_window) {
|
|
Packit Service |
fd1217 |
_connect_button_press_event (ibusimcontext, TRUE);
|
|
Packit Service |
fd1217 |
}
|
|
Packit Service |
fd1217 |
}
|
|
Packit Service |
fd1217 |
#endif
|
|
Packit Service |
fd1217 |
|
|
Packit |
3ff832 |
str = text->text;
|
|
Packit |
3ff832 |
ibusimcontext->preedit_string = g_strdup (str);
|
|
Packit |
3ff832 |
if (text->attrs) {
|
|
Packit |
3ff832 |
guint i;
|
|
Packit |
3ff832 |
ibusimcontext->preedit_attrs = pango_attr_list_new ();
|
|
Packit |
3ff832 |
for (i = 0; ; i++) {
|
|
Packit |
3ff832 |
IBusAttribute *attr = ibus_attr_list_get (text->attrs, i);
|
|
Packit |
3ff832 |
if (attr == NULL) {
|
|
Packit |
3ff832 |
break;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
PangoAttribute *pango_attr;
|
|
Packit |
3ff832 |
switch (attr->type) {
|
|
Packit |
3ff832 |
case IBUS_ATTR_TYPE_UNDERLINE:
|
|
Packit |
3ff832 |
pango_attr = pango_attr_underline_new (attr->value);
|
|
Packit |
3ff832 |
break;
|
|
Packit |
3ff832 |
case IBUS_ATTR_TYPE_FOREGROUND:
|
|
Packit |
3ff832 |
pango_attr = pango_attr_foreground_new (
|
|
Packit |
3ff832 |
((attr->value & 0xff0000) >> 8) | 0xff,
|
|
Packit |
3ff832 |
((attr->value & 0x00ff00)) | 0xff,
|
|
Packit |
3ff832 |
((attr->value & 0x0000ff) << 8) | 0xff);
|
|
Packit |
3ff832 |
break;
|
|
Packit |
3ff832 |
case IBUS_ATTR_TYPE_BACKGROUND:
|
|
Packit |
3ff832 |
pango_attr = pango_attr_background_new (
|
|
Packit |
3ff832 |
((attr->value & 0xff0000) >> 8) | 0xff,
|
|
Packit |
3ff832 |
((attr->value & 0x00ff00)) | 0xff,
|
|
Packit |
3ff832 |
((attr->value & 0x0000ff) << 8) | 0xff);
|
|
Packit |
3ff832 |
break;
|
|
Packit |
3ff832 |
default:
|
|
Packit |
3ff832 |
continue;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
pango_attr->start_index = g_utf8_offset_to_pointer (str, attr->start_index) - str;
|
|
Packit |
3ff832 |
pango_attr->end_index = g_utf8_offset_to_pointer (str, attr->end_index) - str;
|
|
Packit |
3ff832 |
pango_attr_list_insert (ibusimcontext->preedit_attrs, pango_attr);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
ibusimcontext->preedit_cursor_pos = cursor_pos;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
flag = ibusimcontext->preedit_visible != visible;
|
|
Packit |
3ff832 |
ibusimcontext->preedit_visible = visible;
|
|
Packit Service |
fd1217 |
ibusimcontext->preedit_mode = mode;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->preedit_visible) {
|
|
Packit |
3ff832 |
if (flag) {
|
|
Packit |
3ff832 |
/* invisible => visible */
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_preedit_start_id, 0);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_preedit_changed_id, 0);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
else {
|
|
Packit |
3ff832 |
if (flag) {
|
|
Packit |
3ff832 |
/* visible => invisible */
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_preedit_changed_id, 0);
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_preedit_end_id, 0);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
else {
|
|
Packit |
3ff832 |
/* still invisible */
|
|
Packit |
3ff832 |
/* do nothing */
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_ibus_context_show_preedit_text_cb (IBusInputContext *ibuscontext,
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->preedit_visible == TRUE)
|
|
Packit |
3ff832 |
return;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
ibusimcontext->preedit_visible = TRUE;
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_preedit_start_id, 0);
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_preedit_changed_id, 0);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
_request_surrounding_text (ibusimcontext);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_ibus_context_hide_preedit_text_cb (IBusInputContext *ibuscontext,
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->preedit_visible == FALSE)
|
|
Packit |
3ff832 |
return;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
ibusimcontext->preedit_visible = FALSE;
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_preedit_changed_id, 0);
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_preedit_end_id, 0);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_ibus_context_destroy_cb (IBusInputContext *ibuscontext,
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
g_assert (ibusimcontext->ibuscontext == ibuscontext);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_object_unref (ibusimcontext->ibuscontext);
|
|
Packit |
3ff832 |
ibusimcontext->ibuscontext = NULL;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* clear preedit */
|
|
Packit |
3ff832 |
ibusimcontext->preedit_visible = FALSE;
|
|
Packit |
3ff832 |
ibusimcontext->preedit_cursor_pos = 0;
|
|
Packit |
3ff832 |
g_free (ibusimcontext->preedit_string);
|
|
Packit |
3ff832 |
ibusimcontext->preedit_string = NULL;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_preedit_changed_id, 0);
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_preedit_end_id, 0);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_create_input_context_done (IBusBus *bus,
|
|
Packit |
3ff832 |
GAsyncResult *res,
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
GError *error = NULL;
|
|
Packit |
3ff832 |
IBusInputContext *context = ibus_bus_create_input_context_async_finish (
|
|
Packit |
3ff832 |
_bus, res, &error);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->cancellable != NULL) {
|
|
Packit |
3ff832 |
g_object_unref (ibusimcontext->cancellable);
|
|
Packit |
3ff832 |
ibusimcontext->cancellable = NULL;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (context == NULL) {
|
|
Packit |
3ff832 |
g_warning ("Create input context failed: %s.", error->message);
|
|
Packit |
3ff832 |
g_error_free (error);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
else {
|
|
Packit Service |
fd1217 |
ibus_input_context_set_client_commit_preedit (context, TRUE);
|
|
Packit |
3ff832 |
ibusimcontext->ibuscontext = context;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_signal_connect (ibusimcontext->ibuscontext,
|
|
Packit |
3ff832 |
"commit-text",
|
|
Packit |
3ff832 |
G_CALLBACK (_ibus_context_commit_text_cb),
|
|
Packit |
3ff832 |
ibusimcontext);
|
|
Packit |
3ff832 |
g_signal_connect (ibusimcontext->ibuscontext,
|
|
Packit |
3ff832 |
"forward-key-event",
|
|
Packit |
3ff832 |
G_CALLBACK (_ibus_context_forward_key_event_cb),
|
|
Packit |
3ff832 |
ibusimcontext);
|
|
Packit |
3ff832 |
g_signal_connect (ibusimcontext->ibuscontext,
|
|
Packit |
3ff832 |
"delete-surrounding-text",
|
|
Packit |
3ff832 |
G_CALLBACK (_ibus_context_delete_surrounding_text_cb),
|
|
Packit |
3ff832 |
ibusimcontext);
|
|
Packit |
3ff832 |
g_signal_connect (ibusimcontext->ibuscontext,
|
|
Packit Service |
fd1217 |
"update-preedit-text-with-mode",
|
|
Packit |
3ff832 |
G_CALLBACK (_ibus_context_update_preedit_text_cb),
|
|
Packit |
3ff832 |
ibusimcontext);
|
|
Packit |
3ff832 |
g_signal_connect (ibusimcontext->ibuscontext,
|
|
Packit |
3ff832 |
"show-preedit-text",
|
|
Packit |
3ff832 |
G_CALLBACK (_ibus_context_show_preedit_text_cb),
|
|
Packit |
3ff832 |
ibusimcontext);
|
|
Packit |
3ff832 |
g_signal_connect (ibusimcontext->ibuscontext,
|
|
Packit |
3ff832 |
"hide-preedit-text",
|
|
Packit |
3ff832 |
G_CALLBACK (_ibus_context_hide_preedit_text_cb),
|
|
Packit |
3ff832 |
ibusimcontext);
|
|
Packit |
3ff832 |
g_signal_connect (ibusimcontext->ibuscontext, "destroy",
|
|
Packit |
3ff832 |
G_CALLBACK (_ibus_context_destroy_cb),
|
|
Packit |
3ff832 |
ibusimcontext);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
ibus_input_context_set_capabilities (ibusimcontext->ibuscontext, ibusimcontext->caps);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->has_focus) {
|
|
Packit |
3ff832 |
/* The time order is _create_input_context() ->
|
|
Packit |
3ff832 |
* ibus_im_context_notify() -> ibus_im_context_focus_in() ->
|
|
Packit |
3ff832 |
* _create_input_context_done()
|
|
Packit |
3ff832 |
* so _set_content_type() is called at the beginning here
|
|
Packit |
3ff832 |
* because ibusimcontext->ibuscontext == NULL before. */
|
|
Packit |
3ff832 |
_set_content_type (ibusimcontext);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
ibus_input_context_focus_in (ibusimcontext->ibuscontext);
|
|
Packit |
3ff832 |
_set_cursor_location_internal (ibusimcontext);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (!g_queue_is_empty (ibusimcontext->events_queue)) {
|
|
Packit |
3ff832 |
GdkEventKey *event;
|
|
Packit |
3ff832 |
while ((event = g_queue_pop_head (ibusimcontext->events_queue))) {
|
|
Packit |
3ff832 |
_process_key_event (context, event);
|
|
Packit |
3ff832 |
gdk_event_free ((GdkEvent *)event);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_object_unref (ibusimcontext);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_create_input_context (IBusIMContext *ibusimcontext)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IDEBUG ("%s", __FUNCTION__);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_assert (ibusimcontext->ibuscontext == NULL);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_return_if_fail (ibusimcontext->cancellable == NULL);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
ibusimcontext->cancellable = g_cancellable_new ();
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
ibus_bus_create_input_context_async (_bus,
|
|
Packit |
3ff832 |
"gtk-im", -1,
|
|
Packit |
3ff832 |
ibusimcontext->cancellable,
|
|
Packit |
3ff832 |
(GAsyncReadyCallback)_create_input_context_done,
|
|
Packit |
3ff832 |
g_object_ref (ibusimcontext));
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* Callback functions for slave context */
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_slave_commit_cb (GtkIMContext *slave,
|
|
Packit |
3ff832 |
gchar *string,
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_commit_id, 0, string);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_slave_preedit_changed_cb (GtkIMContext *slave,
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
if (ibusimcontext->ibuscontext) {
|
|
Packit |
3ff832 |
return;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_preedit_changed_id, 0);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_slave_preedit_start_cb (GtkIMContext *slave,
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
if (ibusimcontext->ibuscontext) {
|
|
Packit |
3ff832 |
return;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_preedit_start_id, 0);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_slave_preedit_end_cb (GtkIMContext *slave,
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
if (ibusimcontext->ibuscontext) {
|
|
Packit |
3ff832 |
return;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_preedit_end_id, 0);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gboolean
|
|
Packit |
3ff832 |
_slave_retrieve_surrounding_cb (GtkIMContext *slave,
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
gboolean return_value;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->ibuscontext) {
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_retrieve_surrounding_id, 0,
|
|
Packit |
3ff832 |
&return_value);
|
|
Packit |
3ff832 |
return return_value;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gboolean
|
|
Packit |
3ff832 |
_slave_delete_surrounding_cb (GtkIMContext *slave,
|
|
Packit |
3ff832 |
gint offset_from_cursor,
|
|
Packit |
3ff832 |
guint nchars,
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
gboolean return_value;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (ibusimcontext->ibuscontext) {
|
|
Packit |
3ff832 |
return FALSE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
g_signal_emit (ibusimcontext, _signal_delete_surrounding_id, 0, offset_from_cursor, nchars, &return_value);
|
|
Packit |
3ff832 |
return return_value;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
#ifdef OS_CHROMEOS
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_ibus_fake_context_destroy_cb (IBusInputContext *ibuscontext,
|
|
Packit |
3ff832 |
gpointer user_data)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
/* The fack IC may be destroyed when the connection is lost.
|
|
Packit |
3ff832 |
* Should release it. */
|
|
Packit |
3ff832 |
g_assert (ibuscontext == _fake_context);
|
|
Packit |
3ff832 |
g_object_unref (_fake_context);
|
|
Packit |
3ff832 |
_fake_context = NULL;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static GCancellable *_fake_cancellable = NULL;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_create_fake_input_context_done (IBusBus *bus,
|
|
Packit |
3ff832 |
GAsyncResult *res,
|
|
Packit |
3ff832 |
IBusIMContext *ibusimcontext)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
GError *error = NULL;
|
|
Packit |
3ff832 |
IBusInputContext *context = ibus_bus_create_input_context_async_finish (
|
|
Packit |
3ff832 |
_bus, res, &error);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (_fake_cancellable != NULL) {
|
|
Packit |
3ff832 |
g_object_unref (_fake_cancellable);
|
|
Packit |
3ff832 |
_fake_cancellable = NULL;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (context == NULL) {
|
|
Packit |
3ff832 |
g_warning ("Create fake input context failed: %s.", error->message);
|
|
Packit |
3ff832 |
g_error_free (error);
|
|
Packit |
3ff832 |
return;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
_fake_context = context;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_signal_connect (_fake_context, "forward-key-event",
|
|
Packit |
3ff832 |
G_CALLBACK (_ibus_context_forward_key_event_cb),
|
|
Packit |
3ff832 |
NULL);
|
|
Packit |
3ff832 |
g_signal_connect (_fake_context, "destroy",
|
|
Packit |
3ff832 |
G_CALLBACK (_ibus_fake_context_destroy_cb),
|
|
Packit |
3ff832 |
NULL);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
guint32 caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS | IBUS_CAP_SURROUNDING_TEXT;
|
|
Packit |
3ff832 |
ibus_input_context_set_capabilities (_fake_context, caps);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* focus in/out the fake context */
|
|
Packit |
3ff832 |
if (_focus_im_context == NULL)
|
|
Packit |
3ff832 |
ibus_input_context_focus_in (_fake_context);
|
|
Packit |
3ff832 |
else
|
|
Packit |
3ff832 |
ibus_input_context_focus_out (_fake_context);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_create_fake_input_context (void)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
g_return_if_fail (_fake_context == NULL);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* Global engine is always enabled in Chrome OS,
|
|
Packit |
3ff832 |
* so create fake IC, and set focus if no other IC has focus.
|
|
Packit |
3ff832 |
*/
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (_fake_cancellable != NULL) {
|
|
Packit |
3ff832 |
g_cancellable_cancel (_fake_cancellable);
|
|
Packit |
3ff832 |
g_object_unref (_fake_cancellable);
|
|
Packit |
3ff832 |
_fake_cancellable = NULL;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
_fake_cancellable = g_cancellable_new ();
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
ibus_bus_create_input_context_async (_bus,
|
|
Packit |
3ff832 |
"fake-gtk-im", -1,
|
|
Packit |
3ff832 |
_fake_cancellable,
|
|
Packit |
3ff832 |
(GAsyncReadyCallback)_create_fake_input_context_done,
|
|
Packit |
3ff832 |
NULL);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
#else
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_create_fake_input_context (void)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
/* For Linux desktop, do not use fake IC. */
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
#endif
|