public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Takao Fujiwara <tfujiwar@redhat.com>
To: git-commits@fedoraproject.org
Subject: [rpms/ibus] autotool: Deleted upstreamed patches
Date: Sun, 31 May 2026 02:06:57 GMT [thread overview]
Message-ID: <178019321700.1.14459109162438851166.rpms-ibus-3032216b57aa@fedoraproject.org> (raw)
A new commit has been pushed.
Repo : rpms/ibus
Branch : autotool
Commit : 3032216b57aac3d11c9d6323228d7a58a8b309aa
Author : Takao Fujiwara <tfujiwar@redhat.com>
Date : 2018-08-08T20:07:39+09:00
Stats : +0/-11241 in 1 file(s)
URL : https://src.fedoraproject.org/rpms/ibus/c/3032216b57aac3d11c9d6323228d7a58a8b309aa?branch=autotool
Log:
Deleted upstreamed patches
---
diff --git a/ibus-HEAD.patch b/ibus-HEAD.patch
deleted file mode 100644
index 0f9a5c8..0000000
--- a/ibus-HEAD.patch
+++ /dev/null
@@ -1,11241 +0,0 @@
-From c6439d74d5472c95de4d5c2cdc6487bfd508e3d8 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Thu, 15 Mar 2018 16:57:02 +0900
-Subject: [PATCH] ui/gtk3: Add num pad Enter, Down, Up, Left, Right on Emojier
-
-BUG=rhbz#1554813
-R=Shawn.P.Huang@gmail.com
-
-Review URL: https://codereview.appspot.com/337690043
----
- ui/gtk3/emojier.vala | 25 +++++++++++++++++--------
- 1 file changed, 17 insertions(+), 8 deletions(-)
-
-diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala
-index 8707e432..24029703 100644
---- a/ui/gtk3/emojier.vala
-+++ b/ui/gtk3/emojier.vala
-@@ -1918,6 +1918,7 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- return true;
- break;
- case Gdk.Key.Return:
-+ case Gdk.Key.KP_Enter:
- key_press_enter();
- return true;
- case Gdk.Key.BackSpace:
-@@ -1959,29 +1960,37 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- }
- return true;
- case Gdk.Key.Right:
-- key_press_cursor_horizontal(keyval, modifiers);
-+ case Gdk.Key.KP_Right:
-+ key_press_cursor_horizontal(Gdk.Key.Right, modifiers);
- return true;
- case Gdk.Key.Left:
-- key_press_cursor_horizontal(keyval, modifiers);
-+ case Gdk.Key.KP_Left:
-+ key_press_cursor_horizontal(Gdk.Key.Left, modifiers);
- return true;
- case Gdk.Key.Down:
-- key_press_cursor_vertical(keyval, modifiers);
-+ case Gdk.Key.KP_Down:
-+ key_press_cursor_vertical(Gdk.Key.Down, modifiers);
- return true;
- case Gdk.Key.Up:
-- key_press_cursor_vertical(keyval, modifiers);
-+ case Gdk.Key.KP_Up:
-+ key_press_cursor_vertical(Gdk.Key.Up, modifiers);
- return true;
- case Gdk.Key.Page_Down:
-- key_press_cursor_vertical(keyval, modifiers);
-+ case Gdk.Key.KP_Page_Down:
-+ key_press_cursor_vertical(Gdk.Key.Page_Down, modifiers);
- return true;
- case Gdk.Key.Page_Up:
-- key_press_cursor_vertical(keyval, modifiers);
-+ case Gdk.Key.KP_Page_Up:
-+ key_press_cursor_vertical(Gdk.Key.Page_Up, modifiers);
- return true;
- case Gdk.Key.Home:
-- if (key_press_cursor_home_end(keyval, modifiers))
-+ case Gdk.Key.KP_Home:
-+ if (key_press_cursor_home_end(Gdk.Key.Home, modifiers))
- return true;
- break;
- case Gdk.Key.End:
-- if (key_press_cursor_home_end(keyval, modifiers))
-+ case Gdk.Key.KP_End:
-+ if (key_press_cursor_home_end(Gdk.Key.End, modifiers))
- return true;
- break;
- case Gdk.Key.Insert:
---
-2.14.3
-
-From b184861396279d903e62bf6aad271a2205a79832 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Fri, 30 Mar 2018 12:33:59 +0900
-Subject: [PATCH] ui/gtk3: Sort Unicode candidates
-
-BUG=rhbz#1554714
-R=Shawn.P.Huang@gmail.com
-
-Review URL: https://codereview.appspot.com/339430043
----
- ui/gtk3/emojier.vala | 26 +++++++++++++++++++++++---
- 1 file changed, 23 insertions(+), 3 deletions(-)
-
-diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala
-index 24029703..0c0865f1 100644
---- a/ui/gtk3/emojier.vala
-+++ b/ui/gtk3/emojier.vala
-@@ -1144,9 +1144,11 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- lookup_emojis_from_annotation(string annotation) {
- GLib.SList<string>? total_emojis = null;
- unowned GLib.SList<string>? sub_emojis = null;
-+ unowned GLib.SList<unichar>? sub_exact_unicodes = null;
- unowned GLib.SList<unichar>? sub_unicodes = null;
- int length = annotation.length;
- if (m_has_partial_match && length >= m_partial_match_length) {
-+ GLib.SList<string>? sorted_emojis = null;
- foreach (unowned string key in
- m_annotation_to_emojis_dict.get_keys()) {
- if (key.length < length)
-@@ -1173,16 +1175,29 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- sub_emojis = m_annotation_to_emojis_dict.lookup(key);
- foreach (unowned string emoji in sub_emojis) {
- if (total_emojis.find_custom(emoji, GLib.strcmp) == null) {
-- total_emojis.append(emoji);
-+ sorted_emojis.insert_sorted(emoji, GLib.strcmp);
- }
- }
- }
-+ foreach (string emoji in sorted_emojis) {
-+ if (total_emojis.find_custom(emoji, GLib.strcmp) == null) {
-+ total_emojis.append(emoji);
-+ }
-+ }
- } else {
- sub_emojis = m_annotation_to_emojis_dict.lookup(annotation);
- foreach (unowned string emoji in sub_emojis)
- total_emojis.append(emoji);
- }
-+ sub_exact_unicodes = m_name_to_unicodes_dict.lookup(annotation);
-+ foreach (unichar code in sub_exact_unicodes) {
-+ string ch = code.to_string();
-+ if (total_emojis.find_custom(ch, GLib.strcmp) == null) {
-+ total_emojis.append(ch);
-+ }
-+ }
- if (length >= m_partial_match_length) {
-+ GLib.SList<string>? sorted_unicodes = null;
- foreach (unowned string key in m_name_to_unicodes_dict.get_keys()) {
- bool matched = false;
- if (key.index_of(annotation) >= 0)
-@@ -1192,11 +1207,16 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- sub_unicodes = m_name_to_unicodes_dict.lookup(key);
- foreach (unichar code in sub_unicodes) {
- string ch = code.to_string();
-- if (total_emojis.find_custom(ch, GLib.strcmp) == null) {
-- total_emojis.append(ch);
-+ if (sorted_unicodes.find_custom(ch, GLib.strcmp) == null) {
-+ sorted_unicodes.insert_sorted(ch, GLib.strcmp);
- }
- }
- }
-+ foreach (string ch in sorted_unicodes) {
-+ if (total_emojis.find_custom(ch, GLib.strcmp) == null) {
-+ total_emojis.append(ch);
-+ }
-+ }
- }
- return total_emojis;
- }
---
-2.14.3
-
-From 5788be80685f397c3db3bdf4e672d67cfb9b3433 Mon Sep 17 00:00:00 2001
-From: Jeremy Bicha <jbicha@ubuntu.com>
-Date: Fri, 30 Mar 2018 12:37:27 +0900
-Subject: [PATCH] Fix ucd directory override
-
-BUG=https://github.com/ibus/ibus/pull/1995
-R=Shawn.P.Huang@gmail.com
-
-Review URL: https://codereview.appspot.com/339450043
-
-Patch from Jeremy Bicha <jbicha@ubuntu.com>.
----
- configure.ac | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/configure.ac b/configure.ac
-index 6c00803f..d19aa874 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -666,7 +666,7 @@ AC_ARG_WITH(ucd-dir,
- AS_HELP_STRING([--with-ucd-dir[=DIR]],
- [Set the directory of UCD (Unicode Character Database) files.
- (default: "/usr/share/unicode/ucd")]),
-- UCD_DIR=$with_emoji_annotation_dir,
-+ UCD_DIR=$with_ucd_dir,
- UCD_DIR="/usr/share/unicode/ucd"
- )
- AC_SUBST(UCD_DIR)
---
-2.14.3
-
-From 75a6667b6ad8c8cb801cb160b7b04625334f9094 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Thu, 5 Apr 2018 16:54:41 +0900
-Subject: [PATCH] src/tests: Fix ibus-compose for the latest GTK
-
----
- src/tests/ibus-compose.c | 17 +++++++++++++++--
- 1 file changed, 15 insertions(+), 2 deletions(-)
-
-diff --git a/src/tests/ibus-compose.c b/src/tests/ibus-compose.c
-index eb7b9f19..aabb36ac 100644
---- a/src/tests/ibus-compose.c
-+++ b/src/tests/ibus-compose.c
-@@ -2,6 +2,10 @@
- #include "ibus.h"
- #include "ibuscomposetable.h"
-
-+#define GREEN "\033[0;32m"
-+#define RED "\033[0;31m"
-+#define NC "\033[0m"
-+
- IBusBus *m_bus;
- IBusComposeTable *m_compose_table;
- IBusEngine *m_engine;
-@@ -172,7 +176,12 @@ window_inserted_text_cb (GtkEntryBuffer *buffer,
- guint nchars,
- gpointer data)
- {
-+/* https://gitlab.gnome.org/GNOME/gtk/commit/9981f46e0b
-+ * The latest GTK does not emit "inserted-text" when the text is "".
-+ */
-+#if !GTK_CHECK_VERSION (3, 22, 16)
- static int n_loop = 0;
-+#endif
- static guint stride = 0;
- guint i;
- int seq;
-@@ -182,16 +191,18 @@ window_inserted_text_cb (GtkEntryBuffer *buffer,
-
- g_assert (m_compose_table != NULL);
-
-+#if !GTK_CHECK_VERSION (3, 22, 16)
- if (n_loop % 2 == 1) {
- n_loop = 0;
- return;
- }
-+#endif
- i = stride + (m_compose_table->max_seq_len + 2) - 1;
- seq = (i + 1) / (m_compose_table->max_seq_len + 2);
- if (m_compose_table->data[i] == code) {
-- test = "OK";
-+ test = GREEN "PASS" NC;
- } else {
-- test = "NG";
-+ test = RED "FAIL" NC;
- m_retval = -1;
- }
- g_print ("%05d/%05d %s expected: %04X typed: %04X\n",
-@@ -207,7 +218,9 @@ window_inserted_text_cb (GtkEntryBuffer *buffer,
- }
-
- stride += m_compose_table->max_seq_len + 2;
-+#if !GTK_CHECK_VERSION (3, 22, 16)
- n_loop++;
-+#endif
- gtk_entry_set_text (entry, "");
- }
-
---
-2.14.3
-
-From 28d0c1d4bc47beb38995d84cc4bb1d539c08a070 Mon Sep 17 00:00:00 2001
-From: Olivier Tilloy <olivier.tilloy@canonical.com>
-Date: Fri, 6 Apr 2018 16:02:11 +0900
-Subject: [PATCH] src: Make the call to chmod in ibus_bus_init conditional
-
-BUG=https://github.com/ibus/ibus/issues/1996
----
- src/ibusbus.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/src/ibusbus.c b/src/ibusbus.c
-index 11659c41..98820e8a 100644
---- a/src/ibusbus.c
-+++ b/src/ibusbus.c
-@@ -557,7 +557,6 @@ ibus_bus_init (IBusBus *bus)
- path = g_path_get_dirname (ibus_get_socket_path ());
-
- g_mkdir_with_parents (path, 0700);
-- g_chmod (path, 0700);
-
- if (stat (path, &buf) == 0) {
- if (buf.st_uid != getuid ()) {
-@@ -565,6 +564,9 @@ ibus_bus_init (IBusBus *bus)
- path, ibus_get_user_name ());
- return;
- }
-+ if (buf.st_mode != (S_IFDIR | S_IRWXU)) {
-+ g_chmod (path, 0700);
-+ }
- }
-
- g_free (path);
---
-2.14.3
-
-From 32f2f2bab149ad766674e7421f7044ebe98bb0b6 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Fri, 6 Apr 2018 20:24:08 +0900
-Subject: [PATCH] tests: Added an automation testing on console
-
-test-console.sh runs /usr/bin/ibus-daemon on console after install ibus.
-
-Login as root
- --builddir /root/ibus/src/tests --srcdir /root/ibus/src/tests
-
-Also added DISABLE_GUI_TESTS parameters for make check.
----
- bus/Makefile.am | 1 +
- src/tests/Makefile.am | 5 +-
- src/tests/runtest | 151 +++++++++++++++++++------------
- test/test-console.sh | 242 ++++++++++++++++++++++++++++++++++++++++++++++++++
- 4 files changed, 343 insertions(+), 56 deletions(-)
- create mode 100755 test/test-console.sh
-
-diff --git a/bus/Makefile.am b/bus/Makefile.am
-index 8bcc8e16..76166a0f 100644
---- a/bus/Makefile.am
-+++ b/bus/Makefile.am
-@@ -122,6 +122,7 @@ TESTS_ENVIRONMENT = \
- top_builddir=$(top_builddir) \
- top_srcdir=$(top_srcdir) \
- builddir=$(builddir) \
-+ srcdir=$(srcdir) \
- $(NULL)
-
- LOG_COMPILER = $(top_srcdir)/src/tests/runtest
-diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
-index 125be3fc..8bcac8f2 100644
---- a/src/tests/Makefile.am
-+++ b/src/tests/Makefile.am
-@@ -3,7 +3,8 @@
- # ibus - The Input Bus
- #
- # Copyright (c) 2007-2015 Peng Huang <shawn.p.huang@gmail.com>
--# Copyright (c) 2007-2015 Red Hat, Inc.
-+# Copyright (c) 2015-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+# Copyright (c) 2007-2018 Red Hat, Inc.
- #
- # This library is free software; you can redistribute it and/or
- # modify it under the terms of the GNU Lesser General Public
-@@ -66,6 +67,8 @@ TESTS_ENVIRONMENT = \
- top_builddir=$(top_builddir) \
- top_srcdir=$(top_srcdir) \
- builddir=$(builddir) \
-+ srcdir=$(srcdir) \
-+ DISABLE_GUI_TESTS=$(DISABLE_GUI_TESTS) \
- $(NULL)
-
- LOG_COMPILER = $(srcdir)/runtest
-diff --git a/src/tests/runtest b/src/tests/runtest
-index 0e43fee5..b3b2a1ce 100755
---- a/src/tests/runtest
-+++ b/src/tests/runtest
-@@ -1,5 +1,8 @@
- #!/bin/sh
-
-+# -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*-
-+# vim:set et sts=4:
-+
- # Run a test case given by the first argument in a separate directory.
- # This script may also launch $top_builddir/bus/ibus-daemon for testing.
-
-@@ -17,6 +20,8 @@
- : ${top_builddir:=../..}
- : ${top_srcdir:=../..}
- : ${builddir:=.}
-+: ${srcdir:=.}
-+: ${DISABLE_GUI_TESTS:=''}
-
- BUS_REQUIRED_TESTS="
- ibus-bus
-@@ -29,50 +34,51 @@ ibus-engine-switch
- ibus-compose
- test-stress
- "
-+retval=0
-
- # Portable replacement of basename.
- func_basename () {
-- case "$1" in
-+ case "$1" in
- */*)
-- expr "$1" : '.*/\(.*\)'
-- ;;
-+ expr "$1" : '.*/\(.*\)'
-+ ;;
- *)
-- echo "$1"
-- esac
-+ echo "$1"
-+ esac
- }
-
- # Portable replacement of dirname.
- func_dirname () {
-- case "$1" in
-+ case "$1" in
- */*)
-- expr "$1" : '\(.*\)/.*'
-- ;;
-+ expr "$1" : '\(.*\)/.*'
-+ ;;
- *)
-- echo .
-- esac
-+ echo .
-+ esac
- }
-
- # Kill ibus-daemon process and remove temporary files.
- func_cleanup () {
-- tstdir=$1
-- if test -f $tstdir/ibus-daemon.pid; then
-- . $tstdir/ibus-daemon.pid
-- kill $IBUS_DAEMON_PID &> /dev/null
-- fi
-- rm -fr $tstdir
-+ tstdir=$1
-+ if test -f $tstdir/ibus-daemon.pid; then
-+ . $tstdir/ibus-daemon.pid
-+ kill $IBUS_DAEMON_PID &> /dev/null
-+ fi
-+ rm -fr $tstdir
- }
-
- # Prepare component files necessary for testing, under components/.
- func_copy_component () {
-- file=$1
-- base=`func_basename $file`
-- libexecdir=`func_dirname $file`
-- # top_srcdir != top_builddir in make dist
-- libexecdir=`echo "$libexecdir" | sed -e "s|$top_srcdir|$top_builddir|"`
-- if test -f $file.in; then
-- mkdir -p components
-- sed "s|@libexecdir@|$libexecdir|g" < $file.in > components/$base
-- fi
-+ file=$1
-+ base=`func_basename $file`
-+ libexecdir=`func_dirname $file`
-+ # top_srcdir != top_builddir in make dist
-+ libexecdir=`echo "$libexecdir" | sed -e "s|$top_srcdir|$top_builddir|"`
-+ if test -f $file.in; then
-+ mkdir -p components
-+ sed "s|@libexecdir@|$libexecdir|g" < $file.in > components/$base
-+ fi
- }
-
- trap 'func_cleanup $tstdir' 1 2 3 15
-@@ -80,44 +86,79 @@ trap 'func_cleanup $tstdir' 1 2 3 15
- tst=$1; shift
- tstdir=tmp-`func_basename $tst`
-
--test -d $tstdir || mkdir $tstdir
--
--( cd $tstdir
--
-- need_bus=no
-- for t in $BUS_REQUIRED_TESTS; do
-+for t in $DISABLE_GUI_TESTS; do
- if test $t = `func_basename $tst`; then
-- need_bus=yes
-+ exit 77
- fi
-- done
--
-- if test $need_bus = yes; then
-- func_copy_component "../$top_srcdir/engine/simple.xml"
-- func_copy_component "../$top_srcdir/conf/memconf/memconf.xml"
-+done
-
-- IBUS_COMPONENT_PATH=$PWD/components
-- export IBUS_COMPONENT_PATH
-+test -d $tstdir || mkdir $tstdir
-
-- IBUS_ADDRESS_FILE=$PWD/ibus-daemon.pid
-- export IBUS_ADDRESS_FILE
-+run_test_case()
-+{
-+ pushd $tstdir
-+
-+ need_bus=no
-+ for t in $BUS_REQUIRED_TESTS; do
-+ if test $t = `func_basename $tst`; then
-+ need_bus=yes
-+ fi
-+ done
-+
-+ if test $need_bus = yes; then
-+ func_copy_component "../$top_srcdir/engine/simple.xml"
-+ func_copy_component "../$top_srcdir/conf/memconf/memconf.xml"
-+
-+ IBUS_COMPONENT_PATH=$PWD/components
-+ export IBUS_COMPONENT_PATH
-+
-+ IBUS_ADDRESS_FILE=$PWD/ibus-daemon.pid
-+ export IBUS_ADDRESS_FILE
-+
-+ # Start ibus-daemon.
-+ ../$top_builddir/bus/ibus-daemon \
-+ --daemonize \
-+ --cache=none \
-+ --panel=disable \
-+ --panel-extension=disable \
-+ --config=default \
-+ --verbose;
-+
-+ # Wait until all necessary components are up.
-+ sleep 1
-+ fi
-
-- # Start ibus-daemon.
-- ../$top_builddir/bus/ibus-daemon \
-- --daemonize \
-- --cache=none \
-- --panel=disable \
-- --panel-extension=disable \
-- --config=default \
-- --verbose;
-+ "../$tst" ${1+"$@"}
-
-- # Wait until all necessary components are up.
-- sleep 1
-- fi
-+ retval=`expr $retval \| $?`
-
-- exec "../$tst" ${1+"$@"} )
-+ $popd
-
--retval=$?
-+ func_cleanup $tstdir
-+}
-
--func_cleanup $tstdir
-+envfile=$srcdir/`func_basename $tst`.env
-+if test -f $envfile ; then
-+ ENVS="`cat $envfile`"
-+fi;
-+if test x"$ENVS" = x ; then
-+ run_test_case
-+else
-+ LANG_backup=$LANG
-+ i=1
-+ for e in $ENVS; do
-+ first=`echo "$e" | cut -c1-1`
-+ if test x"$first" = x"#" ; then
-+ continue
-+ fi
-+ export $e
-+ echo "Run `func_basename $tst` on $e"
-+ echo "======================="
-+ run_test_case
-+ echo ""
-+ i=`expr $i + 1`
-+ done
-+ export LANG=$LANG_backup
-+fi
-
- exit $retval
-diff --git a/test/test-console.sh b/test/test-console.sh
-new file mode 100755
-index 00000000..7199f7a7
---- /dev/null
-+++ b/test/test-console.sh
-@@ -0,0 +1,242 @@
-+#!/bin/sh
-+# -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*-
-+# vim:set noet ts=4:
-+#
-+# ibus-anthy - The Anthy engine for IBus
-+#
-+# Copyright (c) 2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+# Copyright (c) 2018 Red Hat, Inc.
-+#
-+# This program is free software; you can redistribute it and/or modify
-+# it under the terms of the GNU General Public License as published by
-+# the Free Software Foundation; either version 2 of the License, or
-+# (at your option) any later version.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License along
-+# with this program; if not, write to the Free Software Foundation, Inc.,
-+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-+
-+# This test runs /usr/bin/ibus-daemon after install ibus
-+#
-+# # init 3
-+# Login as root
-+# # /root/ibus/tests/test-console.sh --tests ibus-compose \
-+# --builddir /root/ibus/src/tests --srcdir /root/ibus/src/tests
-+
-+PROGNAME=`basename $0`
-+VERSION=0.1
-+DISPLAY=:99.0
-+BUILDDIR="."
-+SRCDIR="."
-+TEST_LOG=test-suite.log
-+HAVE_GRAPHICS=1
-+DESKTOP_COMMAND="gnome-session"
-+PID_XORG=0
-+PID_GNOME_SESSION=0
-+TESTS=""
-+GREEN='\033[0;32m'
-+RED='\033[0;31m'
-+NC='\033[0m'
-+
-+usage()
-+{
-+ echo -e \
-+"This test runs /usr/bin/ibus-daemon after install ibus\n" \
-+"$PROGNAME [OPTIONS…]\n" \
-+"\n" \
-+"OPTIONS:\n" \
-+"-h, --help This help\n" \
-+"-v, --version Show version\n" \
-+"-b, --builddir=BUILDDIR Set the BUILDDIR\n" \
-+"-s, --srcdir=SOURCEDIR Set the SOURCEDIR\n" \
-+"-c, --no-graphics Use Xvfb instead of Xorg\n" \
-+"-d, --desktop=DESKTOP Run DESTKTOP. The default is gnome-session\n" \
-+"-t, --tests=\"TESTS...\" Run TESTS programs which is separated by space\n" \
-+""
-+}
-+
-+parse_args()
-+{
-+ # This is GNU getopt. "sudo port getopt" in BSD?
-+ ARGS=`getopt -o hvb:s:cd:t: --long help,version,builddir:,srcdir:,no-graphics,desktop:,tests:\
-+ -- "$@"`;
-+ eval set -- "$ARGS"
-+ while [ 1 ] ; do
-+ case "$1" in
-+ -h | --help ) usage; exit 0;;
-+ -v | --version ) echo -e "$VERSION"; exit 0;;
-+ -b | --builddir ) BUILDDIR="$2"; shift 2;;
-+ -s | --srcdir ) SRCDIR="$2"; shift 2;;
-+ -c | --no-graphics ) HAVE_GRAPHICS=0; shift;;
-+ -d | --desktop ) DESKTOP_COMMAND="$2"; shift 2;;
-+ -t | --tests ) TESTS="$2"; shift 2;;
-+ -- ) shift; break;;
-+ * ) usage; exit 1;;
-+ esac
-+ done
-+}
-+
-+init_desktop()
-+{
-+ if test x$FORCE_TEST != x ; then
-+ RUN_ARGS="$RUN_ARGS --force"
-+ fi
-+
-+ if test ! -f $HOME/.config/gnome-initial-setup-done ; then
-+ if test ! -f /var/lib/AccountsService/users/$USER ; then
-+ mkdir -p /var/lib/AccountsService/users
-+ cat >> /var/lib/AccountsService/users/$USER << _EOF
-+[User]
-+Language=ja_JP.UTF-8
-+XSession=gnome
-+SystemAccount=false
-+_EOF
-+ fi
-+ mkdir -p $HOME/.config
-+ touch $HOME/.config/gnome-initial-setup-done
-+ fi
-+}
-+
-+run_dbus_daemon()
-+{
-+ a=`ps -ef | grep dbus-daemon | grep "\-\-system" | grep -v session | grep -v grep`
-+ if test x"$a" = x ; then
-+ eval `dbus-launch --sh-syntax`
-+ fi
-+ SUSER=`echo "$USER" | cut -c 1-7`
-+ a=`ps -ef | grep dbus-daemon | grep "$SUSER" | grep -v gdm | grep session | grep -v grep`
-+ if test x"$a" = x ; then
-+ systemctl --user start dbus
-+ export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$UID/bus
-+ fi
-+ systemctl --user status dbus | col -b
-+ ps -ef | grep dbus-daemon | grep "$SUSER" | grep -v gdm | egrep 'session|system' | grep -v grep
-+ systemctl --user show-environment | col -b
-+}
-+
-+run_desktop()
-+{
-+ if test $HAVE_GRAPHICS -eq 1 ; then
-+ /usr/libexec/Xorg.wrap -noreset +extension GLX +extension RANDR +extension RENDER -logfile ./xorg.log -config ./xorg.conf -configdir . $DISPLAY &
-+ else
-+ /usr/bin/Xvfb $DISPLAY -noreset +extension GLX +extension RANDR +extension RENDER -screen 0 1280x1024x24 &
-+ fi
-+ PID_XORG=$!
-+ sleep 1
-+ export DISPLAY=$DISPLAY
-+ $DESKTOP_COMMAND &
-+ PID_GNOME_SESSION=$!
-+ sleep 30
-+ if test "$DESKTOP_COMMAND" != "gnome-session" ; then
-+ ibus-daemon --daemonize --verbose
-+ sleep 1
-+ fi
-+}
-+
-+count_case_result()
-+{
-+ retval=$1
-+ pass=$2
-+ fail=$3
-+
-+ if test $retval -eq 0 ; then
-+ pass=`expr $pass + 1`
-+ else
-+ fail=`expr $fail + 1`
-+ fi
-+ echo $pass $fail
-+}
-+
-+echo_case_result()
-+{
-+ retval=$1
-+ tst=$2
-+ log=$3
-+ subtst=${4:-''}
-+
-+ if test $retval -eq 0 ; then
-+ echo -e "${GREEN}PASS${NC}: $tst $subtst"
-+ else
-+ echo -e "${RED}FAIL${NC}: $tst $subtst"
-+ echo "FAIL: $tst $subtst" >> $TEST_LOG
-+ echo "======================" >> $TEST_LOG
-+ echo "" >> $TEST_LOG
-+ cat "$log" >> $TEST_LOG
-+ echo "" >> $TEST_LOG
-+ fi
-+}
-+
-+run_test_suite()
-+{
-+ cd `dirname $0`
-+ pass=0
-+ fail=0
-+
-+ if test -f $TEST_LOG ; then
-+ rm $TEST_LOG
-+ fi
-+ for tst in $TESTS; do
-+ ENVS=
-+ if test -f $SRCDIR/${tst}.env ; then
-+ ENVS="`cat $SRCDIR/${tst}.env`"
-+ fi
-+ if test x"$ENVS" = x ; then
-+ $BUILDDIR/$tst >&${tst}.log
-+ retval=$?
-+ read pass fail << EOF
-+ `count_case_result $retval $pass $fail`
-+EOF
-+ echo_case_result $retval $tst ${tst}.log
-+ else
-+ LANG_backup=$LANG
-+ i=1
-+ for e in $ENVS; do
-+ first=`echo "$e" | cut -c1-1`
-+ if test x"$first" = x"#" ; then
-+ continue
-+ fi
-+ export $e
-+ $BUILDDIR/$tst >&${tst}.${i}.log
-+ retval=$?
-+ read pass fail << EOF
-+ `count_case_result $retval $pass $fail`
-+EOF
-+ echo_case_result $retval $tst ${tst}.${i}.log $e
-+ i=`expr $i + 1`
-+ done
-+ export LANG=$LANG_backup
-+ fi
-+ done
-+ echo ""
-+ echo -e "# ${GREEN}PASS${NC}: $pass"
-+ echo -e "# ${RED}FAIL${NC}: $fail"
-+ if test -f ${TEST_LOG} ; then
-+ echo ""
-+ echo -e "${RED}See ${TEST_LOG}$NC"
-+ fi
-+}
-+
-+finit()
-+{
-+ if test "$DESKTOP_COMMAND" != "gnome-session" ; then
-+ ibus exit
-+ fi
-+ kill $PID_GNOME_SESSION $PID_XORG
-+}
-+
-+main()
-+{
-+ parse_args $@
-+ init_desktop
-+ run_dbus_daemon
-+ run_desktop
-+ run_test_suite
-+ finit
-+}
-+
-+main $@
---
-2.14.3
-
-From 68e162a59c7943ee6207ff7d21f9a75d1e6f2f79 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Fri, 6 Apr 2018 20:35:50 +0900
-Subject: [PATCH] src/tests: Fix a typo in runtest
-
----
- src/tests/runtest | 5 ++---
- 1 file changed, 2 insertions(+), 3 deletions(-)
-
-diff --git a/src/tests/runtest b/src/tests/runtest
-index b3b2a1ce..09026be0 100755
---- a/src/tests/runtest
-+++ b/src/tests/runtest
-@@ -92,10 +92,9 @@ for t in $DISABLE_GUI_TESTS; do
- fi
- done
-
--test -d $tstdir || mkdir $tstdir
--
- run_test_case()
- {
-+ test -d $tstdir || mkdir $tstdir
- pushd $tstdir
-
- need_bus=no
-@@ -132,7 +131,7 @@ run_test_case()
-
- retval=`expr $retval \| $?`
-
-- $popd
-+ popd
-
- func_cleanup $tstdir
- }
---
-2.14.3
-
-From c360cbd830943a4bfb0ece9cc07b99a426dc2121 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Mon, 9 Apr 2018 11:57:09 +0900
-Subject: [PATCH] src/tests: Add ibus-compose.env
-
----
- src/tests/ibus-compose.env | 3 +++
- 1 file changed, 3 insertions(+)
- create mode 100644 src/tests/ibus-compose.env
-
-diff --git a/src/tests/ibus-compose.env b/src/tests/ibus-compose.env
-new file mode 100644
-index 00000000..734ab8fa
---- /dev/null
-+++ b/src/tests/ibus-compose.env
-@@ -0,0 +1,3 @@
-+LANG=el_GR.UTF-8
-+LANG=fi_FI.UTF-8
-+LANG=pt_BR.UTF-8
---
-2.14.3
-
-From 68bd2695c4cc6a06cb8a55a55fed2054d29f0995 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Fri, 13 Apr 2018 16:31:29 +0900
-Subject: [PATCH] src/tests: Fix a typo
-
----
- src/tests/Makefile.am | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
-index 8bcac8f2..11ebb531 100644
---- a/src/tests/Makefile.am
-+++ b/src/tests/Makefile.am
-@@ -68,7 +68,7 @@ TESTS_ENVIRONMENT = \
- top_srcdir=$(top_srcdir) \
- builddir=$(builddir) \
- srcdir=$(srcdir) \
-- DISABLE_GUI_TESTS=$(DISABLE_GUI_TESTS) \
-+ DISABLE_GUI_TESTS="$(DISABLE_GUI_TESTS)" \
- $(NULL)
-
- LOG_COMPILER = $(srcdir)/runtest
---
-2.14.3
-
-From 8d4c4738d07b6850e56ae74d46b7b13b7382f865 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Fri, 13 Apr 2018 17:33:50 +0900
-Subject: [PATCH] configure: Add --disable-python2 option
-
----
- bindings/pygobject/Makefile.am | 6 ++++++
- configure.ac | 37 ++++++++++++++++++++++++++++---------
- 2 files changed, 34 insertions(+), 9 deletions(-)
-
-diff --git a/bindings/pygobject/Makefile.am b/bindings/pygobject/Makefile.am
-index 238a537a..fb2e2a7a 100644
---- a/bindings/pygobject/Makefile.am
-+++ b/bindings/pygobject/Makefile.am
-@@ -4,6 +4,8 @@
- #
- # Copyright (c) 2012 Daiki Ueno <ueno@unixuser.org>
- # Copyright (c) 2014-2016 Peng Huang <shawn.p.huang@gmail.com>
-+# Copyright (c) 2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+# Copyright (c) 2012-2018 Red Hat, Inc.
- #
- # This library is free software; you can redistribute it and/or
- # modify it under the terms of the GNU Lesser General Public
-@@ -22,11 +24,13 @@
-
- NULL =
-
-+if ENABLE_PYTHON2
- py2_compile = PYTHON=$(PYTHON2) $(SHELL) $(py_compile)
- overrides2dir = $(py2overridesdir)
- overrides2_DATA = \
- gi/overrides/IBus.py \
- $(NULL)
-+endif
-
- overridesdir = $(pyoverridesdir)
- overrides_PYTHON = \
-@@ -56,6 +60,7 @@ EXTRA_DIST = \
- $(NULL)
-
- install-data-hook:
-+if ENABLE_PYTHON2
- @for data in $(overrides2_DATA); do \
- file=`echo $$data | sed -e 's|^.*/||'`; \
- dlist="$$dlist $$file"; \
-@@ -63,6 +68,7 @@ install-data-hook:
- $(py2_compile) --destdir "$(DESTDIR)" \
- --basedir "$(overrides2dir)" \
- $$dlist
-+endif
- $(NULL)
-
- -include $(top_srcdir)/git.mk
-diff --git a/configure.ac b/configure.ac
-index d19aa874..085cecb8 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -391,6 +391,14 @@ fi
- AC_PATH_PROG(ENV_IBUS_TEST, env)
- AC_SUBST(ENV_IBUS_TEST)
-
-+AC_ARG_ENABLE(python2,
-+ AS_HELP_STRING([--disable-python2],
-+ [Do not install bindings/pygobject/gi and ibus for python2.
-+ '--disable-python2' bring '--disable-python-library'.]),
-+ [enable_python2=$enableval],
-+ [enable_python2=yes]
-+)
-+
- AC_ARG_ENABLE(python-library,
- AS_HELP_STRING([--enable-python-library],
- [Use ibus python library]),
-@@ -405,10 +413,6 @@ AC_ARG_ENABLE(setup,
- [enable_setup=yes]
- )
-
--AM_CONDITIONAL([ENABLE_PYTHON_LIBRARY], [test x"$enable_python_library" = x"yes"])
--AM_CONDITIONAL([ENABLE_SETUP], [test x"$enable_setup" = x"yes"])
--AM_CONDITIONAL([ENABLE_DAEMON], [true])
--
- # Define python version
- AC_ARG_WITH(python,
- AS_HELP_STRING([--with-python[=PATH]],
-@@ -417,12 +421,24 @@ AC_ARG_WITH(python,
- )
-
- AM_PATH_PYTHON([2.5])
--AC_PATH_PROG(PYTHON2, python2)
-
--if test x"$PYTHON2" = x""; then
-- PYTHON2=$PYTHON
-+if test x"$enable_python2" != x"yes"; then
-+ enable_python_library=no
-+ PYTHON2=
-+ enable_python2="no (disabled, use --enable-python2 to enable)"
-+else
-+ AC_PATH_PROG(PYTHON2, python2)
-+
-+ if test x"$PYTHON2" = x""; then
-+ PYTHON2=$PYTHON
-+ fi
- fi
-
-+AM_CONDITIONAL([ENABLE_PYTHON2], [test x"$enable_python2" = x"yes"])
-+AM_CONDITIONAL([ENABLE_PYTHON_LIBRARY], [test x"$enable_python_library" = x"yes"])
-+AM_CONDITIONAL([ENABLE_SETUP], [test x"$enable_setup" = x"yes"])
-+AM_CONDITIONAL([ENABLE_DAEMON], [true])
-+
- PYGOBJECT_REQUIRED=3.0.0
-
- PKG_CHECK_EXISTS([pygobject-3.0 >= $PYGOBJECT_REQUIRED],
-@@ -434,8 +450,10 @@ if test "x$enable_pygobject" = "xyes"; then
- pyoverridesdir=`$PYTHON -c "import gi; print(gi._overridesdir)"`
- AC_SUBST(pyoverridesdir)
-
-- py2overridesdir=`$PYTHON2 -c "import gi; print(gi._overridesdir)"`
-- AC_SUBST(py2overridesdir)
-+ if test x"$enable_python2" = x"yes"; then
-+ py2overridesdir=`$PYTHON2 -c "import gi; print(gi._overridesdir)"`
-+ AC_SUBST(py2overridesdir)
-+ fi
- fi
-
- AM_CONDITIONAL(ENABLE_PYGOBJECT, test x"$enable_pygobject" = "xyes")
-@@ -752,6 +770,7 @@ Build options:
- CFLAGS $CFLAGS
- PYTHON $PYTHON
- PYTHON2 $PYTHON2
-+ Enable python2 $enable_python2
- Gtk2 immodule dir $GTK2_IM_MODULEDIR
- Gtk3 immodule dir $GTK3_IM_MODULEDIR
- Build gtk2 immodule $enable_gtk2
---
-2.14.3
-
-From 7bc160f2139799b853678264c6b01277f0721336 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Fri, 13 Apr 2018 19:39:09 +0900
-Subject: [PATCH] bus: Add DISABLE_GUI_TESTS for test-stress
-
----
- bus/Makefile.am | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/bus/Makefile.am b/bus/Makefile.am
-index 76166a0f..dda79eac 100644
---- a/bus/Makefile.am
-+++ b/bus/Makefile.am
-@@ -110,7 +110,6 @@ if ENABLE_EMOJI_DICT
- AM_CFLAGS += -DEMOJI_DICT
- endif
-
--
- if ENABLE_TESTS
- TESTS = \
- test-matchrule \
-@@ -123,6 +122,7 @@ TESTS_ENVIRONMENT = \
- top_srcdir=$(top_srcdir) \
- builddir=$(builddir) \
- srcdir=$(srcdir) \
-+ DISABLE_GUI_TESTS="$(DISABLE_GUI_TESTS)" \
- $(NULL)
-
- LOG_COMPILER = $(top_srcdir)/src/tests/runtest
---
-2.14.3
-
-From 10cc30eac200d10b581d9d2122d5a732f4880943 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Tue, 17 Apr 2018 14:00:20 +0900
-Subject: [PATCH] src/tests: Enable GSettings in runtest
-
----
- src/tests/runtest | 22 ++++++++++++++++++++++
- 1 file changed, 22 insertions(+)
-
-diff --git a/src/tests/runtest b/src/tests/runtest
-index 09026be0..35825b1b 100755
---- a/src/tests/runtest
-+++ b/src/tests/runtest
-@@ -34,6 +34,8 @@ ibus-engine-switch
- ibus-compose
- test-stress
- "
-+IBUS_SCHEMA_FILE='org.freedesktop.ibus.gschema.xml'
-+
- retval=0
-
- # Portable replacement of basename.
-@@ -92,6 +94,12 @@ for t in $DISABLE_GUI_TESTS; do
- fi
- done
-
-+# IBusEngine has GSettings
-+if test ! -f "$top_builddir/data/dconf/$IBUS_SCHEMA_FILE" ; then
-+ echo "NOT FOUND $top_builddir/data/dconf/$IBUS_SCHEMA_FILE"
-+ exit -1
-+fi
-+
- run_test_case()
- {
- test -d $tstdir || mkdir $tstdir
-@@ -114,6 +122,20 @@ run_test_case()
- IBUS_ADDRESS_FILE=$PWD/ibus-daemon.pid
- export IBUS_ADDRESS_FILE
-
-+ cp "../$top_builddir/data/dconf/$IBUS_SCHEMA_FILE" $PWD
-+ glib-compile-schemas $PWD
-+ if test $? -ne 0 ; then
-+ echo "FAILED glib-compile-schemas"
-+ retval=1
-+ return
-+ fi
-+ if test ! -f $PWD/gschemas.compiled ; then
-+ echo "NOT FOUND $PWD/gschemas.compiled"
-+ retval=1
-+ return
-+ fi
-+ export GSETTINGS_SCHEMA_DIR=$PWD
-+
- # Start ibus-daemon.
- ../$top_builddir/bus/ibus-daemon \
- --daemonize \
---
-2.14.3
-
-From 3280848b42b07afbac3d59066474c5f429de9182 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Tue, 17 Apr 2018 14:43:02 +0900
-Subject: [PATCH] bus: Enable sub package of gtkextension.xml and
- ibus-extension-gtk3
-
-GNOME destkop asked not to install ibus-extension-gtk3 by default
-since the UI is not called by gnome-shell.
-
-BUG=rhbz#1567689
----
- bus/main.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/bus/main.c b/bus/main.c
-index 7aa89fc4..e1cc423b 100644
---- a/bus/main.c
-+++ b/bus/main.c
-@@ -293,7 +293,7 @@ main (gint argc, gchar **argv)
- if (component) {
- bus_component_set_restart (component, restart);
- }
-- if (component == NULL ||
-+ if (component != NULL &&
- !bus_component_start (component, g_verbose)) {
- g_printerr ("Can not execute default panel program\n");
- exit (-1);
---
-2.14.3
-
-From d8f901f856ddd75baba5826038d1346c5a43d048 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Fri, 20 Apr 2018 15:58:06 +0900
-Subject: [PATCH] Replace OnlyShowIn= with NoDisplay=true
-
-BUG=rhbz#1567689
----
- ui/gtk3/ibus-extension-gtk3.desktop.in.in | 2 +-
- ui/gtk3/ibus-ui-emojier.desktop.in.in | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/ui/gtk3/ibus-extension-gtk3.desktop.in.in b/ui/gtk3/ibus-extension-gtk3.desktop.in.in
-index 6ec5585f..a119ec8e 100644
---- a/ui/gtk3/ibus-extension-gtk3.desktop.in.in
-+++ b/ui/gtk3/ibus-extension-gtk3.desktop.in.in
-@@ -3,4 +3,4 @@ _Name=Emoji Choice
- Icon=ibus
- Exec=@libexecdir@/ibus-extension-gtk3
- Type=Application
--OnlyShowIn=
-+NoDisplay=true
-diff --git a/ui/gtk3/ibus-ui-emojier.desktop.in.in b/ui/gtk3/ibus-ui-emojier.desktop.in.in
-index f4b750a8..6d9422d5 100644
---- a/ui/gtk3/ibus-ui-emojier.desktop.in.in
-+++ b/ui/gtk3/ibus-ui-emojier.desktop.in.in
-@@ -3,4 +3,4 @@ _Name=Emoji Choice
- Icon=ibus
- Exec=ibus emoji
- Type=Application
--OnlyShowIn=
-+NoDisplay=true
---
-2.14.3
-
-From 886ad3651d16dd821e2526e8601c69738533a7e8 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Mon, 7 May 2018 12:35:03 +0900
-Subject: [PATCH] src: Fix SEGV in IBusEngine if no emoji shortcut keys
-
-BUG=https://github.com/ibus/ibus/issues/2005
----
- src/ibusengine.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/src/ibusengine.c b/src/ibusengine.c
-index 9a0b1a8a..fd61102a 100644
---- a/src/ibusengine.c
-+++ b/src/ibusengine.c
-@@ -925,6 +925,9 @@ ibus_engine_filter_key_event (IBusEngine *engine,
- g_return_val_if_fail (IBUS_IS_ENGINE (engine), FALSE);
-
- priv = engine->priv;
-+ if (!priv->emoji_keybindings)
-+ return FALSE;
-+
- modifiers = state & IBUS_MODIFIER_FILTER;
- if (keyval >= IBUS_KEY_A && keyval <= IBUS_KEY_Z &&
- (modifiers & IBUS_SHIFT_MASK) != 0) {
---
-2.14.3
-
-From 196216a89a9167425dd9b41f4f1d8a494d370249 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Fri, 11 May 2018 19:13:03 +0900
-Subject: [PATCH] src: Add ibus-keypress
-
----
- configure.ac | 8 ++
- src/tests/Makefile.am | 7 ++
- src/tests/ibus-keypress.c | 298 ++++++++++++++++++++++++++++++++++++++++++++++
- src/tests/runtest | 1 +
- 4 files changed, 314 insertions(+)
- create mode 100644 src/tests/ibus-keypress.c
-
-diff --git a/configure.ac b/configure.ac
-index 085cecb8..f332a775 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -621,6 +621,14 @@ if test x"$enable_libnotify" = x"yes"; then
- enable_libnotify="yes (enabled, use --disable-libnotify to disable)"
- fi
-
-+PKG_CHECK_MODULES(XTEST,
-+ [x11 xtst],
-+ [enable_xtest=yes],
-+ [enable_xtest=no]
-+)
-+AM_CONDITIONAL([ENABLE_XTEST], [test x"$enable_xtest" = x"yes"])
-+
-+
- # --disable-emoji-dict option.
- AC_ARG_ENABLE(emoji-dict,
- AS_HELP_STRING([--disable-emoji-dict],
-diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
-index 11ebb531..5f21ebcd 100644
---- a/src/tests/Makefile.am
-+++ b/src/tests/Makefile.am
-@@ -61,6 +61,9 @@ endif
-
- if ENABLE_GTK3
- TESTS += ibus-compose
-+if ENABLE_XTEST
-+TESTS += ibus-keypress
-+endif
- endif
-
- TESTS_ENVIRONMENT = \
-@@ -103,6 +106,10 @@ ibus_inputcontext_create_LDADD = $(prog_ldadd)
- ibus_keynames_SOURCES = ibus-keynames.c
- ibus_keynames_LDADD = $(prog_ldadd)
-
-+ibus_keypress_SOURCES = ibus-keypress.c
-+ibus_keypress_CFLAGS = @GTK3_CFLAGS@ @XTEST_CFLAGS@
-+ibus_keypress_LDADD = $(prog_ldadd) @GTK3_LIBS@ @XTEST_LIBS@
-+
- ibus_registry_SOURCES = ibus-registry.c
- ibus_registry_LDADD = $(prog_ldadd)
-
-diff --git a/src/tests/ibus-keypress.c b/src/tests/ibus-keypress.c
-new file mode 100644
-index 00000000..3486523b
---- /dev/null
-+++ b/src/tests/ibus-keypress.c
-@@ -0,0 +1,298 @@
-+#include <gtk/gtk.h>
-+#include <gdk/gdkx.h>
-+#include "ibus.h"
-+#include <stdlib.h>
-+#include <X11/Xlib.h>
-+#include <X11/extensions/XTest.h>
-+
-+#define GREEN "\033[0;32m"
-+#define RED "\033[0;31m"
-+#define NC "\033[0m"
-+
-+typedef struct _KeyData {
-+ guint keyval;
-+ guint modifiers;
-+} KeyData;
-+
-+static const KeyData test_cases[][30] = {
-+ { { IBUS_KEY_a, 0 }, { IBUS_KEY_comma, IBUS_SHIFT_MASK },
-+ { IBUS_KEY_b, 0 }, { IBUS_KEY_period, IBUS_SHIFT_MASK },
-+ { IBUS_KEY_c, 0 }, { IBUS_KEY_slash, IBUS_SHIFT_MASK },
-+ { IBUS_KEY_d, 0 }, { IBUS_KEY_semicolon, IBUS_SHIFT_MASK },
-+ { IBUS_KEY_e, 0 }, { IBUS_KEY_apostrophe, IBUS_SHIFT_MASK },
-+ { IBUS_KEY_f, 0 }, { IBUS_KEY_bracketleft, IBUS_SHIFT_MASK },
-+ { IBUS_KEY_g, 0 }, { IBUS_KEY_backslash, IBUS_SHIFT_MASK },
-+ { 0, 0 } },
-+ { { IBUS_KEY_grave, IBUS_SHIFT_MASK }, { IBUS_KEY_a, IBUS_SHIFT_MASK },
-+ { IBUS_KEY_1, IBUS_SHIFT_MASK }, { IBUS_KEY_b, IBUS_SHIFT_MASK },
-+ { IBUS_KEY_2, IBUS_SHIFT_MASK }, { IBUS_KEY_c, IBUS_SHIFT_MASK },
-+ { IBUS_KEY_3, IBUS_SHIFT_MASK }, { IBUS_KEY_d, IBUS_SHIFT_MASK },
-+ { IBUS_KEY_9, IBUS_SHIFT_MASK }, { IBUS_KEY_e, IBUS_SHIFT_MASK },
-+ { IBUS_KEY_0, IBUS_SHIFT_MASK }, { IBUS_KEY_f, IBUS_SHIFT_MASK },
-+ { IBUS_KEY_equal, IBUS_SHIFT_MASK }, { IBUS_KEY_g, IBUS_SHIFT_MASK },
-+ { 0, 0 } },
-+ { { 0, 0 } }
-+};
-+
-+KeyData test_end_key = { IBUS_KEY_z, IBUS_SHIFT_MASK };
-+
-+static const gunichar test_results[][60] = {
-+ { 'a', '<', 'b', '>', 'c', '?', 'd', ':', 'e', '"', 'f', '{', 'g', '|', 0 },
-+ { '~', 'A', '!', 'B', '@', 'C', '#', 'D', '(', 'E', ')', 'F', '+', 'G', 0 },
-+ { 0 }
-+};
-+
-+
-+IBusBus *m_bus;
-+IBusEngine *m_engine;
-+
-+static gboolean window_focus_in_event_cb (GtkWidget *entry,
-+ GdkEventFocus *event,
-+ gpointer data);
-+
-+static IBusEngine *
-+create_engine_cb (IBusFactory *factory, const gchar *name, gpointer data)
-+{
-+ static int i = 1;
-+ gchar *engine_path =
-+ g_strdup_printf ("/org/freedesktop/IBus/engine/simpletest/%d",
-+ i++);
-+
-+ m_engine = ibus_engine_new_with_type (IBUS_TYPE_ENGINE_SIMPLE,
-+ name,
-+ engine_path,
-+ ibus_bus_get_connection (m_bus));
-+ g_free (engine_path);
-+ return m_engine;
-+}
-+
-+static gboolean
-+register_ibus_engine ()
-+{
-+ IBusFactory *factory;
-+ IBusComponent *component;
-+ IBusEngineDesc *desc;
-+
-+ m_bus = ibus_bus_new ();
-+ if (!ibus_bus_is_connected (m_bus)) {
-+ g_critical ("ibus-daemon is not running.");
-+ return FALSE;
-+ }
-+ factory = ibus_factory_new (ibus_bus_get_connection (m_bus));
-+ g_signal_connect (factory, "create-engine",
-+ G_CALLBACK (create_engine_cb), NULL);
-+
-+ component = ibus_component_new (
-+ "org.freedesktop.IBus.SimpleTest",
-+ "Simple Engine Test",
-+ "0.0.1",
-+ "GPL",
-+ "Takao Fujiwara <takao.fujiwara1@gmail.com>",
-+ "https://github.com/ibus/ibus/wiki",
-+ "",
-+ "ibus");
-+ desc = ibus_engine_desc_new (
-+ "xkbtest:us::eng",
-+ "XKB Test",
-+ "XKB Test",
-+ "en",
-+ "GPL",
-+ "Takao Fujiwara <takao.fujiwara1@gmail.com>",
-+ "ibus-engine",
-+ "us");
-+ ibus_component_add_engine (component, desc);
-+ ibus_bus_register_component (m_bus, component);
-+
-+ return TRUE;
-+}
-+
-+static gboolean
-+finit (gpointer data)
-+{
-+ g_critical ("time out");
-+ gtk_main_quit ();
-+ return FALSE;
-+}
-+
-+static void
-+send_key_event (Display *xdisplay,
-+ guint keyval,
-+ guint modifiers)
-+{
-+ static struct {
-+ guint state;
-+ KeySym keysym;
-+ } state2keysym[] = {
-+ { IBUS_CONTROL_MASK, XK_Control_L } ,
-+ { IBUS_MOD1_MASK, XK_Alt_L },
-+ { IBUS_MOD4_MASK, XK_Super_L },
-+ { IBUS_SHIFT_MASK, XK_Shift_L },
-+ { IBUS_LOCK_MASK, XK_Caps_Lock },
-+ { 0, 0L }
-+ };
-+ int i;
-+ guint keycode;
-+ guint state = modifiers;
-+
-+ while (state) {
-+ for (i = 0; state2keysym[i].state; i++) {
-+ if ((state2keysym[i].state & state) != 0) {
-+ keycode = XKeysymToKeycode (xdisplay, state2keysym[i].keysym);
-+ XTestFakeKeyEvent (xdisplay, keycode, True, CurrentTime);
-+ XSync (xdisplay, False);
-+ state ^= state2keysym[i].state;
-+ break;
-+ }
-+ }
-+ }
-+ keycode = XKeysymToKeycode (xdisplay, keyval);
-+ XTestFakeKeyEvent (xdisplay, keycode, True, CurrentTime);
-+ XSync (xdisplay, False);
-+ XTestFakeKeyEvent (xdisplay, keycode, False, CurrentTime);
-+ XSync (xdisplay, False);
-+
-+ state = modifiers;
-+ while (state) {
-+ for (i = G_N_ELEMENTS (state2keysym) - 1; i >= 0; i--) {
-+ if ((state2keysym[i].state & state) != 0) {
-+ keycode = XKeysymToKeycode (xdisplay, state2keysym[i].keysym);
-+ XTestFakeKeyEvent (xdisplay, keycode, False, CurrentTime);
-+ XSync (xdisplay, False);
-+ state ^= state2keysym[i].state;
-+ break;
-+ }
-+ }
-+ }
-+}
-+
-+static void
-+set_engine_cb (GObject *object,
-+ GAsyncResult *res,
-+ gpointer data)
-+{
-+ IBusBus *bus = IBUS_BUS (object);
-+ GtkWidget *entry = GTK_WIDGET (data);
-+ GdkDisplay *display;
-+ Display *xdisplay;
-+ GError *error = NULL;
-+ int i, j;
-+
-+ g_assert (GTK_IS_ENTRY (entry));
-+
-+ if (!ibus_bus_set_global_engine_async_finish (bus, res, &error)) {
-+ g_critical ("set engine failed: %s", error->message);
-+ g_error_free (error);
-+ return;
-+ }
-+
-+ display = gtk_widget_get_display (entry);
-+ if (GDK_IS_X11_DISPLAY (display)) {
-+ xdisplay = gdk_x11_display_get_xdisplay (display);
-+ } else {
-+#if 0
-+ xdisplay = XOpenDisplay (NULL);
-+#else
-+ g_critical ("No idea to simulate key events in Wayland\n");
-+#endif
-+ }
-+ g_return_if_fail (xdisplay);
-+
-+ for (i = 0; test_cases[i][0].keyval; i++) {
-+ for (j = 0; test_cases[i][j].keyval; j++) {
-+ send_key_event (xdisplay,
-+ test_cases[i][j].keyval,
-+ test_cases[i][j].modifiers);
-+ }
-+ send_key_event (xdisplay, test_end_key.keyval, test_end_key.modifiers);
-+ }
-+
-+ g_timeout_add_seconds (10, finit, NULL);
-+}
-+
-+static gboolean
-+window_focus_in_event_cb (GtkWidget *entry, GdkEventFocus *event, gpointer data)
-+{
-+ g_assert (m_bus != NULL);
-+ ibus_bus_set_global_engine_async (m_bus,
-+ "xkbtest:us::eng",
-+ -1,
-+ NULL,
-+ set_engine_cb,
-+ entry);
-+ return FALSE;
-+}
-+
-+static void
-+window_inserted_text_cb (GtkEntryBuffer *buffer,
-+ guint position,
-+ const gchar *chars,
-+ guint nchars,
-+ gpointer data)
-+{
-+ GtkWidget *entry = data;
-+ static int i = 0;
-+ static int j = 0;
-+
-+ if (g_utf8_get_char (chars) == 'Z') {
-+ int k;
-+ g_print ("\n" GREEN "PASS" NC ": ");
-+ for (k = 0; k < j; k++)
-+ g_print ("%lc(%X) ", test_results[i][k], test_results[i][k]);
-+ g_print ("\n");
-+ i++;
-+ j = 0;
-+ if (test_results[i][0] == 0)
-+ gtk_main_quit ();
-+ else
-+ gtk_entry_set_text (GTK_ENTRY (entry), "");
-+ return;
-+ }
-+ g_assert (g_utf8_get_char (chars) == test_results[i][j]);
-+ j++;
-+}
-+
-+static void
-+create_window ()
-+{
-+ GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-+ GtkWidget *entry = gtk_entry_new ();
-+ GtkEntryBuffer *buffer;
-+
-+ g_signal_connect (window, "destroy",
-+ G_CALLBACK (gtk_main_quit), NULL);
-+ g_signal_connect (entry, "focus-in-event",
-+ G_CALLBACK (window_focus_in_event_cb), NULL);
-+ buffer = gtk_entry_get_buffer (GTK_ENTRY (entry));
-+ g_signal_connect (buffer, "inserted-text",
-+ G_CALLBACK (window_inserted_text_cb), entry);
-+ gtk_container_add (GTK_CONTAINER (window), entry);
-+ gtk_widget_show_all (window);
-+}
-+
-+static void
-+test_keypress (void)
-+{
-+ int status = 0;
-+ GError *error = NULL;
-+
-+ g_spawn_command_line_sync ("setxkbmap -layout us",
-+ NULL, NULL,
-+ &status, &error);
-+ g_assert (register_ibus_engine ());
-+
-+ create_window ();
-+ gtk_main ();
-+}
-+
-+int
-+main (int argc, char *argv[])
-+{
-+ ibus_init ();
-+ g_test_init (&argc, &argv, NULL);
-+ gtk_init (&argc, &argv);
-+
-+ g_test_add_func ("/ibus/keyrepss", test_keypress);
-+
-+
-+ return g_test_run ();
-+}
-diff --git a/src/tests/runtest b/src/tests/runtest
-index 35825b1b..b6b845d6 100755
---- a/src/tests/runtest
-+++ b/src/tests/runtest
-@@ -32,6 +32,7 @@ ibus-inputcontext
- ibus-inputcontext-create
- ibus-engine-switch
- ibus-compose
-+ibus-keypress
- test-stress
- "
- IBUS_SCHEMA_FILE='org.freedesktop.ibus.gschema.xml'
---
-2.14.3
-
-From 8ab0b603ba1cd8701583aee46c712898d52005f1 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Wed, 23 May 2018 19:20:10 +0900
-Subject: [PATCH] bus: Fix a SEGV in bus_input_context_emit_signal
-
-IBus engines can call 'RequireSurroundingText' for a fake input context
-if there is no input focus.
----
- bus/inputcontext.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/bus/inputcontext.c b/bus/inputcontext.c
-index a957d107..dfb98c36 100644
---- a/bus/inputcontext.c
-+++ b/bus/inputcontext.c
-@@ -716,7 +716,9 @@ bus_input_context_emit_signal (BusInputContext *context,
- GError **error)
- {
- if (context->connection == NULL) {
-- g_variant_unref (parameters);
-+ /* fake context has no connections. */
-+ if (parameters)
-+ g_variant_unref (parameters);
- return TRUE;
- }
-
---
-2.14.3
-
-From a1f91b27145b046a112bb5eba2561880dae5d6a2 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Mon, 4 Jun 2018 17:44:17 +0900
-Subject: [PATCH] ui/gtk3: Get PangoAttrList of auxiliary text from
- IBusText
-
-Since IBus auxiliary text would be one line, it's better to show the
-character attributes likes color, italic, bold, on the auxiliary text.
-
-Also deleted the cursor width from the X position of CandidatePanel
-because IBus preedit overrides the original cursor of the applications.
----
- ui/gtk3/candidatepanel.vala | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/ui/gtk3/candidatepanel.vala b/ui/gtk3/candidatepanel.vala
-index ec2d3db4..d404c659 100644
---- a/ui/gtk3/candidatepanel.vala
-+++ b/ui/gtk3/candidatepanel.vala
-@@ -3,7 +3,7 @@
- * ibus - The Input Bus
- *
- * Copyright(c) 2011-2015 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright(c) 2015-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright(c) 2015-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
-@@ -153,6 +153,8 @@ public class CandidatePanel : Gtk.Box{
- public void set_auxiliary_text(IBus.Text? text) {
- if (text != null) {
- m_aux_label.set_text(text.get_text());
-+ Pango.AttrList attrs = get_pango_attr_list_from_ibus_text(text);
-+ m_aux_label.set_attributes(attrs);
- m_aux_label.show();
- } else {
- m_aux_label.set_text("");
-@@ -314,7 +316,7 @@ public class CandidatePanel : Gtk.Box{
-
- private void adjust_window_position_horizontal() {
- Gdk.Point cursor_right_bottom = {
-- m_cursor_location.x + m_cursor_location.width,
-+ m_cursor_location.x,
- m_cursor_location.y + m_cursor_location.height
- };
-
---
-2.14.3
-
-From cf4e2f1d815b700b0470380e0ff428ff266cc18a Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Thu, 14 Jun 2018 17:29:06 +0900
-Subject: [PATCH] bus: Rename panel-extension to emoji-extension for CLI
-
----
- bus/main.c | 14 +++++++-------
- 1 file changed, 7 insertions(+), 7 deletions(-)
-
-diff --git a/bus/main.c b/bus/main.c
-index e1cc423b..2fb37b69 100644
---- a/bus/main.c
-+++ b/bus/main.c
-@@ -43,7 +43,7 @@ static gboolean xim = FALSE;
- static gboolean replace = FALSE;
- static gboolean restart = FALSE;
- static gchar *panel = "default";
--static gchar *panel_extension = "default";
-+static gchar *emoji_extension = "default";
- static gchar *config = "default";
- static gchar *desktop = "gnome";
-
-@@ -67,7 +67,7 @@ static const GOptionEntry entries[] =
- { "xim", 'x', 0, G_OPTION_ARG_NONE, &xim, "execute ibus XIM server.", NULL },
- { "desktop", 'n', 0, G_OPTION_ARG_STRING, &desktop, "specify the name of desktop session. [default=gnome]", "name" },
- { "panel", 'p', 0, G_OPTION_ARG_STRING, &panel, "specify the cmdline of panel program. pass 'disable' not to start a panel program.", "cmdline" },
-- { "panel-extension", 'E', 0, G_OPTION_ARG_STRING, &panel_extension, "specify the cmdline of panel extension program. pass 'disable' not to start an extension program.", "cmdline" },
-+ { "emoji-extension", 'E', 0, G_OPTION_ARG_STRING, &emoji_extension, "specify the cmdline of emoji extension program. pass 'disable' not to start an extension program.", "cmdline" },
- { "config", 'c', 0, G_OPTION_ARG_STRING, &config, "specify the cmdline of config program. pass 'disable' not to start a config program.", "cmdline" },
- { "address", 'a', 0, G_OPTION_ARG_STRING, &g_address, "specify the address of ibus daemon.", "address" },
- { "replace", 'r', 0, G_OPTION_ARG_NONE, &replace, "if there is an old ibus-daemon is running, it will be replaced.", NULL },
-@@ -245,7 +245,7 @@ main (gint argc, gchar **argv)
- bus_server_init ();
- for (i = 0; i < G_N_ELEMENTS(panel_extension_disable_users); i++) {
- if (!g_strcmp0 (username, panel_extension_disable_users[i]) != 0) {
-- panel_extension = "disable";
-+ emoji_extension = "disable";
- break;
- }
- }
-@@ -286,7 +286,7 @@ main (gint argc, gchar **argv)
- }
-
- #ifdef EMOJI_DICT
-- if (g_strcmp0 (panel_extension, "default") == 0) {
-+ if (g_strcmp0 (emoji_extension, "default") == 0) {
- BusComponent *component;
- component = bus_ibus_impl_lookup_component_by_name (
- BUS_DEFAULT_IBUS, IBUS_SERVICE_PANEL_EXTENSION);
-@@ -298,9 +298,9 @@ main (gint argc, gchar **argv)
- g_printerr ("Can not execute default panel program\n");
- exit (-1);
- }
-- } else if (g_strcmp0 (panel_extension, "disable") != 0 &&
-- g_strcmp0 (panel_extension, "") != 0) {
-- if (!execute_cmdline (panel_extension))
-+ } else if (g_strcmp0 (emoji_extension, "disable") != 0 &&
-+ g_strcmp0 (emoji_extension, "") != 0) {
-+ if (!execute_cmdline (emoji_extension))
- exit (-1);
- }
- #endif
---
-2.14.3
-
-From ddc2284200971141947a37057356b4bbd84be7ce Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Thu, 14 Jun 2018 18:30:46 +0900
-Subject: [PATCH] tools: Add ibus read-config --engine-id option for engine
- schemas
-
-Fixed ibus read-config and reset-config options and also added --engine-id
-sub option for engine schemas.
-E.g.
-% ibus read-config --engine-id anthy
-% ibus read-config --engine-id com.github.libpinyin.ibus-libpinyin.libpinyin
----
- tools/main.vala | 99 +++++++++++++++++++++++++++++++++++++++++++++++++--------
- 1 file changed, 85 insertions(+), 14 deletions(-)
-
-diff --git a/tools/main.vala b/tools/main.vala
-index 8c0b64d3..6e201f30 100644
---- a/tools/main.vala
-+++ b/tools/main.vala
-@@ -3,7 +3,7 @@
- * ibus - The Input Bus
- *
- * Copyright(c) 2013 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright(c) 2015-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright(c) 2015-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
-@@ -22,20 +22,17 @@
- */
-
- private const string IBUS_SCHEMAS_GENERAL = "org.freedesktop.ibus.general";
--private const string IBUS_SCHEMAS_GENERAL_PANEL =
-- "org.freedesktop.ibus.general.panel";
-+private const string IBUS_SCHEMAS_GENERAL_HOTKEY =
-+ "org.freedesktop.ibus.general.hotkey";
- private const string IBUS_SCHEMAS_PANEL = "org.freedesktop.ibus.panel";
--
--private const string[] IBUS_SCHEMAS = {
-- IBUS_SCHEMAS_GENERAL,
-- IBUS_SCHEMAS_GENERAL_PANEL,
-- IBUS_SCHEMAS_PANEL,
--};
-+private const string IBUS_SCHEMAS_PANEL_EMOJI =
-+ "org.freedesktop.ibus.panel.emoji";
-
- bool name_only = false;
- /* system() exists as a public API. */
- bool is_system = false;
- string cache_file = null;
-+string engine_id = null;
-
- class EngineList {
- public IBus.EngineDesc[] data = {};
-@@ -292,15 +289,78 @@ int print_address(string[] argv) {
- return Posix.EXIT_SUCCESS;
- }
-
-+private int read_config_options(string[] argv) {
-+ const OptionEntry[] options = {
-+ { "engine-id", 0, 0, OptionArg.STRING, out engine_id,
-+ N_("Use engine schema paths instead of ibus core, " +
-+ "which can be comma-separated values."), "ENGINE_ID" },
-+ { null }
-+ };
-+
-+ var option = new OptionContext();
-+ option.add_main_entries(options, Config.GETTEXT_PACKAGE);
-+
-+ try {
-+ option.parse(ref argv);
-+ } catch (OptionError e) {
-+ stderr.printf("%s\n", e.message);
-+ return Posix.EXIT_FAILURE;
-+ }
-+ return Posix.EXIT_SUCCESS;
-+}
-+
-+private GLib.SList<string> get_ibus_schemas() {
-+ string[] ids = {};
-+ if (engine_id != null) {
-+ ids = engine_id.split(",");
-+ }
-+ GLib.SList<string> ibus_schemas = new GLib.SList<string>();
-+ GLib.SettingsSchemaSource schema_source =
-+ GLib.SettingsSchemaSource.get_default();
-+ string[] list_schemas = {};
-+ schema_source.list_schemas(true, out list_schemas, null);
-+ foreach (string schema in list_schemas) {
-+ if (ids.length != 0) {
-+ foreach (unowned string id in ids) {
-+ if (id == schema ||
-+ schema.has_prefix("org.freedesktop.ibus.engine." + id)) {
-+ ibus_schemas.prepend(schema);
-+ break;
-+ }
-+ }
-+ } else if (schema.has_prefix("org.freedesktop.ibus") &&
-+ !schema.has_prefix("org.freedesktop.ibus.engine")) {
-+ ibus_schemas.prepend(schema);
-+ }
-+ }
-+ if (ibus_schemas.length() == 0) {
-+ printerr("Not found schemas of \"org.freedesktop.ibus\"\n");
-+ return ibus_schemas;
-+ }
-+ ibus_schemas.sort(GLib.strcmp);
-+
-+ return ibus_schemas;
-+}
-+
- int read_config(string[] argv) {
-- var output = new GLib.StringBuilder();
-+ if (read_config_options(argv) == Posix.EXIT_FAILURE)
-+ return Posix.EXIT_FAILURE;
-+
-+ GLib.SList<string> ibus_schemas = get_ibus_schemas();
-+ if (ibus_schemas.length() == 0)
-+ return Posix.EXIT_FAILURE;
-
-- foreach (string schema in IBUS_SCHEMAS) {
-+ GLib.SettingsSchemaSource schema_source =
-+ GLib.SettingsSchemaSource.get_default();
-+ var output = new GLib.StringBuilder();
-+ foreach (string schema in ibus_schemas) {
-+ GLib.SettingsSchema settings_schema = schema_source.lookup(schema,
-+ false);
- GLib.Settings settings = new GLib.Settings(schema);
-
- output.append_printf("SCHEMA: %s\n", schema);
-
-- foreach (string key in settings.list_keys()) {
-+ foreach (string key in settings_schema.list_keys()) {
- GLib.Variant variant = settings.get_value(key);
- output.append_printf(" %s: %s\n", key, variant.print(true));
- }
-@@ -311,14 +371,25 @@ int read_config(string[] argv) {
- }
-
- int reset_config(string[] argv) {
-+ if (read_config_options(argv) == Posix.EXIT_FAILURE)
-+ return Posix.EXIT_FAILURE;
-+
-+ GLib.SList<string> ibus_schemas = get_ibus_schemas();
-+ if (ibus_schemas.length() == 0)
-+ return Posix.EXIT_FAILURE;
-+
- print("%s\n", _("Resetting…"));
-
-- foreach (string schema in IBUS_SCHEMAS) {
-+ GLib.SettingsSchemaSource schema_source =
-+ GLib.SettingsSchemaSource.get_default();
-+ foreach (string schema in ibus_schemas) {
-+ GLib.SettingsSchema settings_schema = schema_source.lookup(schema,
-+ false);
- GLib.Settings settings = new GLib.Settings(schema);
-
- print("SCHEMA: %s\n", schema);
-
-- foreach (string key in settings.list_keys()) {
-+ foreach (string key in settings_schema.list_keys()) {
- print(" %s\n", key);
- settings.reset(key);
- }
---
-2.14.3
-
-From 37aa95f1adcdde82ef473936cadc0fa3fe8a4e44 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Fri, 15 Jun 2018 19:23:27 +0900
-Subject: [PATCH] setup: Replace GtkTable /w GtkGrid
-
----
- setup/setup.ui | 113 +++++++++++++++++++++------------------------------------
- 1 file changed, 41 insertions(+), 72 deletions(-)
-
-diff --git a/setup/setup.ui b/setup/setup.ui
-index 322f5146..e64b1046 100644
---- a/setup/setup.ui
-+++ b/setup/setup.ui
-@@ -99,11 +99,9 @@
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- <child>
-- <object class="GtkTable" id="table1">
-+ <object class="GtkGrid" id="table1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
-- <property name="n_rows">5</property>
-- <property name="n_columns">2</property>
- <property name="column_spacing">12</property>
- <property name="row_spacing">6</property>
- <property name="margin_top">6</property>
-@@ -117,8 +115,8 @@
- <property name="label" translatable="yes">Next input method:</property>
- </object>
- <packing>
-- <property name="x_options">GTK_FILL</property>
-- <property name="y_options">GTK_FILL</property>
-+ <property name="left_attach">0</property>
-+ <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
-@@ -131,10 +129,8 @@
- <property name="label" translatable="yes">Previous input method:</property>
- </object>
- <packing>
-+ <property name="left_attach">0</property>
- <property name="top_attach">1</property>
-- <property name="bottom_attach">2</property>
-- <property name="x_options">GTK_FILL</property>
-- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
-@@ -143,6 +139,7 @@
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">6</property>
-+ <property name="hexpand">True</property>
- <child>
- <object class="GtkEntry" id="entry_switch_engine">
- <property name="visible">True</property>
-@@ -174,8 +171,7 @@
- </object>
- <packing>
- <property name="left_attach">1</property>
-- <property name="right_attach">2</property>
-- <property name="y_options">GTK_FILL</property>
-+ <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
-@@ -184,6 +180,7 @@
- <property name="no_show_all">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">6</property>
-+ <property name="hexpand">True</property>
- <child>
- <object class="GtkEntry" id="entry_prev_engine">
- > <property name="no_show_all">True</property>
-@@ -217,10 +214,7 @@
- </object>
- <packing>
- <property name="left_attach">1</property>
-- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
-- <property name="bottom_attach">2</property>
-- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
-@@ -232,10 +226,8 @@
- <property name="label" translatable="yes">Enable or disable:</property>
- </object>
- <packing>
-+ <property name="left_attach">0</property>
- <property name="top_attach">2</property>
-- <property name="bottom_attach">3</property>
-- <property name="x_options">GTK_FILL</property>
-- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
-@@ -246,10 +238,8 @@
- <property name="label" translatable="yes">Enable:</property>
- </object>
- <packing>
-+ <property name="left_attach">0</property>
- <property name="top_attach">3</property>
-- <property name="bottom_attach">4</property>
-- <property name="x_options">GTK_FILL</property>
-- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
-@@ -258,6 +248,7 @@
- <property name="no_show_all">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">6</property>
-+ <property name="hexpand">True</property>
- <child>
- <object class="GtkEntry" id="entry_enable_unconditional">
- <property name="visible">True</property>
-@@ -289,10 +280,7 @@
- </object>
- <packing>
- <property name="left_attach">1</property>
-- <property name="right_attach">2</property>
- <property name="top_attach">3</property>
-- <property name="bottom_attach">4</property>
-- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
-@@ -303,10 +291,8 @@
- <property name="label" translatable="yes">Disable:</property>
- </object>
- <packing>
-+ <property name="left_attach">0</property>
- <property name="top_attach">4</property>
-- <property name="bottom_attach">5</property>
-- <property name="x_options">GTK_FILL</property>
-- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
-@@ -315,6 +301,7 @@
- <property name="no_show_all">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">6</property>
-+ <property name="hexpand">True</property>
- <child>
- <object class="GtkEntry" id="entry_disable_unconditional">
- <property name="visible">True</property>
-@@ -346,10 +333,7 @@
- </object>
- <packing>
- <property name="left_attach">1</property>
-- <property name="right_attach">2</property>
- <property name="top_attach">4</property>
-- <property name="bottom_attach">5</property>
-- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- </object>
-@@ -376,11 +360,9 @@
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- <child>
-- <object class="GtkTable" id="table2">
-+ <object class="GtkGrid" id="table2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
-- <property name="n_rows">7</property>
-- <property name="n_columns">2</property>
- <property name="column_spacing">12</property>
- <property name="row_spacing">6</property>
- <property name="margin_top">6</property>
-@@ -393,10 +375,11 @@
- <property name="halign">start</property>
- <property name="label" translatable="yes">Candidates orientation:</property>
- <property name="justify">right</property>
-+ <property name="hexpand">True</property>
- </object>
- <packing>
-- <property name="x_options">GTK_FILL</property>
-- <property name="y_options">GTK_FILL</property>
-+ <property name="left_attach">0</property>
-+ <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
-@@ -404,6 +387,7 @@
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="model">model_candidates_orientation</property>
-+ <property name="hexpand">True</property>
- <child>
- <object class="GtkCellRendererText" id="renderer1"/>
- <attributes>
-@@ -413,8 +397,7 @@
- </object>
- <packing>
- <property name="left_attach">1</property>
-- <property name="right_attach">2</property>
-- <property name="y_options">GTK_FILL</property>
-+ <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
-@@ -425,12 +408,11 @@
- <property name="halign">start</property>
- <property name="label" translatable="yes">Show property panel:</property>
- <property name="justify">right</property>
-+ <property name="hexpand">True</property>
- </object>
- <packing>
-+ <property name="left_attach">0</property>
- <property name="top_attach">1</property>
-- <property name="bottom_attach">2</property>
-- <property name="x_options">GTK_FILL</property>
-- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
-@@ -440,12 +422,11 @@
- <property name="halign">start</property>
- <property name="label" translatable="yes">Language panel position:</property>
- <property name="justify">right</property>
-+ <property name="hexpand">True</property>
- </object>
- <packing>
-+ <property name="left_attach">0</property>
- <property name="top_attach">2</property>
-- <property name="bottom_attach">3</property>
-- <property name="x_options">GTK_FILL</property>
-- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
-@@ -453,6 +434,7 @@
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="model">model_panel_show_mode</property>
-+ <property name="hexpand">True</property>
- <child>
- <object class="GtkCellRendererText" id="renderer2"/>
- <attributes>
-@@ -462,10 +444,7 @@
- </object>
- <packing>
- <property name="left_attach">1</property>
-- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
-- <property name="bottom_attach">2</property>
-- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
-@@ -473,6 +452,7 @@
- <property name="can_focus">False</property>
- <property name="no_show_all">True</property>
- <property name="model">model_panel_position</property>
-+ <property name="hexpand">True</property>
- <child>
- <object class="GtkCellRendererText" id="renderer3"/>
- <attributes>
-@@ -482,10 +462,7 @@
- </object>
- <packing>
- <property name="left_attach">1</property>
-- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
-- <property name="bottom_attach">3</property>
-- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
-@@ -499,13 +476,12 @@
- <property name="use_action_appearance">False</property>
- <property name="halign">start</property>
- <property name="draw_indicator">True</property>
-+ <property name="hexpand">True</property>
- </object>
- <packing>
-- <property name="right_attach">2</property>
-+ <property name="left_attach">0</property>
- <property name="top_attach">3</property>
-- <property name="bottom_attach">4</property>
-- <property name="x_options">GTK_FILL</property>
-- <property name="y_options">GTK_FILL</property>
-+ <property name="width">2</property>
- </packing>
- </child>
- <child>
-@@ -519,13 +495,12 @@
- <property name="use_action_appearance">False</property>
- <property name="halign">start</property>
- <property name="draw_indicator">True</property>
-+ <property name="hexpand">True</property>
- </object>
- <packing>
-- <property name="right_attach">2</property>
-+ <property name="left_attach">0</property>
- <property name="top_attach">4</property>
-- <property name="bottom_attach">5</property>
-- <property name="x_options">GTK_FILL</property>
-- <property name="y_options">GTK_FILL</property>
-+ <property name="width">2</property>
- </packing>
- </child>
- <child>
-@@ -539,13 +514,12 @@
- <property name="use_action_appearance">False</property>
- <property name="halign">start</property>
- <property name="draw_indicator">True</property>
-+ <property name="hexpand">True</property>
- </object>
- <packing>
-- <property name="right_attach">2</property>
-+ <property name="left_attach">0</property>
- <property name="top_attach">5</property>
-- <property name="bottom_attach">6</property>
-- <property name="x_options">GTK_FILL</property>
-- <property name="y_options">GTK_FILL</property>
-+ <property name="width">2</property>
- </packing>
- </child>
- <child>
-@@ -559,12 +533,11 @@
- <property name="use_underline">True</property>
- <property name="halign">start</property>
- <property name="draw_indicator">True</property>
-+ <property name="hexpand">True</property>
- </object>
- <packing>
-+ <property name="left_attach">0</property>
- <property name="top_attach">6</property>
-- <property name="bottom_attach">7</property>
-- <property name="x_options">GTK_FILL</property>
-- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
-@@ -573,13 +546,11 @@
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_action_appearance">False</property>
-+ <property name="hexpand">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
-- <property name="right_attach">2</property>
- <property name="top_attach">6</property>
-- <property name="bottom_attach">7</property>
-- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- </object>
-@@ -888,11 +859,9 @@
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- <child>
-- <object class="GtkTable" id="table_emoji1">
-+ <object class="GtkGrid" id="table_emoji1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
-- <property name="n_rows">5</property>
-- <property name="n_columns">2</property>
- <property name="column_spacing">12</property>
- <property name="row_spacing">6</property>
- <property name="margin_top">6</property>
-@@ -906,8 +875,8 @@
- <property name="label" translatable="yes">Emoji choice:</property>
- </object>
- <packing>
-- <property name="x_options">GTK_FILL</property>
-- <property name="y_options">GTK_FILL</property>
-+ <property name="left_attach">0</property>
-+ <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
-@@ -916,6 +885,7 @@
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">6</property>
-+ <property name="hexpand">true</property>
- <child>
- <object class="GtkEntry" id="entry_emoji_dialog">
- <property name="visible">True</property>
-@@ -947,8 +917,7 @@
- </object>
- <packing>
- <property name="left_attach">1</property>
-- <property name="right_attach">2</property>
-- <property name="y_options">GTK_FILL</property>
-+ <property name="top_attach">0</property>
- </packing>
- </child>
- </object>
---
-2.14.3
-
-From 5ee3f48049ecf128391da6448ae7e74786bd171b Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Mon, 18 Jun 2018 12:46:11 +0900
-Subject: [PATCH] Move input focus on Emojier to engines' preedit
-
----
- bindings/vala/IBus-1.0-custom.vala | 7 +
- bindings/vala/Makefile.am | 3 +-
- bindings/vala/gdk-wayland.vapi | 7 +
- bus/engineproxy.c | 53 +-
- bus/engineproxy.h | 25 +-
- bus/ibusimpl.c | 247 +++++++--
- bus/inputcontext.c | 399 +++++++++++----
- bus/inputcontext.h | 110 +++-
- bus/panelproxy.c | 210 +++++++-
- bus/panelproxy.h | 23 +-
- data/ibus.schemas.in | 12 +
- setup/main.py | 10 +-
- setup/setup.ui | 58 ++-
- src/ibusengine.c | 305 ++++++++----
- src/ibuspanelservice.c | 318 +++++++++++-
- src/ibuspanelservice.h | 117 ++++-
- src/ibusshare.h | 17 +-
- src/ibusxevent.c | 375 +++++++++++++-
- src/ibusxevent.h | 143 +++++-
- ui/gtk3/Makefile.am | 3 +
- ui/gtk3/emojier.vala | 991 +++++++++++++++++++++++++++----------
- ui/gtk3/emojierapp.vala | 74 ++-
- ui/gtk3/extension.vala | 6 +-
- ui/gtk3/panel.vala | 23 +-
- ui/gtk3/panelbinding.vala | 859 +++++++++++++++++++++++++++++---
- 25 files changed, 3695 insertions(+), 700 deletions(-)
- create mode 100644 bindings/vala/gdk-wayland.vapi
-
-diff --git a/bindings/vala/IBus-1.0-custom.vala b/bindings/vala/IBus-1.0-custom.vala
-index cf1fc3fa..7d34a8bd 100644
---- a/bindings/vala/IBus-1.0-custom.vala
-+++ b/bindings/vala/IBus-1.0-custom.vala
-@@ -6,8 +6,15 @@ namespace IBus {
- [CCode (cname = "ibus_text_new_from_static_string", has_construct_function = false)]
- public Text.from_static_string (string str);
- }
-+ public class ExtensionEvent : IBus.Serializable {
-+ [CCode (cname = "ibus_extension_event_new", has_construct_function = true)]
-+ public ExtensionEvent (string first_property_name, ...);
-+ }
- public class XEvent : IBus.Serializable {
- [CCode (cname = "ibus_x_event_new", has_construct_function = true)]
- public XEvent (string first_property_name, ...);
- }
-+ public class PanelService : IBus.Service {
-+ public void panel_extension_register_keys(string first_property_name, ...);
-+ }
- }
-diff --git a/bindings/vala/Makefile.am b/bindings/vala/Makefile.am
-index fc8e2f01..e4ecab97 100644
---- a/bindings/vala/Makefile.am
-+++ b/bindings/vala/Makefile.am
-@@ -3,7 +3,7 @@
- # ibus - The Input Bus
- #
- # Copyright (c) 2007-2016 Peng Huang <shawn.p.huang@gmail.com>
--# Copyright (c) 2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+# Copyright (c) 2017-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
- # Copyright (c) 2007-2017 Red Hat, Inc.
- #
- # This library is free software; you can redistribute it and/or
-@@ -86,6 +86,7 @@ EXTRA_DIST = \
- ibus-1.0.deps \
- ibus-emoji-dialog-1.0.deps \
- config.vapi \
-+ gdk-wayland.vapi \
- xi.vapi \
- $(NULL)
-
-diff --git a/bindings/vala/gdk-wayland.vapi b/bindings/vala/gdk-wayland.vapi
-new file mode 100644
-index 00000000..c65f2be4
---- /dev/null
-+++ b/bindings/vala/gdk-wayland.vapi
-@@ -0,0 +1,7 @@
-+[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "gdk/gdkwayland.h")]
-+namespace GdkWayland
-+{
-+ [CCode (type_id = "gdk_wayland_display_get_type ()")]
-+ public class Display : Gdk.Display {
-+ }
-+}
-diff --git a/bus/engineproxy.c b/bus/engineproxy.c
-index 175aec56..2d98995c 100644
---- a/bus/engineproxy.c
-+++ b/bus/engineproxy.c
-@@ -377,10 +377,10 @@ bus_engine_proxy_class_init (BusEngineProxyClass *class)
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
-- bus_marshal_VOID__VARIANT,
-+ bus_marshal_VOID__OBJECT,
- G_TYPE_NONE,
- 1,
-- G_TYPE_VARIANT);
-+ IBUS_TYPE_EXTENSION_EVENT);
-
- text_empty = ibus_text_new_from_static_string ("");
- g_object_ref_sink (text_empty);
-@@ -644,7 +644,16 @@ bus_engine_proxy_g_signal (GDBusProxy *proxy,
- }
-
- if (g_strcmp0 (signal_name, "PanelExtension") == 0) {
-- g_signal_emit (engine, engine_signals[PANEL_EXTENSION], 0, parameters);
-+ GVariant *arg0 = NULL;
-+ g_variant_get (parameters, "(v)", &arg0);
-+ g_return_if_fail (arg0 != NULL);
-+
-+ IBusExtensionEvent *event = IBUS_EXTENSION_EVENT (
-+ ibus_serializable_deserialize (arg0));
-+ g_variant_unref (arg0);
-+ g_return_if_fail (event != NULL);
-+ g_signal_emit (engine, engine_signals[PANEL_EXTENSION], 0, event);
-+ _g_object_unref_if_floating (event);
- return;
- }
-
-@@ -1323,6 +1332,44 @@ bus_engine_proxy_is_enabled (BusEngineProxy *engine)
- return engine->enabled;
- }
-
-+void
-+bus_engine_proxy_panel_extension_received (BusEngineProxy *engine,
-+ IBusExtensionEvent *event)
-+{
-+ GVariant *variant;
-+ g_assert (BUS_IS_ENGINE_PROXY (engine));
-+ g_assert (IBUS_IS_EXTENSION_EVENT (event));
-+
-+ variant = ibus_serializable_serialize_object (
-+ IBUS_SERIALIZABLE (event));
-+ g_return_if_fail (variant != NULL);
-+ g_dbus_proxy_call ((GDBusProxy *)engine,
-+ "PanelExtensionReceived",
-+ g_variant_new ("(v)", variant),
-+ G_DBUS_CALL_FLAGS_NONE,
-+ -1,
-+ NULL,
-+ NULL,
-+ NULL);
-+}
-+
-+void
-+bus_engine_proxy_panel_extension_register_keys (BusEngineProxy *engine,
-+ GVariant *parameters)
-+{
-+ g_assert (BUS_IS_ENGINE_PROXY (engine));
-+ g_assert (parameters);
-+
-+ g_dbus_proxy_call ((GDBusProxy *)engine,
-+ "PanelExtensionRegisterKeys",
-+ g_variant_new ("(v)", g_variant_ref (parameters)),
-+ G_DBUS_CALL_FLAGS_NONE,
-+ -1,
-+ NULL,
-+ NULL,
-+ NULL);
-+}
-+
- static gboolean
- initable_init (GInitable *initable,
- GCancellable *cancellable,
-diff --git a/bus/engineproxy.h b/bus/engineproxy.h
-index 528e61b7..a3006b47 100644
---- a/bus/engineproxy.h
-+++ b/bus/engineproxy.h
-@@ -2,7 +2,8 @@
- /* vim:set et sts=4: */
- /* ibus - The Input Bus
- * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2008-2013 Red Hat, Inc.
-+ * Copyright (C) 2018 Takao Fujiwara <takao.fujiwara@gmail.com>
-+ * Copyright (C) 2008-2018 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
-@@ -325,5 +326,27 @@ void bus_engine_proxy_set_content_type
- IBusPropList *bus_engine_proxy_get_properties
- (BusEngineProxy *engine);
-
-+/**
-+ * bus_engine_proxy_panel_extension_received:
-+ * @engine: A #BusEngineProxy.
-+ * @event: An #IBusExtensionEvent.
-+ *
-+ * Send an #IBusExtensionEvent to the engine.
-+ */
-+void bus_engine_proxy_panel_extension_received
-+ (BusEngineProxy *engine,
-+ IBusExtensionEvent *event);
-+
-+/**
-+ * bus_engine_proxy_panel_extension_register_keys:
-+ * @engine: A #BusEngineProxy.
-+ * @parameters: A #GVariant array which includes the name and shortcut keys.
-+ *
-+ * Send shortcut keys to the engine to enable the extension.
-+ */
-+void bus_engine_proxy_panel_extension_register_keys
-+ (BusEngineProxy *engine,
-+ GVariant *parameters);
-+
- G_END_DECLS
- #endif
-diff --git a/bus/ibusimpl.c b/bus/ibusimpl.c
-index a4ce3d9d..ec1caea8 100644
---- a/bus/ibusimpl.c
-+++ b/bus/ibusimpl.c
-@@ -74,7 +74,8 @@ struct _BusIBusImpl {
-
- BusInputContext *focused_context;
- BusPanelProxy *panel;
-- BusPanelProxy *extension;
-+ BusPanelProxy *emoji_extension;
-+ gboolean enable_emoji_extension;
-
- /* a default keymap of ibus-daemon (usually "us") which is used only
- * when use_sys_layout is FALSE. */
-@@ -83,6 +84,7 @@ struct _BusIBusImpl {
- gboolean use_global_engine;
- gchar *global_engine_name;
- gchar *global_previous_engine_name;
-+ GVariant *extension_register_keys;
- };
-
- struct _BusIBusImplClass {
-@@ -294,40 +296,158 @@ _panel_destroy_cb (BusPanelProxy *panel,
-
- if (ibus->panel == panel)
- ibus->panel = NULL;
-- else if (ibus->extension == panel)
-- ibus->extension = NULL;
-+ else if (ibus->emoji_extension == panel)
-+ ibus->emoji_extension = NULL;
- else
- g_return_if_reached ();
- g_object_unref (panel);
- }
-
- static void
--bus_ibus_impl_panel_extension_received (BusIBusImpl *ibus,
-- GVariant *parameters)
-+bus_ibus_impl_set_panel_extension_mode (BusIBusImpl *ibus,
-+ IBusExtensionEvent *event)
- {
-- if (!ibus->extension) {
-+ gboolean is_extension = FALSE;
-+ g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
-+ g_return_if_fail (IBUS_IS_EXTENSION_EVENT (event));
-+
-+ if (!ibus->emoji_extension) {
- g_warning ("Panel extension is not running.");
- return;
- }
-
-- g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
-- g_return_if_fail (BUS_IS_PANEL_PROXY (ibus->extension));
-+ g_return_if_fail (BUS_IS_PANEL_PROXY (ibus->emoji_extension));
-+
-+ ibus->enable_emoji_extension = ibus_extension_event_is_enabled (event);
-+ is_extension = ibus_extension_event_is_extension (event);
-+ if (ibus->focused_context != NULL) {
-+ if (ibus->enable_emoji_extension) {
-+ bus_input_context_set_emoji_extension (ibus->focused_context,
-+ ibus->emoji_extension);
-+ } else {
-+ bus_input_context_set_emoji_extension (ibus->focused_context, NULL);
-+ }
-+ if (is_extension)
-+ bus_input_context_panel_extension_received (ibus->focused_context,
-+ event);
-+ }
-+ if (is_extension)
-+ return;
-
- /* Use the DBus method because it seems any DBus signal,
- * g_dbus_message_new_signal(), cannot be reached to the server. */
-- g_dbus_proxy_call (G_DBUS_PROXY (ibus->extension),
-- "PanelExtensionReceived",
-- parameters,
-- G_DBUS_CALL_FLAGS_NONE,
-- -1, NULL, NULL, NULL);
-+ bus_panel_proxy_panel_extension_received (ibus->emoji_extension,
-+ event);
-+}
-+
-+static void
-+bus_ibus_impl_set_panel_extension_keys (BusIBusImpl *ibus,
-+ GVariant *parameters)
-+{
-+ BusEngineProxy *engine = NULL;
-+
-+ g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
-+ g_return_if_fail (parameters);
-+
-+ if (!ibus->emoji_extension) {
-+ g_warning ("Panel extension is not running.");
-+ return;
-+ }
-+
-+ if (ibus->extension_register_keys)
-+ g_variant_unref (ibus->extension_register_keys);
-+ ibus->extension_register_keys = g_variant_ref_sink (parameters);
-+ if (ibus->focused_context != NULL) {
-+ engine = bus_input_context_get_engine (ibus->focused_context);
-+ }
-+ if (!engine)
-+ return;
-+ bus_engine_proxy_panel_extension_register_keys (engine, parameters);
- }
-
- static void
--_panel_panel_extension_cb (BusPanelProxy *panel,
-- GVariant *parameters,
-- BusIBusImpl *ibus)
-+_panel_panel_extension_cb (BusPanelProxy *panel,
-+ IBusExtensionEvent *event,
-+ BusIBusImpl *ibus)
- {
-- bus_ibus_impl_panel_extension_received (ibus, parameters);
-+ bus_ibus_impl_set_panel_extension_mode (ibus, event);
-+}
-+
-+static void
-+_panel_panel_extension_register_keys_cb (BusInputContext *context,
-+ GVariant *parameters,
-+ BusIBusImpl *ibus)
-+{
-+ bus_ibus_impl_set_panel_extension_keys (ibus, parameters);
-+}
-+
-+static void
-+_panel_update_preedit_text_received_cb (BusPanelProxy *panel,
-+ IBusText *text,
-+ guint cursor_pos,
-+ gboolean visible,
-+ BusIBusImpl *ibus)
-+{
-+ g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
-+
-+ if (!ibus->focused_context)
-+ return;
-+ bus_input_context_update_preedit_text (ibus->focused_context,
-+ text, cursor_pos, visible, IBUS_ENGINE_PREEDIT_CLEAR, FALSE);
-+}
-+
-+static void
-+_panel_update_lookup_table_received_cb (BusPanelProxy *panel,
-+ IBusLookupTable *table,
-+ gboolean visible,
-+ BusIBusImpl *ibus)
-+{
-+ g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
-+ g_return_if_fail (IBUS_IS_LOOKUP_TABLE (table));
-+
-+ if (!ibus->focused_context)
-+ return;
-+ /* Call bus_input_context_update_lookup_table() instead of
-+ * bus_panel_proxy_update_lookup_table() for panel extensions because
-+ * bus_input_context_page_up() can call bus_panel_proxy_page_up_received().
-+ */
-+ bus_input_context_update_lookup_table (
-+ ibus->focused_context, table, visible, TRUE);
-+}
-+
-+static void
-+_panel_update_auxiliary_text_received_cb (BusPanelProxy *panel,
-+ IBusText *text,
-+ gboolean visible,
-+ BusIBusImpl *ibus)
-+{
-+ g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
-+ g_return_if_fail (IBUS_IS_TEXT (text));
-+
-+ if (!ibus->panel)
-+ return;
-+ bus_panel_proxy_update_auxiliary_text (
-+ ibus->panel, text, visible);
-+}
-+
-+static void
-+_panel_show_lookup_table_received_cb (BusPanelProxy *panel,
-+ BusIBusImpl *ibus)
-+{
-+ g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
-+
-+ if (ibus->panel)
-+ bus_panel_proxy_show_lookup_table (ibus->panel);
-+}
-+
-+static void
-+_panel_hide_lookup_table_received_cb (BusPanelProxy *panel,
-+ BusIBusImpl *ibus)
-+{
-+ g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
-+
-+ if (ibus->panel)
-+ bus_panel_proxy_hide_lookup_table (ibus->panel);
- }
-
- static void
-@@ -361,8 +481,8 @@ _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
-
- if (!g_strcmp0 (name, IBUS_SERVICE_PANEL))
- panel_type = PANEL_TYPE_PANEL;
-- else if (!g_strcmp0 (name, IBUS_SERVICE_PANEL_EXTENSION))
-- panel_type = PANEL_TYPE_EXTENSION;
-+ else if (!g_strcmp0 (name, IBUS_SERVICE_PANEL_EXTENSION_EMOJI))
-+ panel_type = PANEL_TYPE_EXTENSION_EMOJI;
-
- if (panel_type != PANEL_TYPE_NONE) {
- if (g_strcmp0 (new_name, "") != 0) {
-@@ -370,7 +490,7 @@ _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
- BusConnection *connection;
- BusInputContext *context = NULL;
- BusPanelProxy **panel = (panel_type == PANEL_TYPE_PANEL) ?
-- &ibus->panel : &ibus->extension;
-+ &ibus->panel : &ibus->emoji_extension;
-
- if (*panel != NULL) {
- ibus_proxy_destroy ((IBusProxy *)(*panel));
-@@ -383,6 +503,8 @@ _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
- g_return_if_fail (connection != NULL);
-
- *panel = bus_panel_proxy_new (connection, panel_type);
-+ if (panel_type == PANEL_TYPE_EXTENSION_EMOJI)
-+ ibus->enable_emoji_extension = FALSE;
-
- g_signal_connect (*panel,
- "destroy",
-@@ -392,6 +514,26 @@ _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
- "panel-extension",
- G_CALLBACK (_panel_panel_extension_cb),
- ibus);
-+ g_signal_connect (*panel,
-+ "panel-extension-register-keys",
-+ G_CALLBACK (
-+ _panel_panel_extension_register_keys_cb),
-+ ibus);
-+ g_signal_connect (
-+ *panel,
-+ "update-preedit-text-received",
-+ G_CALLBACK (_panel_update_preedit_text_received_cb),
-+ ibus);
-+ g_signal_connect (
-+ *panel,
-+ "update-lookup-table-received",
-+ G_CALLBACK (_panel_update_lookup_table_received_cb),
-+ ibus);
-+ g_signal_connect (
-+ *panel,
-+ "update-auxiliary-text-received",
-+ G_CALLBACK (_panel_update_auxiliary_text_received_cb),
-+ ibus);
-
- if (ibus->focused_context != NULL) {
- context = ibus->focused_context;
-@@ -450,7 +592,7 @@ bus_ibus_impl_init (BusIBusImpl *ibus)
- ibus->contexts = NULL;
- ibus->focused_context = NULL;
- ibus->panel = NULL;
-- ibus->extension = NULL;
-+ ibus->emoji_extension = NULL;
-
- ibus->keymap = ibus_keymap_get ("us");
-
-@@ -650,11 +792,11 @@ bus_ibus_impl_set_context_engine_from_desc (BusIBusImpl *ibus,
- }
-
- static void
--_context_panel_extension_cb (BusInputContext *context,
-- GVariant *parameters,
-- BusIBusImpl *ibus)
-+_context_panel_extension_cb (BusInputContext *context,
-+ IBusExtensionEvent *event,
-+ BusIBusImpl *ibus)
- {
-- bus_ibus_impl_panel_extension_received (ibus, parameters);
-+ bus_ibus_impl_set_panel_extension_mode (ibus, event);
- }
-
- const static struct {
-@@ -694,13 +836,18 @@ bus_ibus_impl_set_focused_context (BusIBusImpl *ibus,
- if (engine) {
- g_object_ref (engine);
- bus_input_context_set_engine (ibus->focused_context, NULL);
-+ bus_input_context_set_emoji_extension (ibus->focused_context,
-+ NULL);
- }
- }
-
- if (ibus->panel != NULL)
- bus_panel_proxy_focus_out (ibus->panel, ibus->focused_context);
-- if (ibus->extension != NULL)
-- bus_panel_proxy_focus_out (ibus->extension, ibus->focused_context);
-+ if (ibus->emoji_extension != NULL) {
-+ bus_panel_proxy_focus_out (ibus->emoji_extension,
-+ ibus->focused_context);
-+ }
-+ bus_input_context_set_emoji_extension (ibus->focused_context, NULL);
-
- bus_input_context_get_content_type (ibus->focused_context,
- &purpose, &hints);
-@@ -724,6 +871,12 @@ bus_ibus_impl_set_focused_context (BusIBusImpl *ibus,
- if (engine != NULL) {
- bus_input_context_set_engine (context, engine);
- bus_input_context_enable (context);
-+ if (ibus->enable_emoji_extension) {
-+ bus_input_context_set_emoji_extension (context,
-+ ibus->emoji_extension);
-+ } else {
-+ bus_input_context_set_emoji_extension (context, NULL);
-+ }
- }
- for (i = 0; i < G_N_ELEMENTS(context_signals); i++) {
- g_signal_connect (ibus->focused_context,
-@@ -734,8 +887,8 @@ bus_ibus_impl_set_focused_context (BusIBusImpl *ibus,
-
- if (ibus->panel != NULL)
- bus_panel_proxy_focus_in (ibus->panel, context);
-- if (ibus->extension != NULL)
-- bus_panel_proxy_focus_in (ibus->extension, context);
-+ if (ibus->emoji_extension != NULL)
-+ bus_panel_proxy_focus_in (ibus->emoji_extension, context);
- }
-
- if (engine != NULL)
-@@ -751,6 +904,12 @@ bus_ibus_impl_set_global_engine (BusIBusImpl *ibus,
-
- if (ibus->focused_context) {
- bus_input_context_set_engine (ibus->focused_context, engine);
-+ if (ibus->enable_emoji_extension) {
-+ bus_input_context_set_emoji_extension (ibus->focused_context,
-+ ibus->emoji_extension);
-+ } else {
-+ bus_input_context_set_emoji_extension (ibus->focused_context, NULL);
-+ }
- } else if (ibus->fake_context) {
- bus_input_context_set_engine (ibus->fake_context, engine);
- }
-@@ -927,9 +1086,9 @@ _context_destroy_cb (BusInputContext *context,
- bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) {
- bus_panel_proxy_destroy_context (ibus->panel, context);
- }
-- if (ibus->extension &&
-+ if (ibus->emoji_extension &&
- bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) {
-- bus_panel_proxy_destroy_context (ibus->extension, context);
-+ bus_panel_proxy_destroy_context (ibus->emoji_extension, context);
- }
-
- ibus->contexts = g_list_remove (ibus->contexts, context);
-@@ -1489,6 +1648,7 @@ _ibus_set_global_engine_ready_cb (BusInputContext *context,
- else {
- g_dbus_method_invocation_return_value (data->invocation, NULL);
-
-+ BusEngineProxy *engine = bus_input_context_get_engine (context);
- if (ibus->use_global_engine && (context != ibus->focused_context)) {
- /* context and ibus->focused_context don't match. This means that
- * the focus is moved before _ibus_set_global_engine() asynchronous
-@@ -1496,14 +1656,28 @@ _ibus_set_global_engine_ready_cb (BusInputContext *context,
- * being focused hasn't been updated. Update the engine here so that
- * subsequent _ibus_get_global_engine() call could return a
- * consistent engine name. */
-- BusEngineProxy *engine = bus_input_context_get_engine (context);
- if (engine && ibus->focused_context != NULL) {
- g_object_ref (engine);
- bus_input_context_set_engine (context, NULL);
-+ bus_input_context_set_emoji_extension (context, NULL);
- bus_input_context_set_engine (ibus->focused_context, engine);
-+ if (ibus->enable_emoji_extension) {
-+ bus_input_context_set_emoji_extension (
-+ ibus->focused_context,
-+ ibus->emoji_extension);
-+ } else {
-+ bus_input_context_set_emoji_extension (
-+ ibus->focused_context,
-+ NULL);
-+ }
- g_object_unref (engine);
- }
- }
-+ if (engine && ibus->extension_register_keys) {
-+ bus_engine_proxy_panel_extension_register_keys (
-+ engine,
-+ ibus->extension_register_keys);
-+ }
- }
-
- g_object_unref (ibus);
-@@ -2013,11 +2187,12 @@ bus_ibus_impl_registry_destroy (BusIBusImpl *ibus)
- g_list_free_full (ibus->components, g_object_unref);
- ibus->components = NULL;
-
-- g_hash_table_destroy (ibus->engine_table);
-- ibus->engine_table = NULL;
-+ g_clear_pointer (&ibus->engine_table, g_hash_table_destroy);
-
-- ibus_object_destroy (IBUS_OBJECT (ibus->registry));
-- ibus->registry = NULL;
-+ g_clear_pointer (&ibus->registry, ibus_object_destroy);
-+
-+ if (ibus->extension_register_keys)
-+ g_clear_pointer (&ibus->extension_register_keys, g_variant_unref);
- }
-
- static gint
-diff --git a/bus/inputcontext.c b/bus/inputcontext.c
-index dfb98c36..bf9eafcf 100644
---- a/bus/inputcontext.c
-+++ b/bus/inputcontext.c
-@@ -94,6 +94,9 @@ struct _BusInputContext {
- /* content-type (primary purpose and hints) */
- guint purpose;
- guint hints;
-+
-+ BusPanelProxy *emoji_extension;
-+ gboolean is_extension_lookup_table;
- };
-
- struct _BusInputContextClass {
-@@ -162,16 +165,12 @@ static gboolean bus_input_context_service_set_property
- GError **error);
- static void bus_input_context_unset_engine
- (BusInputContext *context);
--static void bus_input_context_update_preedit_text
-- (BusInputContext *context,
-- IBusText *text,
-- guint cursor_pos,
-- gboolean visible,
-- guint mode);
- static void bus_input_context_show_preedit_text
-- (BusInputContext *context);
-+ (BusInputContext *context,
-+ gboolean is_extension);
- static void bus_input_context_hide_preedit_text
-- (BusInputContext *context);
-+ (BusInputContext *context,
-+ gboolean is_extension);
- static void bus_input_context_update_auxiliary_text
- (BusInputContext *context,
- IBusText *text,
-@@ -180,10 +179,6 @@ static void bus_input_context_show_auxiliary_text
- (BusInputContext *context);
- static void bus_input_context_hide_auxiliary_text
- (BusInputContext *context);
--static void bus_input_context_update_lookup_table
-- (BusInputContext *context,
-- IBusLookupTable *table,
-- gboolean visible);
- static void bus_input_context_show_lookup_table
- (BusInputContext *context);
- static void bus_input_context_hide_lookup_table
-@@ -605,10 +600,10 @@ bus_input_context_class_init (BusInputContextClass *class)
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
-- bus_marshal_VOID__VARIANT,
-+ bus_marshal_VOID__OBJECT,
- G_TYPE_NONE,
- 1,
-- G_TYPE_VARIANT);
-+ IBUS_TYPE_EXTENSION_EVENT);
-
- text_empty = ibus_text_new_from_string ("");
- g_object_ref_sink (text_empty);
-@@ -760,28 +755,85 @@ bus_input_context_property_changed (BusInputContext *context,
- error);
- }
-
-+
-+/**
-+ * _panel_process_key_event_cb:
-+ *
-+ * A GAsyncReadyCallback function to be called when
-+ * bus_panel_proxy_process_key_event() is finished.
-+ */
-+static void
-+_panel_process_key_event_cb (GObject *source,
-+ GAsyncResult *res,
-+ GDBusMethodInvocation *invocation)
-+{
-+ GError *error = NULL;
-+ GVariant *value = g_dbus_proxy_call_finish ((GDBusProxy *)source,
-+ res,
-+ &error);
-+ if (value != NULL) {
-+ g_dbus_method_invocation_return_value (invocation, value);
-+ g_variant_unref (value);
-+ }
-+ else {
-+ g_dbus_method_invocation_return_gerror (invocation, error);
-+ g_error_free (error);
-+ }
-+}
-+
-+typedef struct _ProcessKeyEventData ProcessKeyEventData;
-+struct _ProcessKeyEventData {
-+ GDBusMethodInvocation *invocation;
-+ BusInputContext *context;
-+ guint keyval;
-+ guint keycode;
-+ guint modifiers;
-+};
-+
- /**
- * _ic_process_key_event_reply_cb:
- *
-- * A GAsyncReadyCallback function to be called when bus_engine_proxy_process_key_event() is finished.
-+ * A GAsyncReadyCallback function to be called when
-+ * bus_engine_proxy_process_key_event() is finished.
- */
- static void
- _ic_process_key_event_reply_cb (GObject *source,
- GAsyncResult *res,
-- GDBusMethodInvocation *invocation)
-+ ProcessKeyEventData *data)
- {
-+ GDBusMethodInvocation *invocation = data->invocation;
-+ BusInputContext *context = data->context;
-+ guint keyval = data->keyval;
-+ guint keycode = data->keycode;
-+ guint modifiers = data->modifiers;
- GError *error = NULL;
- GVariant *value = g_dbus_proxy_call_finish ((GDBusProxy *)source,
- res,
- &error);
-+
- if (value != NULL) {
-- g_dbus_method_invocation_return_value (invocation, value);
-+ gboolean retval = FALSE;
-+ g_variant_get (value, "(b)", &retval);
-+ if (context->emoji_extension && !retval) {
-+ bus_panel_proxy_process_key_event (context->emoji_extension,
-+ keyval,
-+ keycode,
-+ modifiers,
-+ (GAsyncReadyCallback)
-+ _panel_process_key_event_cb,
-+ invocation);
-+ } else {
-+ g_dbus_method_invocation_return_value (invocation, value);
-+ }
- g_variant_unref (value);
- }
- else {
- g_dbus_method_invocation_return_gerror (invocation, error);
- g_error_free (error);
- }
-+
-+ g_object_unref (context);
-+ g_slice_free (ProcessKeyEventData, data);
- }
-
- /**
-@@ -840,12 +892,19 @@ _ic_process_key_event (BusInputContext *context,
-
- /* ignore key events, if it is a fake input context */
- if (context->has_focus && context->engine && context->fake == FALSE) {
-+ ProcessKeyEventData *data = g_slice_new0 (ProcessKeyEventData);
-+ data->invocation = invocation;
-+ data->context = g_object_ref (context);
-+ data->keyval = keyval;
-+ data->keycode = keycode;
-+ data->modifiers = modifiers;
- bus_engine_proxy_process_key_event (context->engine,
- keyval,
- keycode,
- modifiers,
-- (GAsyncReadyCallback) _ic_process_key_event_reply_cb,
-- invocation);
-+ (GAsyncReadyCallback)
-+ _ic_process_key_event_reply_cb,
-+ data);
- }
- else {
- g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", FALSE));
-@@ -880,6 +939,13 @@ _ic_set_cursor_location (BusInputContext *context,
- context->y,
- context->w,
- context->h);
-+ if (context->emoji_extension) {
-+ bus_panel_proxy_set_cursor_location (context->emoji_extension,
-+ context->x,
-+ context->y,
-+ context->w,
-+ context->h);
-+ }
- }
- }
-
-@@ -912,6 +978,14 @@ _ic_set_cursor_location_relative (BusInputContext *context,
- y,
- w,
- h);
-+ if (context->emoji_extension) {
-+ bus_panel_proxy_set_cursor_location_relative (
-+ context->emoji_extension,
-+ x,
-+ y,
-+ w,
-+ h);
-+ }
- }
- }
-
-@@ -1394,7 +1468,7 @@ bus_input_context_clear_preedit_text (BusInputContext *context)
-
- /* always clear preedit text */
- bus_input_context_update_preedit_text (context,
-- text_empty, 0, FALSE, IBUS_ENGINE_PREEDIT_CLEAR);
-+ text_empty, 0, FALSE, IBUS_ENGINE_PREEDIT_CLEAR, TRUE);
- }
-
- void
-@@ -1407,7 +1481,10 @@ bus_input_context_focus_out (BusInputContext *context)
-
- bus_input_context_clear_preedit_text (context);
- bus_input_context_update_auxiliary_text (context, text_empty, FALSE);
-- bus_input_context_update_lookup_table (context, lookup_table_empty, FALSE);
-+ bus_input_context_update_lookup_table (context,
-+ lookup_table_empty,
-+ FALSE,
-+ FALSE);
- bus_input_context_register_properties (context, props_empty);
-
- if (context->engine) {
-@@ -1427,7 +1504,12 @@ bus_input_context_focus_out (BusInputContext *context)
- { \
- g_assert (BUS_IS_INPUT_CONTEXT (context)); \
- \
-- if (context->has_focus && context->engine) { \
-+ if (context->is_extension_lookup_table && \
-+ context->emoji_extension) { \
-+ bus_panel_proxy_##name##_lookup_table (context->emoji_extension); \
-+ return; \
-+ } \
-+ if (context->has_focus && context->engine) { \
- bus_engine_proxy_##name (context->engine); \
- } \
- }
-@@ -1447,6 +1529,14 @@ bus_input_context_candidate_clicked (BusInputContext *context,
- {
- g_assert (BUS_IS_INPUT_CONTEXT (context));
-
-+ if (context->is_extension_lookup_table && context->emoji_extension) {
-+ bus_panel_proxy_candidate_clicked_lookup_table (
-+ context->emoji_extension,
-+ index,
-+ button,
-+ state);
-+ return;
-+ }
- if (context->engine) {
- bus_engine_proxy_candidate_clicked (context->engine,
- index,
-@@ -1467,61 +1557,33 @@ bus_input_context_property_activate (BusInputContext *context,
- }
- }
-
--/**
-- * bus_input_context_update_preedit_text:
-- *
-- * Update a preedit text. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
-- */
--static void
--bus_input_context_update_preedit_text (BusInputContext *context,
-- IBusText *text,
-- guint cursor_pos,
-- gboolean visible,
-- guint mode)
--{
-- g_assert (BUS_IS_INPUT_CONTEXT (context));
--
-- if (context->preedit_text) {
-- g_object_unref (context->preedit_text);
-- }
--
-- context->preedit_text = (IBusText *) g_object_ref_sink (text ? text : text_empty);
-- context->preedit_cursor_pos = cursor_pos;
-- context->preedit_visible = visible;
-- context->preedit_mode = mode;
--
-- if (PREEDIT_CONDITION) {
-- GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)context->preedit_text);
-- bus_input_context_emit_signal (context,
-- "UpdatePreeditText",
-- g_variant_new ("(vub)", variant, context->preedit_cursor_pos, context->preedit_visible),
-- NULL);
-- }
-- else {
-- g_signal_emit (context,
-- context_signals[UPDATE_PREEDIT_TEXT],
-- 0,
-- context->preedit_text,
-- context->preedit_cursor_pos,
-- context->preedit_visible);
-- }
--}
--
- /**
- * bus_input_context_show_preedit_text:
- *
- * Show a preedit text. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
- */
- static void
--bus_input_context_show_preedit_text (BusInputContext *context)
-+bus_input_context_show_preedit_text (BusInputContext *context,
-+ gboolean is_extension)
- {
- g_assert (BUS_IS_INPUT_CONTEXT (context));
-
-- if (context->preedit_visible) {
-+ if (context->preedit_visible)
- return;
-- }
-+ if (!is_extension && context->emoji_extension)
-+ return;
-+
-+ if (!is_extension)
-+ context->preedit_visible = TRUE;
-
-- context->preedit_visible = TRUE;
-+ if (context->emoji_extension && !is_extension) {
-+ /* Do not use HIDE_PREEDIT_TEXT signal below but call
-+ * bus_panel_proxy_hide_preedit_text() directly for the extension only
-+ * but not for the normal panel.
-+ */
-+ bus_panel_proxy_show_preedit_text (context->emoji_extension);
-+ return;
-+ }
-
- if (PREEDIT_CONDITION) {
- bus_input_context_emit_signal (context,
-@@ -1542,15 +1604,25 @@ bus_input_context_show_preedit_text (BusInputContext *context)
- * Hide a preedit text. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
- */
- static void
--bus_input_context_hide_preedit_text (BusInputContext *context)
-+bus_input_context_hide_preedit_text (BusInputContext *context,
-+ gboolean is_extension)
- {
- g_assert (BUS_IS_INPUT_CONTEXT (context));
-
-- if (!context->preedit_visible) {
-+ if (!is_extension && !context->preedit_visible)
- return;
-- }
-
-- context->preedit_visible = FALSE;
-+ if (!is_extension)
-+ context->preedit_visible = FALSE;
-+
-+ if (context->emoji_extension && !is_extension) {
-+ /* Do not use HIDE_PREEDIT_TEXT signal below but call
-+ * bus_panel_proxy_hide_preedit_text() directly for the extension only
-+ * but not for the normal panel.
-+ */
-+ bus_panel_proxy_hide_preedit_text (context->emoji_extension);
-+ return;
-+ }
-
- if (PREEDIT_CONDITION) {
- bus_input_context_emit_signal (context,
-@@ -1658,19 +1730,15 @@ bus_input_context_hide_auxiliary_text (BusInputContext *context)
- }
- }
-
--/**
-- * bus_input_context_update_lookup_table:
-- *
-- * Update contents in the lookup table.
-- * Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
-- */
--static void
-+void
- bus_input_context_update_lookup_table (BusInputContext *context,
- IBusLookupTable *table,
-- gboolean visible)
-+ gboolean visible,
-+ gboolean is_extension)
- {
- g_assert (BUS_IS_INPUT_CONTEXT (context));
-
-+ context->is_extension_lookup_table = is_extension;
- if (context->lookup_table) {
- g_object_unref (context->lookup_table);
- }
-@@ -2035,7 +2103,9 @@ _engine_update_preedit_text_cb (BusEngineProxy *engine,
-
- g_assert (context->engine == engine);
-
-- bus_input_context_update_preedit_text (context, text, cursor_pos, visible, mode);
-+ bus_input_context_update_preedit_text (context, text,
-+ cursor_pos, visible, mode,
-+ TRUE);
- }
-
- /**
-@@ -2075,7 +2145,7 @@ _engine_update_lookup_table_cb (BusEngineProxy *engine,
-
- g_assert (context->engine == engine);
-
-- bus_input_context_update_lookup_table (context, table, visible);
-+ bus_input_context_update_lookup_table (context, table, visible, FALSE);
- }
-
- /**
-@@ -2123,11 +2193,35 @@ _engine_update_property_cb (BusEngineProxy *engine,
- * from the engine object.
- */
- static void
--_engine_panel_extension_cb (BusEngineProxy *engine,
-- GVariant *parameters,
-- BusInputContext *context)
-+_engine_panel_extension_cb (BusEngineProxy *engine,
-+ IBusExtensionEvent *event,
-+ BusInputContext *context)
- {
-- g_signal_emit (context, context_signals[PANEL_EXTENSION], 0, parameters);
-+ g_signal_emit (context, context_signals[PANEL_EXTENSION], 0, event);
-+}
-+
-+static void
-+_engine_show_preedit_text_cb (BusEngineProxy *engine,
-+ BusInputContext *context)
-+{
-+ g_assert (BUS_IS_ENGINE_PROXY (engine));
-+ g_assert (BUS_IS_INPUT_CONTEXT (context));
-+
-+ g_assert (context->engine == engine);
-+
-+ bus_input_context_show_preedit_text (context, FALSE);
-+}
-+
-+static void
-+_engine_hide_preedit_text_cb (BusEngineProxy *engine,
-+ BusInputContext *context)
-+{
-+ g_assert (BUS_IS_ENGINE_PROXY (engine));
-+ g_assert (BUS_IS_INPUT_CONTEXT (context));
-+
-+ g_assert (context->engine == engine);
-+
-+ bus_input_context_hide_preedit_text (context, FALSE);
- }
-
- #define DEFINE_FUNCTION(name) \
-@@ -2143,8 +2237,6 @@ _engine_panel_extension_cb (BusEngineProxy *engine,
- bus_input_context_##name (context); \
- }
-
--DEFINE_FUNCTION (show_preedit_text)
--DEFINE_FUNCTION (hide_preedit_text)
- DEFINE_FUNCTION (show_auxiliary_text)
- DEFINE_FUNCTION (hide_auxiliary_text)
- DEFINE_FUNCTION (show_lookup_table)
-@@ -2239,7 +2331,10 @@ bus_input_context_disable (BusInputContext *context)
-
- bus_input_context_clear_preedit_text (context);
- bus_input_context_update_auxiliary_text (context, text_empty, FALSE);
-- bus_input_context_update_lookup_table (context, lookup_table_empty, FALSE);
-+ bus_input_context_update_lookup_table (context,
-+ lookup_table_empty,
-+ FALSE,
-+ FALSE);
- bus_input_context_register_properties (context, props_empty);
-
- if (context->engine) {
-@@ -2283,7 +2378,10 @@ bus_input_context_unset_engine (BusInputContext *context)
-
- bus_input_context_clear_preedit_text (context);
- bus_input_context_update_auxiliary_text (context, text_empty, FALSE);
-- bus_input_context_update_lookup_table (context, lookup_table_empty, FALSE);
-+ bus_input_context_update_lookup_table (context,
-+ lookup_table_empty,
-+ FALSE,
-+ FALSE);
- bus_input_context_register_properties (context, props_empty);
-
- if (context->engine) {
-@@ -2639,17 +2737,128 @@ bus_input_context_set_content_type (BusInputContext *context,
- }
-
- void
--bus_input_context_commit_text (BusInputContext *context,
-- IBusText *text)
-+bus_input_context_commit_text_use_extension (BusInputContext *context,
-+ IBusText *text,
-+ gboolean use_extension)
- {
- g_assert (BUS_IS_INPUT_CONTEXT (context));
-
- if (text == text_empty || text == NULL)
- return;
-
-- GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)text);
-- bus_input_context_emit_signal (context,
-- "CommitText",
-- g_variant_new ("(v)", variant),
-- NULL);
-+ if (use_extension && context->emoji_extension) {
-+ bus_panel_proxy_commit_text_received (context->emoji_extension, text);
-+ } else {
-+ GVariant *variant = ibus_serializable_serialize (
-+ (IBusSerializable *)text);
-+ bus_input_context_emit_signal (context,
-+ "CommitText",
-+ g_variant_new ("(v)", variant),
-+ NULL);
-+ }
-+}
-+
-+void
-+bus_input_context_commit_text (BusInputContext *context,
-+ IBusText *text)
-+{
-+ bus_input_context_commit_text_use_extension (context, text, TRUE);
-+}
-+
-+void
-+bus_input_context_update_preedit_text (BusInputContext *context,
-+ IBusText *text,
-+ guint cursor_pos,
-+ gboolean visible,
-+ guint mode,
-+ gboolean use_extension)
-+{
-+ gboolean extension_visible = FALSE;
-+ g_assert (BUS_IS_INPUT_CONTEXT (context));
-+
-+ if (context->preedit_text) {
-+ g_object_unref (context->preedit_text);
-+ }
-+
-+ context->preedit_text = (IBusText *) g_object_ref_sink (text ? text :
-+ text_empty);
-+ context->preedit_cursor_pos = cursor_pos;
-+ if (use_extension)
-+ context->preedit_visible = visible;
-+ if (use_extension)
-+ context->preedit_mode = mode;
-+ extension_visible = context->preedit_visible |
-+ (context->emoji_extension != NULL);
-+
-+ if (use_extension && context->emoji_extension) {
-+ bus_panel_proxy_update_preedit_text (context->emoji_extension,
-+ context->preedit_text,
-+ context->preedit_cursor_pos,
-+ context->preedit_visible);
-+ } else if (PREEDIT_CONDITION) {
-+ GVariant *variant = ibus_serializable_serialize (
-+ (IBusSerializable *)context->preedit_text);
-+ bus_input_context_emit_signal (context,
-+ "UpdatePreeditText",
-+ g_variant_new (
-+ "(vub)",
-+ variant,
-+ context->preedit_cursor_pos,
-+ extension_visible),
-+ NULL);
-+ } else {
-+ g_signal_emit (context,
-+ context_signals[UPDATE_PREEDIT_TEXT],
-+ 0,
-+ context->preedit_text,
-+ context->preedit_cursor_pos,
-+ extension_visible);
-+ }
-+}
-+
-+void
-+bus_input_context_set_emoji_extension (BusInputContext *context,
-+ BusPanelProxy *emoji_extension)
-+{
-+ g_assert (BUS_IS_INPUT_CONTEXT (context));
-+
-+ if (context->emoji_extension)
-+ g_object_unref (context->emoji_extension);
-+ context->emoji_extension = emoji_extension;
-+ if (emoji_extension) {
-+ g_object_ref (context->emoji_extension);
-+ if (!context->connection)
-+ return;
-+ bus_input_context_show_preedit_text (context, TRUE);
-+ bus_panel_proxy_set_cursor_location (context->emoji_extension,
-+ context->x,
-+ context->y,
-+ context->w,
-+ context->h);
-+ } else {
-+ if (!context->connection)
-+ return;
-+ /* https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/113
-+ * Cannot use bus_input_context_hide_preedit_text () yet.
-+ */
-+ if (!context->preedit_visible) {
-+ bus_input_context_update_preedit_text (context,
-+ text_empty,
-+ 0,
-+ FALSE,
-+ IBUS_ENGINE_PREEDIT_CLEAR,
-+ FALSE);
-+ }
-+ }
-+}
-+
-+void
-+bus_input_context_panel_extension_received (BusInputContext *context,
-+ IBusExtensionEvent *event)
-+{
-+ g_assert (BUS_IS_INPUT_CONTEXT (context));
-+
-+ if (!context->engine)
-+ return;
-+ bus_engine_proxy_panel_extension_received (context->engine, event);
- }
-diff --git a/bus/inputcontext.h b/bus/inputcontext.h
-index 7674abd8..a46d5c06 100644
---- a/bus/inputcontext.h
-+++ b/bus/inputcontext.h
-@@ -28,6 +28,11 @@
- #include "connection.h"
- #include "factoryproxy.h"
-
-+#ifndef __BUS_PANEL_PROXY_DEFINED
-+#define __BUS_PANEL_PROXY_DEFINED
-+typedef struct _BusPanelProxy BusPanelProxy;
-+#endif
-+
- /*
- * Type macros.
- */
-@@ -63,6 +68,7 @@ BusInputContext *bus_input_context_new (BusConnection *connection,
-
- /**
- * bus_input_context_focus_in:
-+ * @context: A #BusInputContext.
- *
- * Give a focus to the context. Call FocusIn, Enable, SetCapabilities,
- * and SetCursorLocation methods of the engine for the context,
-@@ -73,6 +79,7 @@ void bus_input_context_focus_in (BusInputContext *context);
-
- /**
- * bus_input_context_focus_out:
-+ * @context: A #BusInputContext.
- *
- * Remove a focus from the context. Call FocusOut method of the engine for
- * the context.
-@@ -83,6 +90,7 @@ void bus_input_context_focus_out
-
- /**
- * bus_input_context_has_focus:
-+ * @context: A #BusInputContext.
- * @returns: context->has_focus.
- */
- gboolean bus_input_context_has_focus
-@@ -90,6 +98,7 @@ gboolean bus_input_context_has_focus
-
- /**
- * bus_input_context_enable:
-+ * @context: A #BusInputContext.
- *
- * Enable the current engine for the context. Request an engine (if needed),
- * call FocusIn, Enable, SetCapabilities, and SetCursorLocation methods
-@@ -100,6 +109,7 @@ void bus_input_context_enable (BusInputContext *context);
-
- /**
- * bus_input_context_disable:
-+ * @context: A #BusInputContext.
- *
- * Disable the current engine for the context. Request an engine (if needed),
- * call FocusIn, Enable, SetCapabilities, and SetCursorLocation methods
-@@ -110,6 +120,7 @@ void bus_input_context_disable (BusInputContext *context);
-
- /**
- * bus_input_context_page_up:
-+ * @context: A #BusInputContext.
- *
- * Call page_up method of the current engine proxy.
- */
-@@ -117,6 +128,7 @@ void bus_input_context_page_up (BusInputContext *context);
-
- /**
- * bus_input_context_page_down:
-+ * @context: A #BusInputContext.
- *
- * Call page_down method of the current engine proxy.
- */
-@@ -125,6 +137,7 @@ void bus_input_context_page_down
-
- /**
- * bus_input_context_cursor_up:
-+ * @context: A #BusInputContext.
- *
- * Call cursor_up method of the current engine proxy.
- */
-@@ -133,6 +146,7 @@ void bus_input_context_cursor_up
-
- /**
- * bus_input_context_cursor_down:
-+ * @context: A #BusInputContext.
- *
- * Call cursor_down method of the current engine proxy.
- */
-@@ -141,6 +155,10 @@ void bus_input_context_cursor_down
-
- /**
- * bus_input_context_candidate_clicked:
-+ * @context: A #BusInputContext.
-+ * @index: An index.
-+ * @button: A button number.
-+ * @state: A button state.
- *
- * Call candidate_clicked method of the current engine proxy.
- */
-@@ -152,6 +170,8 @@ void bus_input_context_candidate_clicked
-
- /**
- * bus_input_context_set_engine:
-+ * @context: A #BusInputContext.
-+ * @engine: A #BusEngineProxy.
- *
- * Use the engine on the context.
- */
-@@ -161,12 +181,14 @@ void bus_input_context_set_engine
-
- /**
- * bus_input_context_set_engine_by_desc:
-+ * @context: A #BusInputContext.
- * @desc: the engine to use on the context.
- * @timeout: timeout (in ms) for D-Bus calls.
- * @callback: a function to be called when bus_input_context_set_engine_by_desc
- * is finished. if NULL, the default callback
- * function, which just calls
- * bus_input_context_set_engine_by_desc_finish, is used.
-+ * @user_data: an argument of @callback.
- *
- * Create a new BusEngineProxy object and use it on the context.
- */
-@@ -181,6 +203,9 @@ void bus_input_context_set_engine_by_desc
-
- /**
- * bus_input_context_set_engine_by_desc_finish:
-+ * @context: A #BusInputContext.
-+ * @res: A #GAsyncResult.
-+ * @error: A #GError.
- *
- * A function to be called by the GAsyncReadyCallback function for
- * bus_input_context_set_engine_by_desc.
-@@ -192,6 +217,7 @@ gboolean bus_input_context_set_engine_by_desc_finish
-
- /**
- * bus_input_context_get_engine:
-+ * @context: A #BusInputContext.
- *
- * Get a BusEngineProxy object of the current engine.
- */
-@@ -200,6 +226,7 @@ BusEngineProxy *bus_input_context_get_engine
-
- /**
- * bus_input_context_get_engine_desc:
-+ * @context: A #BusInputContext.
- *
- * Get an IBusEngineDesc object of the current engine.
- */
-@@ -208,6 +235,9 @@ IBusEngineDesc *bus_input_context_get_engine_desc
-
- /**
- * bus_input_context_property_activate:
-+ * @context: A #BusInputContext.
-+ * @prop_name: A property name.
-+ * @prop_state: A property state.
- *
- * Call property_activate method of the current engine proxy.
- */
-@@ -219,6 +249,7 @@ void bus_input_context_property_activate
-
- /**
- * bus_input_context_get_capabilities:
-+ * @context: A #BusInputContext.
- * @returns: context->capabilities.
- */
- guint bus_input_context_get_capabilities
-@@ -226,6 +257,8 @@ guint bus_input_context_get_capabilities
-
- /**
- * bus_input_context_set_capabilities:
-+ * @context: A #BusInputContext.
-+ * @capabilities: capabilities.
- *
- * Call set_capabilities method of the current engine proxy.
- */
-@@ -236,6 +269,7 @@ void bus_input_context_set_capabilities
-
- /**
- * bus_input_context_get_client:
-+ * @context: A #BusInputContext.
- * @returns: context->client.
- */
- const gchar *bus_input_context_get_client
-@@ -243,6 +277,7 @@ const gchar *bus_input_context_get_client
-
- /**
- * bus_input_context_get_content_type:
-+ * @context: A #BusInputContext.
- * @purpose: Input purpose.
- * @hints: Input hints.
- */
-@@ -253,6 +288,7 @@ void bus_input_context_get_content_type
-
- /**
- * bus_input_context_set_content_type:
-+ * @context: A #BusInputContext.
- * @purpose: Input purpose.
- * @hints: Input hints.
- */
-@@ -263,11 +299,83 @@ void bus_input_context_set_content_type
-
- /**
- * bus_input_context_commit_text:
-- * @text: a commited text.
-+ * @context: A #BusInputContext.
-+ * @text: A committed text.
- */
- void bus_input_context_commit_text
- (BusInputContext *context,
- IBusText *text);
-
-+/**
-+ * bus_input_context_commit_text:
-+ * @context: A #BusInputContext.
-+ * @text: A committed text.
-+ * @use_extension: Use an extension if it's %TRUE and the extension is
-+ * available.
-+ */
-+void bus_input_context_commit_text_use_extension
-+ (BusInputContext *context,
-+ IBusText *text,
-+ gboolean use_extension);
-+
-+/**
-+ * bus_input_context_set_emoji_extension:
-+ * @context: A #BusInputContext.
-+ * @extension: A #BusPanelProxy.
-+ */
-+void bus_input_context_set_emoji_extension
-+ (BusInputContext *context,
-+ BusPanelProxy *extension);
-+
-+/**
-+ * bus_input_context_update_preedit_text:
-+ * @context: A #BusInputContext.
-+ * @text: An #IBusText.
-+ * @cursor_pos: The cursor position.
-+ * @visible: %TRUE if the preedit is visible. Otherwise %FALSE.
-+ * @mode: The preedit commit mode.
-+ * @use_extension: %TRUE if preedit text is sent to the extesion at first.
-+ *
-+ * Update a preedit text. Send D-Bus signal to update status of client or
-+ * send glib signal to the panel, depending on capabilities of the client.
-+ */
-+void bus_input_context_update_preedit_text
-+ (BusInputContext *context,
-+ IBusText *text,
-+ guint cursor_pos,
-+ gboolean visible,
-+ guint mode,
-+ gboolean
-+ use_extension);
-+
-+/**
-+ * bus_input_context_update_lookup_table:
-+ * @context: A #BusInputContext.
-+ * @table: An #IBusTable.
-+ * @visible: %TRUE if the lookup table is visible. Otherwise %FALSE.
-+ * @is_extension: %TRUE if the lookup table is created by panel extensions.
-+ *
-+ * Update contents in the lookup table.
-+ * Send D-Bus signal to update status of client or send glib signal to the
-+ * panel, depending on capabilities of the client.
-+ */
-+void bus_input_context_update_lookup_table
-+ (BusInputContext *context,
-+ IBusLookupTable *table,
-+ gboolean visible,
-+ gboolean
-+ is_extension);
-+
-+
-+/**
-+ * bus_input_context_panel_extension_received:
-+ * @context: A #BusInputContext.
-+ * @event: An #IBusExtensionEvent.
-+ *
-+ * Send An #IBusExtensionEvent callback from an extension.
-+ */
-+void bus_input_context_panel_extension_received
-+ (BusInputContext *context,
-+ IBusExtensionEvent *event);
- G_END_DECLS
- #endif
-diff --git a/bus/panelproxy.c b/bus/panelproxy.c
-index c3908fcf..1c0fcca2 100644
---- a/bus/panelproxy.c
-+++ b/bus/panelproxy.c
-@@ -52,6 +52,10 @@ enum {
- PROPERTY_HIDE,
- COMMIT_TEXT,
- PANEL_EXTENSION,
-+ PANEL_EXTENSION_REGISTER_KEYS,
-+ UPDATE_PREEDIT_TEXT_RECEIVED,
-+ UPDATE_LOOKUP_TABLE_RECEIVED,
-+ UPDATE_AUXILIARY_TEXT_RECEIVED,
- LAST_SIGNAL,
- };
-
-@@ -125,8 +129,8 @@ bus_panel_proxy_new (BusConnection *connection,
- case PANEL_TYPE_PANEL:
- path = IBUS_PATH_PANEL;
- break;
-- case PANEL_TYPE_EXTENSION:
-- path = IBUS_PATH_PANEL_EXTENSION;
-+ case PANEL_TYPE_EXTENSION_EMOJI:
-+ path = IBUS_PATH_PANEL_EXTENSION_EMOJI;
- break;
- default:
- g_return_val_if_reached (NULL);
-@@ -253,6 +257,16 @@ bus_panel_proxy_class_init (BusPanelProxyClass *class)
-
- panel_signals[PANEL_EXTENSION] =
- g_signal_new (I_("panel-extension"),
-+ G_TYPE_FROM_CLASS (class),
-+ G_SIGNAL_RUN_LAST,
-+ 0,
-+ NULL, NULL,
-+ bus_marshal_VOID__OBJECT,
-+ G_TYPE_NONE, 1,
-+ IBUS_TYPE_EXTENSION_EVENT);
-+
-+ panel_signals[PANEL_EXTENSION_REGISTER_KEYS] =
-+ g_signal_new (I_("panel-extension-register-keys"),
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- 0,
-@@ -260,6 +274,40 @@ bus_panel_proxy_class_init (BusPanelProxyClass *class)
- bus_marshal_VOID__VARIANT,
- G_TYPE_NONE, 1,
- G_TYPE_VARIANT);
-+
-+ panel_signals[UPDATE_PREEDIT_TEXT_RECEIVED] =
-+ g_signal_new (I_("update-preedit-text-received"),
-+ G_TYPE_FROM_CLASS (class),
-+ G_SIGNAL_RUN_LAST,
-+ 0,
-+ NULL, NULL,
-+ bus_marshal_VOID__OBJECT_UINT_BOOLEAN,
-+ G_TYPE_NONE, 3,
-+ IBUS_TYPE_TEXT,
-+ G_TYPE_UINT,
-+ G_TYPE_BOOLEAN);
-+
-+ panel_signals[UPDATE_LOOKUP_TABLE_RECEIVED] =
-+ g_signal_new (I_("update-lookup-table-received"),
-+ G_TYPE_FROM_CLASS (class),
-+ G_SIGNAL_RUN_LAST,
-+ 0,
-+ NULL, NULL,
-+ bus_marshal_VOID__OBJECT_BOOLEAN,
-+ G_TYPE_NONE, 2,
-+ IBUS_TYPE_LOOKUP_TABLE,
-+ G_TYPE_BOOLEAN);
-+
-+ panel_signals[UPDATE_AUXILIARY_TEXT_RECEIVED] =
-+ g_signal_new (I_("update-auxiliary-text-received"),
-+ G_TYPE_FROM_CLASS (class),
-+ G_SIGNAL_RUN_LAST,
-+ 0,
-+ NULL, NULL,
-+ bus_marshal_VOID__OBJECT_BOOLEAN,
-+ G_TYPE_NONE, 2,
-+ IBUS_TYPE_TEXT,
-+ G_TYPE_BOOLEAN);
- }
-
- static void
-@@ -355,23 +403,83 @@ bus_panel_proxy_g_signal (GDBusProxy *proxy,
-
- if (g_strcmp0 ("CommitText", signal_name) == 0) {
- GVariant *arg0 = NULL;
-- g_variant_get (parameters, "(v)", &arg0);
-- g_return_if_fail (arg0 != NULL);
-
-+ g_variant_get (parameters, "(v)", &arg0);
-+ g_return_if_fail (arg0);
- IBusText *text = IBUS_TEXT (ibus_serializable_deserialize (arg0));
- g_variant_unref (arg0);
-- g_return_if_fail (text != NULL);
-+ g_return_if_fail (text);
- g_signal_emit (panel, panel_signals[COMMIT_TEXT], 0, text);
- _g_object_unref_if_floating (text);
- return;
- }
-
- if (g_strcmp0 ("PanelExtension", signal_name) == 0) {
-- if (panel->panel_type != PANEL_TYPE_PANEL) {
-- g_warning ("Wrong signal");
-- return;
-- }
-- g_signal_emit (panel, panel_signals[PANEL_EXTENSION], 0, parameters);
-+ GVariant *arg0 = NULL;
-+
-+ g_variant_get (parameters, "(v)", &arg0);
-+ g_return_if_fail (arg0);
-+ IBusExtensionEvent *event = IBUS_EXTENSION_EVENT (
-+ ibus_serializable_deserialize (arg0));
-+ g_variant_unref (arg0);
-+ g_return_if_fail (event);
-+ g_signal_emit (panel, panel_signals[PANEL_EXTENSION], 0, event);
-+ _g_object_unref_if_floating (event);
-+ return;
-+ }
-+
-+ if (g_strcmp0 ("PanelExtensionRegisterKeys", signal_name) == 0) {
-+ g_signal_emit (panel, panel_signals[PANEL_EXTENSION_REGISTER_KEYS], 0,
-+ parameters);
-+ return;
-+ }
-+
-+ if (g_strcmp0 ("UpdatePreeditTextReceived", signal_name) == 0) {
-+ GVariant *variant = NULL;
-+ guint cursor_pos = 0;
-+ gboolean visible = FALSE;
-+ IBusText *text = NULL;
-+
-+ g_variant_get (parameters, "(vub)", &variant, &cursor_pos, &visible);
-+ g_return_if_fail (variant);
-+ text = (IBusText *) ibus_serializable_deserialize (variant);
-+ g_variant_unref (variant);
-+ g_return_if_fail (text);
-+ g_signal_emit (panel, panel_signals[UPDATE_PREEDIT_TEXT_RECEIVED], 0,
-+ text, cursor_pos, visible);
-+ _g_object_unref_if_floating (text);
-+ return;
-+ }
-+
-+ if (g_strcmp0 ("UpdateLookupTableReceived", signal_name) == 0) {
-+ GVariant *variant = NULL;
-+ gboolean visible = FALSE;
-+ IBusLookupTable *table = NULL;
-+
-+ g_variant_get (parameters, "(vb)", &variant, &visible);
-+ g_return_if_fail (variant);
-+ table = (IBusLookupTable *) ibus_serializable_deserialize (variant);
-+ g_variant_unref (variant);
-+ g_return_if_fail (table);
-+ g_signal_emit (panel, panel_signals[UPDATE_LOOKUP_TABLE_RECEIVED], 0,
-+ table, visible);
-+ _g_object_unref_if_floating (table);
-+ return;
-+ }
-+
-+ if (g_strcmp0 ("UpdateAuxiliaryTextReceived", signal_name) == 0) {
-+ GVariant *variant = NULL;
-+ gboolean visible = FALSE;
-+ IBusText *text = NULL;
-+
-+ g_variant_get (parameters, "(vb)", &variant, &visible);
-+ g_return_if_fail (variant);
-+ text = (IBusText *) ibus_serializable_deserialize (variant);
-+ g_variant_unref (variant);
-+ g_return_if_fail (text);
-+ g_signal_emit (panel, panel_signals[UPDATE_AUXILIARY_TEXT_RECEIVED], 0,
-+ text, visible);
-+ _g_object_unref_if_floating (text);
- return;
- }
-
-@@ -552,12 +660,17 @@ static void
- bus_panel_proxy_commit_text (BusPanelProxy *panel,
- IBusText *text)
- {
-+ gboolean use_extension = TRUE;
- g_assert (BUS_IS_PANEL_PROXY (panel));
- g_assert (text != NULL);
-
-- if (panel->focused_context) {
-- bus_input_context_commit_text (panel->focused_context, text);
-- }
-+ if (!panel->focused_context)
-+ return;
-+ if (panel->panel_type != PANEL_TYPE_PANEL)
-+ use_extension = FALSE;
-+ bus_input_context_commit_text_use_extension (panel->focused_context,
-+ text,
-+ use_extension);
- }
-
- #define DEFINE_FUNCTION(Name, name) \
-@@ -877,3 +990,74 @@ bus_panel_proxy_get_panel_type (BusPanelProxy *panel)
- g_assert (BUS_IS_PANEL_PROXY (panel));
- return panel->panel_type;
- }
-+
-+void
-+bus_panel_proxy_panel_extension_received (BusPanelProxy *panel,
-+ IBusExtensionEvent *event)
-+{
-+ GVariant *data;
-+
-+ g_assert (BUS_IS_PANEL_PROXY (panel));
-+ g_assert (event);
-+
-+ data = ibus_serializable_serialize (IBUS_SERIALIZABLE (event));
-+ g_return_if_fail (data);
-+ g_dbus_proxy_call ((GDBusProxy *)panel,
-+ "PanelExtensionReceived",
-+ g_variant_new ("(v)", data),
-+ G_DBUS_CALL_FLAGS_NONE,
-+ -1, NULL, NULL, NULL);
-+}
-+
-+void
-+bus_panel_proxy_process_key_event (BusPanelProxy *panel,
-+ guint keyval,
-+ guint keycode,
-+ guint state,
-+ GAsyncReadyCallback callback,
-+ gpointer user_data)
-+{
-+ g_assert (BUS_IS_PANEL_PROXY (panel));
-+
-+ g_dbus_proxy_call ((GDBusProxy *)panel,
-+ "ProcessKeyEvent",
-+ g_variant_new ("(uuu)", keyval, keycode, state),
-+ G_DBUS_CALL_FLAGS_NONE,
-+ -1,
-+ NULL,
-+ callback,
-+ user_data);
-+}
-+
-+void
-+bus_panel_proxy_commit_text_received (BusPanelProxy *panel,
-+ IBusText *text)
-+{
-+ GVariant *variant;
-+
-+ g_assert (BUS_IS_PANEL_PROXY (panel));
-+ g_assert (IBUS_IS_TEXT (text));
-+
-+ variant = ibus_serializable_serialize (IBUS_SERIALIZABLE (text));
-+ g_dbus_proxy_call ((GDBusProxy *)panel,
-+ "CommitTextReceived",
-+ g_variant_new ("(v)", variant),
-+ G_DBUS_CALL_FLAGS_NONE,
-+ -1, NULL, NULL, NULL);
-+}
-+
-+void
-+bus_panel_proxy_candidate_clicked_lookup_table (BusPanelProxy *panel,
-+ guint index,
-+ guint button,
-+ guint state)
-+{
-+ gboolean use_extension = TRUE;
-+ g_assert (BUS_IS_PANEL_PROXY (panel));
-+
-+ g_dbus_proxy_call ((GDBusProxy *)panel,
-+ "CandidateClickedLookupTable",
-+ g_variant_new ("(uuu)", index, button, state),
-+ G_DBUS_CALL_FLAGS_NONE,
-+ -1, NULL, NULL, NULL);
-+}
-diff --git a/bus/panelproxy.h b/bus/panelproxy.h
-index b5a7af17..4d8afb98 100644
---- a/bus/panelproxy.h
-+++ b/bus/panelproxy.h
-@@ -55,7 +55,7 @@ typedef enum
- {
- PANEL_TYPE_NONE,
- PANEL_TYPE_PANEL,
-- PANEL_TYPE_EXTENSION
-+ PANEL_TYPE_EXTENSION_EMOJI
- } PanelType;
-
- typedef struct _BusPanelProxy BusPanelProxy;
-@@ -135,6 +135,27 @@ void bus_panel_proxy_set_content_type
- guint hints);
- PanelType bus_panel_proxy_get_panel_type
- (BusPanelProxy *panel);
-+void bus_panel_proxy_panel_extension_received
-+ (BusPanelProxy *panel,
-+ IBusExtensionEvent
-+ *event);
-+void bus_panel_proxy_process_key_event
-+ (BusPanelProxy *panel,
-+ guint keyval,
-+ guint keycode,
-+ guint state,
-+ GAsyncReadyCallback
-+ callback,
-+ gpointer user_data);
-+void bus_panel_proxy_commit_text_received
-+ (BusPanelProxy *panel,
-+ IBusText *text);
-+void bus_panel_proxy_candidate_clicked_lookup_table
-+ (BusPanelProxy *panel,
-+ guint index,
-+ guint button,
-+ guint state);
-+
- G_END_DECLS
- #endif
-
-diff --git a/data/ibus.schemas.in b/data/ibus.schemas.in
-index 3c6b6f69..f4a019d0 100644
---- a/data/ibus.schemas.in
-+++ b/data/ibus.schemas.in
-@@ -353,6 +353,18 @@
- <long>Custom font name for language panel</long>
- </locale>
- </schema>
-+ <schema>
-+ <key>/schemas/desktop/ibus/panel/emoji/unicode-hotkey</key>
-+ <applyto>/desktop/ibus/panel/emoji/unicode-hotkey</applyto>
-+ <owner>ibus</owner>
-+ <type>list</type>
-+ <list_type>string</list_type>
-+ <default>[<Control><Shift>u]</default>
-+ <locale name="C">
-+ <short>Unicode shortcut keys for gtk_accelerator_parse</short>
-+ <long>The shortcut keys for turning Unicode typing on or off</long>
-+ </locale>
-+ </schema>
- <schema>
- <key>/schemas/desktop/ibus/panel/emoji/hotkey</key>
- <applyto>/desktop/ibus/panel/emoji/hotkey</applyto>
-diff --git a/setup/main.py b/setup/main.py
-index f0eee996..f6adb098 100644
---- a/setup/main.py
-+++ b/setup/main.py
-@@ -4,7 +4,7 @@
- # ibus - The Input Bus
- #
- # Copyright (c) 2007-2016 Peng Huang <shawn.p.huang@gmail.com>
--# Copyright (c) 2010-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+# Copyright (c) 2010-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
- # Copyright (c) 2007-2016 Red Hat, Inc.
- #
- # This library is free software; you can redistribute it and/or
-@@ -123,10 +123,15 @@ class Setup(object):
- name = 'emoji'
- label = 'emoji_dialog'
- self.__init_hotkey(name, label)
-+ name = 'unicode'
-+ label = 'unicode_dialog'
-+ self.__init_hotkey(name, label)
-
- def __init_hotkey(self, name, label, comment=None):
- if name == 'emoji':
- shortcuts = self.__settings_emoji.get_strv('hotkey')
-+ elif name == 'unicode':
-+ shortcuts = self.__settings_emoji.get_strv('unicode-hotkey')
- else:
- shortcuts = self.__settings_hotkey.get_strv(name)
- button = self.__builder.get_object("button_%s" % label)
-@@ -139,6 +144,9 @@ class Setup(object):
- if name == 'emoji':
- button.connect("clicked", self.__shortcut_button_clicked_cb,
- 'hotkey', 'panel/' + name, label, entry)
-+ elif name == 'unicode':
-+ button.connect("clicked", self.__shortcut_button_clicked_cb,
-+ 'unicode-hotkey', 'panel/emoji', label, entry)
- else:
- button.connect("clicked", self.__shortcut_button_clicked_cb,
- name, "general/hotkey", label, entry)
-diff --git a/setup/setup.ui b/setup/setup.ui
-index e64b1046..f1beb1de 100644
---- a/setup/setup.ui
-+++ b/setup/setup.ui
-@@ -870,9 +870,9 @@
- <object class="GtkLabel" id="label_emoji1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
-- <property name="tooltip_text" translatable="yes">The shortcut keys for showing emoji dialog</property>
-+ <property name="tooltip_text" translatable="yes">The shortcut keys to enable conversions of emoji annotations or Unicode names</property>
- <property name="halign">start</property>
-- <property name="label" translatable="yes">Emoji choice:</property>
-+ <property name="label" translatable="yes">Emoji annotation:</property>
- </object>
- <packing>
- <property name="left_attach">0</property>
-@@ -920,6 +920,60 @@
- <property name="top_attach">0</property>
- </packing>
- </child>
-+ <child>
-+ <object class="GtkLabel" id="label_unicode1">
-+ <property name="visible">True</property>
-+ <property name="can_focus">False</property>
-+ <property name="tooltip_text" translatable="yes">The shortcut keys to enable Unicode code point conversions</property>
-+ <property name="halign">start</property>
-+ <property name="label" translatable="yes">Unicode code point:</property>
-+ </object>
-+ <packing>
-+ <property name="left_attach">0</property>
-+ <property name="top_attach">1</property>
-+ </packing>
-+ </child>
-+ <child>
-+ <object class="GtkBox" id="hbox_unicode1">
-+ <property name="orientation">horizontal</property>
-+ <property name="visible">True</property>
-+ <property name="can_focus">False</property>
-+ <property name="spacing">6</property>
-+ <property name="hexpand">true</property>
-+ <child>
-+ <object class="GtkEntry" id="entry_unicode_dialog">
-+ <property name="visible">True</property>
-+ <property name="can_focus">True</property>
-+ <property name="editable">False</property>
-+ </object>
-+ <packing>
-+ <property name="expand">True</property>
-+ <property name="fill">True</property>
-+ <property name="position">0</property>
-+ </packing>
-+ </child>
-+ <child>
-+ <object class="GtkButton" id="button_unicode_dialog">
-+ <property name="label" translatable="yes">...</property>
-+ <property name="use_action_appearance">False</property>
-+ <property name="visible">True</property>
-+ <property name="can_focus">True</property>
-+ <property name="receives_default">False</property>
-+ <property name="use_action_appearance">False</property>
-+ <property name="use_underline">True</property>
-+ </object>
-+ <packing>
-+ <property name="expand">False</property>
-+ <property name="fill">True</property>
-+ <property name="position">1</property>
-+ </packing>
-+ </child>
-+ </object>
-+ <packing>
-+ <property name="left_attach">1</property>
-+ <property name="top_attach">1</property>
-+ </packing>
-+ </child>
- </object>
- </child>
- <child type="label">
-diff --git a/src/ibusengine.c b/src/ibusengine.c
-index fd61102a..a3ccd7dd 100644
---- a/src/ibusengine.c
-+++ b/src/ibusengine.c
-@@ -64,8 +64,6 @@ enum {
- };
-
-
--typedef struct _IBusEngineKeybinding IBusEngineKeybinding;
--
- /* IBusEnginePriv */
- struct _IBusEnginePrivate {
- gchar *engine_name;
-@@ -81,14 +79,11 @@ struct _IBusEnginePrivate {
- guint content_purpose;
- guint content_hints;
-
-- GSettings *settings_emoji;
-- IBusEngineKeybinding **emoji_keybindings;
-+ GHashTable *extension_keybindings;
-+ gboolean enable_extension;
-+ gchar *current_extension_name;
- };
-
--struct _IBusEngineKeybinding {
-- guint keyval;
-- IBusModifierType modifiers;
--};
-
- static guint engine_signals[LAST_SIGNAL] = { 0 };
-
-@@ -191,10 +186,6 @@ static void ibus_engine_dbus_property_changed
- const gchar *property_name,
- GVariant *value);
- static void ibus_engine_keybinding_free (IBusEngine *engine);
--static void settings_emoji_hotkey_changed_cb
-- (GSettings *settings,
-- const gchar *key,
-- gpointer data);
-
-
- G_DEFINE_TYPE (IBusEngine, ibus_engine, IBUS_TYPE_SERVICE)
-@@ -253,6 +244,12 @@ static const gchar introspection_xml[] =
- " <arg direction='in' type='u' name='cursor_pos' />"
- " <arg direction='in' type='u' name='anchor_pos' />"
- " </method>"
-+ " <method name='PanelExtensionReceived'>"
-+ " <arg direction='in' type='v' name='event' />"
-+ " </method>"
-+ " <method name='PanelExtensionRegisterKeys'>"
-+ " <arg direction='in' type='v' name='data' />"
-+ " </method>"
- /* FIXME signals */
- " <signal name='CommitText'>"
- " <arg type='v' name='text' />"
-@@ -309,16 +306,22 @@ ibus_engine_class_init (IBusEngineClass *class)
- GObjectClass *gobject_class = G_OBJECT_CLASS (class);
- IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (class);
-
-- gobject_class->set_property = (GObjectSetPropertyFunc) ibus_engine_set_property;
-- gobject_class->get_property = (GObjectGetPropertyFunc) ibus_engine_get_property;
-+ gobject_class->set_property =
-+ (GObjectSetPropertyFunc) ibus_engine_set_property;
-+ gobject_class->get_property =
-+ (GObjectGetPropertyFunc) ibus_engine_get_property;
-
- ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_engine_destroy;
-
-- IBUS_SERVICE_CLASS (class)->service_method_call = ibus_engine_service_method_call;
-- IBUS_SERVICE_CLASS (class)->service_get_property = ibus_engine_service_get_property;
-- IBUS_SERVICE_CLASS (class)->service_set_property = ibus_engine_service_set_property;
-+ IBUS_SERVICE_CLASS (class)->service_method_call =
-+ ibus_engine_service_method_call;
-+ IBUS_SERVICE_CLASS (class)->service_get_property =
-+ ibus_engine_service_get_property;
-+ IBUS_SERVICE_CLASS (class)->service_set_property =
-+ ibus_engine_service_set_property;
-
-- ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class), introspection_xml);
-+ ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class),
-+ introspection_xml);
-
- class->process_key_event = ibus_engine_process_key_event;
- class->focus_in = ibus_engine_focus_in;
-@@ -839,26 +842,25 @@ ibus_engine_init (IBusEngine *engine)
- {
- IBusEnginePrivate *priv;
- engine->priv = priv = IBUS_ENGINE_GET_PRIVATE (engine);
--
- priv->surrounding_text = g_object_ref_sink (text_empty);
-- priv->settings_emoji =
-- g_settings_new ("org.freedesktop.ibus.panel.emoji");
-- settings_emoji_hotkey_changed_cb (priv->settings_emoji, "hotkey", engine);
-- g_signal_connect (priv->settings_emoji, "changed::hotkey",
-- G_CALLBACK (settings_emoji_hotkey_changed_cb), engine);
-+ priv->extension_keybindings = g_hash_table_new_full (
-+ g_str_hash,
-+ g_str_equal,
-+ g_free,
-+ g_free);
- }
-
- static void
- ibus_engine_destroy (IBusEngine *engine)
- {
-- g_free (engine->priv->engine_name);
-- engine->priv->engine_name = NULL;
-+ IBusEnginePrivate *priv = engine->priv;
-
-- if (engine->priv->surrounding_text) {
-- g_object_unref (engine->priv->surrounding_text);
-- engine->priv->surrounding_text = NULL;
-- }
-- ibus_engine_keybinding_free (engine);
-+ g_clear_pointer (&priv->engine_name, g_free);
-+ g_clear_pointer (&priv->current_extension_name, g_free);
-+ if (priv->surrounding_text)
-+ g_clear_object (&priv->surrounding_text);
-+ if (priv->extension_keybindings)
-+ g_clear_pointer (&priv->extension_keybindings, g_hash_table_destroy);
-
- IBUS_OBJECT_CLASS(ibus_engine_parent_class)->destroy (IBUS_OBJECT (engine));
- }
-@@ -895,19 +897,38 @@ ibus_engine_get_property (IBusEngine *engine,
- }
-
- static void
--ibus_engine_panel_extension (IBusEngine *engine)
-+ibus_engine_panel_extension (IBusEngine *engine,
-+ const gchar *name)
- {
-- IBusXEvent *xevent = ibus_x_event_new (
-- "event-type", IBUS_X_EVENT_KEY_PRESS,
-- "purpose", "emoji",
-+ IBusEnginePrivate *priv;
-+ IBusExtensionEvent *event;
-+ GVariant *data;
-+
-+ g_assert (IBUS_IS_ENGINE (engine));
-+ g_assert (name);
-+
-+ priv = engine->priv;
-+ if (!g_strcmp0 (name, priv->current_extension_name))
-+ priv->enable_extension = !priv->enable_extension;
-+ else
-+ priv->enable_extension = TRUE;
-+ if (priv->enable_extension) {
-+ g_free (priv->current_extension_name);
-+ priv->current_extension_name = g_strdup (name);
-+ }
-+ event = ibus_extension_event_new (
-+ "name", name,
-+ "is-enabled", priv->enable_extension,
- NULL);
-- GVariant *data = ibus_serializable_serialize_object (
-- IBUS_SERIALIZABLE (xevent));
-+ g_assert (IBUS_IS_EXTENSION_EVENT (event));
-+ data = ibus_serializable_serialize_object (
-+ IBUS_SERIALIZABLE (event));
-
- g_assert (data != NULL);
- ibus_engine_emit_signal (engine,
- "PanelExtension",
- g_variant_new ("(v)", data));
-+ g_object_unref (event);
- }
-
- static gboolean
-@@ -917,7 +938,8 @@ ibus_engine_filter_key_event (IBusEngine *engine,
- guint state)
- {
- IBusEnginePrivate *priv;
-- int i;
-+ GList *names, *n;
-+ IBusProcessKeyEventData *keys;
- guint modifiers;
-
- if ((state & IBUS_RELEASE_MASK) != 0)
-@@ -925,22 +947,29 @@ ibus_engine_filter_key_event (IBusEngine *engine,
- g_return_val_if_fail (IBUS_IS_ENGINE (engine), FALSE);
-
- priv = engine->priv;
-- if (!priv->emoji_keybindings)
-- return FALSE;
--
- modifiers = state & IBUS_MODIFIER_FILTER;
- if (keyval >= IBUS_KEY_A && keyval <= IBUS_KEY_Z &&
- (modifiers & IBUS_SHIFT_MASK) != 0) {
- keyval = keyval - IBUS_KEY_A + IBUS_KEY_a;
- }
-- for (i = 0; priv->emoji_keybindings[i]; i++) {
-- IBusEngineKeybinding *binding = priv->emoji_keybindings[i];
-- if (binding->keyval == keyval &&
-- binding->modifiers == modifiers) {
-- ibus_engine_panel_extension (engine);
-- return TRUE;
-+ names = g_hash_table_get_keys (priv->extension_keybindings);
-+ if (!names)
-+ return FALSE;
-+ for (n = names; n; n = n->next) {
-+ const gchar *name = (const gchar *)n->data;
-+ keys = g_hash_table_lookup (priv->extension_keybindings, name);
-+ for (; keys; keys++) {
-+ if (keys->keyval == 0 && keys->keycode == 0 && keys->state == 0)
-+ break;
-+ if (keys->keyval == keyval &&
-+ keys->state == modifiers &&
-+ (keys->keycode == 0 || keys->keycode == keycode)) {
-+ ibus_engine_panel_extension (engine, name);
-+ return TRUE;
-+ }
- }
- }
-+ g_list_free (names);
- return FALSE;
- }
-
-@@ -953,6 +982,97 @@ ibus_engine_service_authorized_method (IBusService *service,
- return FALSE;
- }
-
-+static void
-+ibus_engine_service_panel_extension_register_keys (IBusEngine *engine,
-+ GVariant *parameters,
-+ GDBusMethodInvocation
-+ *invocation)
-+{
-+ IBusEnginePrivate *priv = engine->priv;
-+ GVariant *v1 = NULL;
-+ GVariant *v2 = NULL;
-+ GVariant *v3 = NULL;
-+ GVariant *vkeys = NULL;
-+ GVariantIter *iter1 = NULL;
-+ GVariantIter *iter2 = NULL;
-+ const gchar *name = NULL;
-+ guint failure_id = 0;
-+
-+ g_variant_get (parameters, "(v)", &v1);
-+ if (v1)
-+ g_variant_get (v1, "(v)", &v2);
-+ else
-+ failure_id = 1;
-+ if (v2)
-+ g_variant_get (v2, "a{sv}", &iter1);
-+ else
-+ failure_id = 2;
-+ if (iter1) {
-+ while (g_variant_iter_loop (iter1, "{&sv}", &name, &vkeys)) {
-+ if (vkeys)
-+ g_variant_get (vkeys, "av", &iter2);
-+ if (name && iter2) {
-+ IBusProcessKeyEventData *keys = NULL;
-+ gint num = 0;
-+ while (g_variant_iter_loop (iter2, "v", &v3)) {
-+ if (v3) {
-+ guint keyval = 0;
-+ guint keycode = 0;
-+ guint state = 0;
-+ g_variant_get (v3, "(iii)",
-+ &keyval, &keycode, &state);
-+ if (!keys)
-+ keys = g_new0 (IBusProcessKeyEventData, 2);
-+ else
-+ keys = g_renew (IBusProcessKeyEventData,
-+ keys,
-+ num + 2);
-+ keys[num].keyval = keyval;
-+ keys[num].keycode = keycode;
-+ keys[num].state = state;
-+ keys[num + 1].keyval = 0;
-+ keys[num + 1].keycode = 0;
-+ keys[num + 1].state = 0;
-+ g_clear_pointer (&v3, g_variant_unref);
-+ num++;
-+ } else {
-+ failure_id = 5;
-+ }
-+ }
-+ if (num > 0) {
-+ g_hash_table_replace (priv->extension_keybindings,
-+ g_strdup (name),
-+ keys);
-+ } else {
-+ g_hash_table_remove (priv->extension_keybindings, name);
-+ }
-+ g_clear_pointer (&iter2, g_variant_iter_free);
-+ } else {
-+ failure_id = 4;
-+ }
-+ g_clear_pointer (&vkeys, g_variant_unref);
-+ name = NULL;
-+ }
-+ g_variant_iter_free (iter1);
-+ } else {
-+ failure_id = 3;
-+ }
-+ if (failure_id == 0) {
-+ g_dbus_method_invocation_return_value (invocation, NULL);
-+ } else {
-+ g_dbus_method_invocation_return_error (
-+ invocation,
-+ G_DBUS_ERROR,
-+ G_DBUS_ERROR_FAILED,
-+ "PanelExtensionRegisterKeys method gives NULL: %d",
-+ failure_id);
-+ }
-+ if (v2)
-+ g_variant_unref (v2);
-+ if (v1)
-+ g_variant_unref (v1);
-+}
-+
- static void
- ibus_engine_service_method_call (IBusService *service,
- GDBusConnection *connection,
-@@ -964,6 +1084,7 @@ ibus_engine_service_method_call (IBusService *service,
- GDBusMethodInvocation *invocation)
- {
- IBusEngine *engine = IBUS_ENGINE (service);
-+ IBusEnginePrivate *priv = engine->priv;
-
- if (g_strcmp0 (interface_name, IBUS_INTERFACE_ENGINE) != 0) {
- IBUS_SERVICE_CLASS (ibus_engine_parent_class)->
-@@ -1002,6 +1123,33 @@ ibus_engine_service_method_call (IBusService *service,
- g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", retval));
- return;
- }
-+ if (g_strcmp0 (method_name, "PanelExtensionReceived") == 0) {
-+ GVariant *arg0 = NULL;
-+ IBusExtensionEvent *event = NULL;
-+
-+ g_variant_get (parameters, "(v)", &arg0);
-+ if (arg0) {
-+ event = (IBusExtensionEvent *)ibus_serializable_deserialize_object (
-+ arg0);
-+ }
-+ if (!event) {
-+ g_dbus_method_invocation_return_error (
-+ invocation,
-+ G_DBUS_ERROR,
-+ G_DBUS_ERROR_FAILED,
-+ "PanelExtensionReceived method gives NULL");
-+ return;
-+ }
-+ priv->enable_extension = ibus_extension_event_is_enabled (event);
-+ g_dbus_method_invocation_return_value (invocation, NULL);
-+ return;
-+ }
-+ if (g_strcmp0 (method_name, "PanelExtensionRegisterKeys") == 0) {
-+ ibus_engine_service_panel_extension_register_keys (engine,
-+ parameters,
-+ invocation);
-+ return;
-+ }
-
- static const struct {
- gchar *member;
-@@ -1441,73 +1589,10 @@ static void
- ibus_engine_keybinding_free (IBusEngine *engine)
- {
- IBusEnginePrivate *priv;
-- int i;
-
- g_return_if_fail (IBUS_IS_ENGINE (engine));
-
- priv = engine->priv;
-- if (priv->emoji_keybindings) {
-- for (i = 0; priv->emoji_keybindings[i]; i++)
-- g_slice_free (IBusEngineKeybinding, priv->emoji_keybindings[i]);
-- g_clear_pointer (&priv->emoji_keybindings, g_free);
-- }
--}
--
--static IBusEngineKeybinding *
--ibus_engine_keybinding_new (IBusEngine *engine,
-- const gchar *accelerator)
--{
-- guint keyval = 0U;
-- IBusModifierType modifiers = 0;
-- IBusEngineKeybinding *binding = NULL;
--
-- ibus_accelerator_parse (accelerator, &keyval, &modifiers);
-- if (keyval == 0U && modifiers == 0) {
-- g_warning ("Failed to parse shortcut key '%s'", accelerator);
-- return NULL;
-- }
-- if (modifiers & IBUS_SUPER_MASK) {
-- modifiers^=IBUS_SUPER_MASK;
-- modifiers|=IBUS_MOD4_MASK;
-- }
--
-- binding = g_slice_new0 (IBusEngineKeybinding);
-- binding->keyval = keyval;
-- binding->modifiers = modifiers;
-- return binding;
--}
--
--static void
--settings_emoji_hotkey_changed_cb (GSettings *settings,
-- const gchar *key,
-- gpointer data)
--{
-- IBusEngine *engine;
-- IBusEnginePrivate *priv;
-- gchar **accelerators;
-- int i, j, length;
-- g_return_if_fail (IBUS_IS_ENGINE (data));
-- engine = IBUS_ENGINE (data);
-- priv = engine->priv;
--
-- if (g_strcmp0 (key, "hotkey") != 0)
-- return;
-- accelerators = g_settings_get_strv (settings, key);
-- length = g_strv_length (accelerators);
-- ibus_engine_keybinding_free (engine);
-- if (length == 0) {
-- g_strfreev (accelerators);
-- return;
-- }
-- priv->emoji_keybindings = g_new0 (IBusEngineKeybinding*, length + 1);
-- for (i = 0, j = 0; i < length; i++) {
-- IBusEngineKeybinding *binding =
-- ibus_engine_keybinding_new (engine, accelerators[i]);
-- if (!binding)
-- continue;
-- priv->emoji_keybindings[j++] = binding;
-- }
-- g_strfreev (accelerators);
- }
-
- IBusEngine *
-diff --git a/src/ibuspanelservice.c b/src/ibuspanelservice.c
-index f37b91c3..71028ebf 100644
---- a/src/ibuspanelservice.c
-+++ b/src/ibuspanelservice.c
-@@ -57,6 +57,9 @@ enum {
- DESTROY_CONTEXT,
- SET_CONTENT_TYPE,
- PANEL_EXTENSION_RECEIVED,
-+ PROCESS_KEY_EVENT,
-+ COMMIT_TEXT_RECEIVED,
-+ CANDIDATE_CLICKED_LOOKUP_TABLE,
- LAST_SIGNAL,
- };
-
-@@ -153,7 +156,7 @@ static void ibus_panel_service_set_content_type
- guint hints);
- static void ibus_panel_service_panel_extension_received
- (IBusPanelService *panel,
-- GVariant *data);
-+ IBusExtensionEvent *event);
-
- G_DEFINE_TYPE (IBusPanelService, ibus_panel_service, IBUS_TYPE_SERVICE)
-
-@@ -184,6 +187,11 @@ static const gchar introspection_xml[] =
- " <method name='CursorDownLookupTable' />"
- " <method name='PageUpLookupTable' />"
- " <method name='PageDownLookupTable' />"
-+ " <method name='CandidateClickedLookupTable'>"
-+ " <arg direction='in' type='u' name='index' />"
-+ " <arg direction='in' type='u' name='button' />"
-+ " <arg direction='in' type='u' name='state' />"
-+ " </method>"
- " <method name='RegisterProperties'>"
- " <arg direction='in' type='v' name='props' />"
- " </method>"
-@@ -221,7 +229,16 @@ static const gchar introspection_xml[] =
- " <arg direction='in' type='u' name='hints' />"
- " </method>"
- " <method name='PanelExtensionReceived'>"
-- " <arg direction='in' type='v' name='data' />"
-+ " <arg direction='in' type='v' name='event' />"
-+ " </method>"
-+ " <method name='ProcessKeyEvent'>"
-+ " <arg direction='in' type='u' name='keyval' />"
-+ " <arg direction='in' type='u' name='keycode' />"
-+ " <arg direction='in' type='u' name='state' />"
-+ " <arg direction='out' type='b' />"
-+ " </method>"
-+ " <method name='CommitTextReceived'>"
-+ " <arg direction='in' type='v' name='text' />"
- " </method>"
- /* Signals */
- " <signal name='CursorUp' />"
-@@ -247,7 +264,23 @@ static const gchar introspection_xml[] =
- " <arg type='v' name='text' />"
- " </signal>"
- " <signal name='PanelExtension'>"
-+ " <arg type='v' name='event' />"
-+ " </signal>"
-+ " <method name='PanelExtensionRegisterKeys'>"
- " <arg type='v' name='data' />"
-+ " </method>"
-+ " <signal name='UpdatePreeditTextReceived'>"
-+ " <arg type='v' name='text' />"
-+ " <arg type='u' name='cursor_pos' />"
-+ " <arg type='b' name='visible' />"
-+ " </signal>"
-+ " <signal name='UpdateAuxiliaryTextReceived'>"
-+ " <arg type='v' name='text' />"
-+ " <arg type='b' name='visible' />"
-+ " </signal>"
-+ " <signal name='UpdateLookupTableReceived'>"
-+ " <arg type='v' name='table' />"
-+ " <arg type='b' name='visible' />"
- " </signal>"
- " </interface>"
- "</node>";
-@@ -927,10 +960,81 @@ ibus_panel_service_class_init (IBusPanelServiceClass *class)
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (IBusPanelServiceClass, panel_extension_received),
- NULL, NULL,
-- _ibus_marshal_VOID__VARIANT,
-+ _ibus_marshal_VOID__OBJECT,
-+ G_TYPE_NONE,
-+ 1,
-+ IBUS_TYPE_EXTENSION_EVENT);
-+
-+ /**
-+ * IBusPanelService::process-key-event:
-+ * @panel: An #IBusPanelService
-+ * @keyval: Key symbol of the key press.
-+ * @keycode: KeyCode of the key press.
-+ * @state: Key modifier flags.
-+ *
-+ * Emitted when a key event is received.
-+ * Implement the member function IBusPanelServiceClass::process_key_event
-+ * in extended class to receive this signal.
-+ * Both the key symbol and keycode are passed to the member function.
-+ * See ibus_input_context_process_key_event() for further explanation of
-+ * key symbol, keycode and which to use.
-+ *
-+ * Returns: %TRUE for successfully process the key; %FALSE otherwise.
-+ * See also: ibus_input_context_process_key_event().
-+ *
-+ * <note><para>Argument @user_data is ignored in this function.</para>
-+ * </note>
-+ */
-+ panel_signals[PROCESS_KEY_EVENT] =
-+ g_signal_new (I_("process-key-event"),
-+ G_TYPE_FROM_CLASS (gobject_class),
-+ G_SIGNAL_RUN_LAST,
-+ G_STRUCT_OFFSET (IBusPanelServiceClass, process_key_event),
-+ g_signal_accumulator_true_handled, NULL,
-+ _ibus_marshal_BOOL__UINT_UINT_UINT,
-+ G_TYPE_BOOLEAN,
-+ 3,
-+ G_TYPE_UINT,
-+ G_TYPE_UINT,
-+ G_TYPE_UINT);
-+
-+ /**
-+ * IBusPanelService::commit-text-received:
-+ * @panel: An #IBusPanelService
-+ * @text: A #IBusText
-+ *
-+ * Emitted when the client application get the ::commit-text-received.
-+ * Implement the member function
-+ * IBusPanelServiceClass::commit_text_received in extended class to
-+ * receive this signal.
-+ *
-+ * <note><para>Argument @user_data is ignored in this function.</para>
-+ * </note>
-+ */
-+ panel_signals[COMMIT_TEXT_RECEIVED] =
-+ g_signal_new (I_("commit-text-received"),
-+ G_TYPE_FROM_CLASS (gobject_class),
-+ G_SIGNAL_RUN_LAST,
-+ G_STRUCT_OFFSET (IBusPanelServiceClass, commit_text_received),
-+ NULL, NULL,
-+ _ibus_marshal_VOID__OBJECT,
- G_TYPE_NONE,
- 1,
-- G_TYPE_VARIANT);
-+ IBUS_TYPE_TEXT);
-+
-+ panel_signals[CANDIDATE_CLICKED_LOOKUP_TABLE] =
-+ g_signal_new (I_("candidate-clicked-lookup-table"),
-+ G_TYPE_FROM_CLASS (gobject_class),
-+ G_SIGNAL_RUN_LAST,
-+ G_STRUCT_OFFSET (IBusPanelServiceClass,
-+ candidate_clicked_lookup_table),
-+ NULL, NULL,
-+ _ibus_marshal_VOID__UINT_UINT_UINT,
-+ G_TYPE_NONE,
-+ 3,
-+ G_TYPE_UINT,
-+ G_TYPE_UINT,
-+ G_TYPE_UINT);
- }
-
- static void
-@@ -1129,9 +1233,14 @@ ibus_panel_service_service_method_call (IBusService *service,
- }
-
- if (g_strcmp0 (method_name, "PanelExtensionReceived") == 0) {
-- GVariant *variant = NULL;
-- g_variant_get (parameters, "(v)", &variant);
-- if (variant == NULL) {
-+ GVariant *arg0 = NULL;
-+ IBusExtensionEvent *event = NULL;
-+ g_variant_get (parameters, "(v)", &arg0);
-+ if (arg0) {
-+ event = IBUS_EXTENSION_EVENT (ibus_serializable_deserialize (arg0));
-+ g_variant_unref (arg0);
-+ }
-+ if (!event) {
- g_dbus_method_invocation_return_error (
- invocation,
- G_DBUS_ERROR,
-@@ -1140,11 +1249,63 @@ ibus_panel_service_service_method_call (IBusService *service,
- return;
- }
- g_signal_emit (panel, panel_signals[PANEL_EXTENSION_RECEIVED], 0,
-- variant);
-- g_variant_unref (variant);
-+ event);
-+ _g_object_unref_if_floating (event);
- g_dbus_method_invocation_return_value (invocation, NULL);
- return;
- }
-+ if (g_strcmp0 (method_name, "ProcessKeyEvent") == 0) {
-+ guint keyval, keycode, state;
-+ gboolean retval = FALSE;
-+
-+ g_variant_get (parameters, "(uuu)", &keyval, &keycode, &state);
-+ g_signal_emit (panel,
-+ panel_signals[PROCESS_KEY_EVENT],
-+ 0,
-+ keyval,
-+ keycode,
-+ state,
-+ &retval);
-+ g_dbus_method_invocation_return_value (invocation,
-+ g_variant_new ("(b)", retval));
-+ return;
-+ }
-+ if (g_strcmp0 (method_name, "CommitTextReceived") == 0) {
-+ GVariant *arg0 = NULL;
-+ IBusText *text = NULL;
-+
-+ g_variant_get (parameters, "(v)", &arg0);
-+ if (arg0) {
-+ text = (IBusText *) ibus_serializable_deserialize (arg0);
-+ g_variant_unref (arg0);
-+ }
-+ if (!text) {
-+ g_dbus_method_invocation_return_error (
-+ invocation,
-+ G_DBUS_ERROR,
-+ G_DBUS_ERROR_FAILED,
-+ "CommitTextReceived method gives NULL");
-+ return;
-+ }
-+ g_signal_emit (panel,
-+ panel_signals[COMMIT_TEXT_RECEIVED],
-+ 0,
-+ text);
-+ _g_object_unref_if_floating (text);
-+ return;
-+ }
-+ if (g_strcmp0 (method_name, "CandidateClickedLookupTable") == 0) {
-+ guint index = 0;
-+ guint button = 0;
-+ guint state = 0;
-+ g_variant_get (parameters, "(uuu)", &index, &button, &state);
-+ g_signal_emit (panel,
-+ panel_signals[CANDIDATE_CLICKED_LOOKUP_TABLE],
-+ 0,
-+ index, button, state);
-+ return;
-+ }
-+
-
- const static struct {
- const gchar *name;
-@@ -1318,8 +1479,8 @@ ibus_panel_service_set_content_type (IBusPanelService *panel,
- }
-
- static void
--ibus_panel_service_panel_extension_received (IBusPanelService *panel,
-- GVariant *data)
-+ibus_panel_service_panel_extension_received (IBusPanelService *panel,
-+ IBusExtensionEvent *event)
- {
- ibus_panel_service_not_implemented(panel);
- }
-@@ -1396,10 +1557,11 @@ void
- ibus_panel_service_commit_text (IBusPanelService *panel,
- IBusText *text)
- {
-+ GVariant *variant;
- g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
- g_return_if_fail (IBUS_IS_TEXT (text));
-
-- GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)text);
-+ variant = ibus_serializable_serialize ((IBusSerializable *)text);
- ibus_service_emit_signal ((IBusService *) panel,
- NULL,
- IBUS_INTERFACE_PANEL,
-@@ -1413,18 +1575,144 @@ ibus_panel_service_commit_text (IBusPanelService *panel,
- }
-
- void
--ibus_panel_service_panel_extension (IBusPanelService *panel,
-- GVariant *variant)
-+ibus_panel_service_panel_extension (IBusPanelService *panel,
-+ IBusExtensionEvent *event)
- {
-+ GVariant *variant;
- g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
-- g_return_if_fail (variant);
-+ g_return_if_fail (IBUS_IS_EXTENSION_EVENT (event));
-
-+ variant = ibus_serializable_serialize ((IBusSerializable *)event);
- ibus_service_emit_signal ((IBusService *) panel,
- NULL,
- IBUS_INTERFACE_PANEL,
- "PanelExtension",
- g_variant_new ("(v)", variant),
- NULL);
-+
-+ if (g_object_is_floating (event)) {
-+ g_object_unref (event);
-+ }
-+}
-+
-+void
-+ibus_panel_service_panel_extension_register_keys (IBusPanelService *panel,
-+ const gchar
-+ *first_property_name,
-+ ...)
-+{
-+ GVariantBuilder builder;
-+ GVariantBuilder child;
-+ const gchar *name;
-+ va_list var_args;
-+ IBusProcessKeyEventData *keys;
-+
-+ g_return_if_fail (first_property_name);
-+
-+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
-+ name = first_property_name;
-+
-+ va_start (var_args, first_property_name);
-+ do {
-+ keys = va_arg (var_args, IBusProcessKeyEventData *);
-+ g_return_if_fail (keys != NULL);
-+ g_variant_builder_init (&child, G_VARIANT_TYPE ("av"));
-+ for (; keys; keys++) {
-+ if (keys->keyval == 0 && keys->keycode == 0 && keys->state == 0)
-+ break;
-+ g_variant_builder_add (&child, "v",
-+ g_variant_new ("(iii)",
-+ keys->keyval,
-+ keys->keycode,
-+ keys->state));
-+ }
-+ g_variant_builder_add (&builder, "{sv}",
-+ g_strdup (name), g_variant_builder_end (&child));
-+ } while ((name = va_arg (var_args, const gchar *)));
-+ va_end (var_args);
-+
-+ ibus_service_emit_signal ((IBusService *) panel,
-+ NULL,
-+ IBUS_INTERFACE_PANEL,
-+ "PanelExtensionRegisterKeys",
-+ g_variant_new ("(v)",
-+ g_variant_builder_end (&builder)),
-+ NULL);
-+}
-+
-+void
-+ibus_panel_service_update_preedit_text_received (IBusPanelService *panel,
-+ IBusText *text,
-+ guint cursor_pos,
-+ gboolean visible)
-+{
-+ GVariant *variant;
-+
-+ g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
-+ g_return_if_fail (IBUS_IS_TEXT (text));
-+
-+ variant = ibus_serializable_serialize ((IBusSerializable *)text);
-+ g_return_if_fail (variant);
-+ ibus_service_emit_signal ((IBusService *) panel,
-+ NULL,
-+ IBUS_INTERFACE_PANEL,
-+ "UpdatePreeditTextReceived",
-+ g_variant_new ("(vub)",
-+ variant, cursor_pos, visible),
-+ NULL);
-+
-+ if (g_object_is_floating (text)) {
-+ g_object_unref (text);
-+ }
-+}
-+
-+void
-+ibus_panel_service_update_auxiliary_text_received (IBusPanelService *panel,
-+ IBusText *text,
-+ gboolean visible)
-+{
-+ GVariant *variant;
-+ g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
-+ g_return_if_fail (IBUS_IS_TEXT (text));
-+
-+ variant = ibus_serializable_serialize ((IBusSerializable *)text);
-+ g_return_if_fail (variant);
-+ ibus_service_emit_signal ((IBusService *) panel,
-+ NULL,
-+ IBUS_INTERFACE_PANEL,
-+ "UpdateAuxiliaryTextReceived",
-+ g_variant_new ("(vb)",
-+ variant, visible),
-+ NULL);
-+
-+ if (g_object_is_floating (text)) {
-+ g_object_unref (text);
-+ }
-+}
-+
-+void
-+ibus_panel_service_update_lookup_table_received (IBusPanelService *panel,
-+ IBusLookupTable *table,
-+ gboolean visible)
-+{
-+ GVariant *variant;
-+
-+ g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
-+ g_return_if_fail (IBUS_IS_LOOKUP_TABLE (table));
-+
-+ variant = ibus_serializable_serialize ((IBusSerializable *)table);
-+ g_return_if_fail (variant);
-+ ibus_service_emit_signal ((IBusService *) panel,
-+ NULL,
-+ IBUS_INTERFACE_PANEL,
-+ "UpdateLookupTableReceived",
-+ g_variant_new ("(vb)",
-+ variant, visible),
-+ NULL);
-+
-+ if (g_object_is_floating (table)) {
-+ g_object_unref (table);
-+ }
- }
-
- #define DEFINE_FUNC(name, Name) \
-diff --git a/src/ibuspanelservice.h b/src/ibuspanelservice.h
-index 60ef842b..d91f2309 100644
---- a/src/ibuspanelservice.h
-+++ b/src/ibuspanelservice.h
-@@ -38,6 +38,7 @@
- #include "ibuslookuptable.h"
- #include "ibusservice.h"
- #include "ibusproplist.h"
-+#include "ibusxevent.h"
-
- /*
- * Type macros.
-@@ -130,11 +131,24 @@ struct _IBusPanelServiceClass {
- gint h);
- void (* panel_extension_received)
- (IBusPanelService *panel,
-- GVariant *data);
-+ IBusExtensionEvent *event);
-+ gboolean (* process_key_event)
-+ (IBusPanelService *panel,
-+ guint keyval,
-+ guint keycode,
-+ guint state);
-+ void (* commit_text_received)
-+ (IBusPanelService *panel,
-+ IBusText *text);
-+ void (* candidate_clicked_lookup_table)
-+ (IBusPanelService *panel,
-+ guint index,
-+ guint button,
-+ guint state);
-
- /*< private >*/
- /* padding */
-- gpointer pdummy[5]; // We can add 8 pointers without breaking the ABI.
-+ gpointer pdummy[2]; // We can add 8 pointers without breaking the ABI.
- };
-
- GType ibus_panel_service_get_type (void);
-@@ -248,12 +262,105 @@ void ibus_panel_service_commit_text (IBusPanelService *panel,
- /**
- * ibus_panel_service_panel_extension:
- * @panel: An #IBusPanelService
-- * @data: (transfer full): A #GVariant data which is sent to a panel extension.
-+ * @event: (transfer full): A #PanelExtensionEvent which is sent to a
-+ * panel extension.
- *
-+ * Enable or disable a panel extension with #IBusExtensionEvent.
- * Notify that a data is sent
- * by sending a "PanelExtension" message to IBus panel extension service.
- */
--void ibus_panel_service_panel_extension (IBusPanelService *panel,
-- GVariant *data);
-+void ibus_panel_service_panel_extension (IBusPanelService *panel,
-+ IBusExtensionEvent *event);
-+
-+/**
-+ * ibus_panel_service_panel_extension_register_keys:
-+ * @panel: An #IBusPanelService
-+ * @first_property_name: the first name of the shortcut keys. This is %NULL
-+ " terminated.
-+ *
-+ * Register shortcut keys to enable panel extensions with #IBusExtensionEvent.
-+ * Notify that a data is sent
-+ * by sending a "PanelExtensionRegisterKeys" message to IBus panel extension
-+ * service. Seems Vala does not support uint[][3] and use
-+ * IBusProcessKeyEventData[]. E.g.
-+ * IBusProcessKeyEventData[] keys = {{
-+ * IBUS_KEY_e, 0, IBUS_SHIFT_MASK | IBUS_SUPER_MASK }};
-+ * ibus_panel_service_panel_extension_register_keys(panel, "emoji", keys, NULL);
-+ */
-+void ibus_panel_service_panel_extension_register_keys
-+ (IBusPanelService *panel,
-+ const gchar *first_property_name,
-+ ...);
-+
-+/**
-+ * ibus_panel_service_update_preedit_text_received:
-+ * @panel: An #IBusPanelService
-+ * @text: Update content.
-+ * @cursor_pos: Current position of cursor
-+ * @visible: Whether the pre-edit buffer is visible.
-+ *
-+ * Notify that the preedit is updated by the panel extension
-+ *
-+ * (Note: The table object will be released, if it is floating.
-+ * If caller want to keep the object, caller should make the object
-+ * sink by g_object_ref_sink.)
-+ */
-+void ibus_panel_service_update_preedit_text_received
-+ (IBusPanelService *panel,
-+ IBusText *text,
-+ guint cursor_pos,
-+ gboolean visible);
-+
-+/**
-+ * ibus_panel_service_show_preedit_text_received:
-+ * @panel: An IBusPanelService
-+ *
-+ * Notify that the preedit is shown by the panel extension
-+ */
-+void ibus_panel_service_show_preedit_text_received
-+ (IBusPanelService *panel);
-+
-+/**
-+ * ibus_panel_service_hide_preedit_text_received:
-+ * @panel: An IBusPanelService
-+ *
-+ * Notify that the preedit is hidden by the panel extension
-+ */
-+void ibus_panel_service_hide_preedit_text_received
-+ (IBusPanelService *panel);
-+
-+/**
-+ * ibus_panel_service_update_auxiliary_text_received:
-+ * @panel: An #IBusPanelService
-+ * @text: An #IBusText
-+ * @visible: Whether the auxilirary text is visible.
-+ *
-+ * Notify that the auxilirary is updated by the panel extension.
-+ *
-+ * (Note: The table object will be released, if it is floating.
-+ * If caller want to keep the object, caller should make the object
-+ * sink by g_object_ref_sink.)
-+ */
-+void ibus_panel_service_update_auxiliary_text_received
-+ (IBusPanelService *panel,
-+ IBusText *text,
-+ gboolean visible);
-+
-+/**
-+ * ibus_panel_service_update_lookup_table_received:
-+ * @panel: An #IBusPanelService
-+ * @table: An #IBusLookupTable
-+ * @visible: Whether the lookup table is visible.
-+ *
-+ * Notify that the lookup table is updated by the panel extension.
-+ *
-+ * (Note: The table object will be released, if it is floating.
-+ * If caller want to keep the object, caller should make the object
-+ * sink by g_object_ref_sink.)
-+ */
-+void ibus_panel_service_update_lookup_table_received
-+ (IBusPanelService *panel,
-+ IBusLookupTable *table,
-+ gboolean visible);
- G_END_DECLS
- #endif
-diff --git a/src/ibusshare.h b/src/ibusshare.h
-index 757d915b..4f5a306b 100644
---- a/src/ibusshare.h
-+++ b/src/ibusshare.h
-@@ -73,6 +73,15 @@
- */
- #define IBUS_SERVICE_PANEL_EXTENSION "org.freedesktop.IBus.Panel.Extension"
-
-+/**
-+ * IBUS_SERVICE_PANEL_EXTENSION_EMOJI:
-+ *
-+ * Address of IBus panel extension service for emoji.
-+ * This service provides emoji, Unicode code point, Unicode name features.
-+ */
-+#define IBUS_SERVICE_PANEL_EXTENSION_EMOJI \
-+ "org.freedesktop.IBus.Panel.Extension.Emoji"
-+
- /**
- * IBUS_SERVICE_CONFIG:
- *
-@@ -109,11 +118,13 @@
- #define IBUS_PATH_PANEL "/org/freedesktop/IBus/Panel"
-
- /**
-- * IBUS_PATH_PANEL_EXTENSION:
-+ * IBUS_PATH_PANEL_EXTENSION_EMOJI:
- *
-- * D-Bus path for IBus panel.
-+ * D-Bus path for IBus extension panel for emoji.
-+ * This service provides emoji, Unicode code point, Unicode name features.
- */
--#define IBUS_PATH_PANEL_EXTENSION "/org/freedesktop/IBus/Panel/Extension"
-+#define IBUS_PATH_PANEL_EXTENSION_EMOJI \
-+ "/org/freedesktop/IBus/Panel/Extension/Emoji"
-
- /**
- * IBUS_PATH_CONFIG:
-diff --git a/src/ibusxevent.c b/src/ibusxevent.c
-index dea80272..287bb99b 100644
---- a/src/ibusxevent.c
-+++ b/src/ibusxevent.c
-@@ -22,13 +22,23 @@
- #include "ibusinternal.h"
- #include "ibusxevent.h"
-
-+#define IBUS_EXTENSION_EVENT_VERSION 1
-+#define IBUS_EXTENSION_EVENT_GET_PRIVATE(o) \
-+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
-+ IBUS_TYPE_EXTENSION_EVENT, \
-+ IBusExtensionEventPrivate))
-+
- #define IBUS_X_EVENT_VERSION 1
--#define IBUS_X_EVENT_GET_PRIVATE(o) \
-+#define IBUS_X_EVENT_GET_PRIVATE(o) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_X_EVENT, IBusXEventPrivate))
-
- enum {
- PROP_0,
- PROP_VERSION,
-+ PROP_NAME,
-+ PROP_IS_ENABLED,
-+ PROP_IS_EXTENSION,
-+ PROP_PARAMS,
- PROP_EVENT_TYPE,
- PROP_WINDOW,
- PROP_SEND_EVENT,
-@@ -52,6 +62,14 @@ enum {
- };
-
-
-+struct _IBusExtensionEventPrivate {
-+ guint version;
-+ gchar *name;
-+ gboolean is_enabled;
-+ gboolean is_extension;
-+ gchar *params;
-+};
-+
- struct _IBusXEventPrivate {
- guint version;
- guint32 time;
-@@ -73,24 +91,346 @@ struct _IBusXEventPrivate {
- };
-
- /* functions prototype */
--static void ibus_x_event_destroy (IBusXEvent *event);
--static void ibus_x_event_set_property (IBusXEvent *event,
-- guint prop_id,
-- const GValue *value,
-- GParamSpec *pspec);
--static void ibus_x_event_get_property (IBusXEvent *event,
-- guint prop_id,
-- GValue *value,
-- GParamSpec *pspec);
--static gboolean ibus_x_event_serialize (IBusXEvent *event,
-- GVariantBuilder *builder);
--static gint ibus_x_event_deserialize (IBusXEvent *event,
-- GVariant *variant);
--static gboolean ibus_x_event_copy (IBusXEvent *dest,
-- const IBusXEvent *src);
--
-+static void ibus_extension_event_destroy (IBusExtensionEvent *event);
-+static void ibus_extension_event_set_property (IBusExtensionEvent *event,
-+ guint prop_id,
-+ const GValue *value,
-+ GParamSpec *pspec);
-+static void ibus_extension_event_get_property (IBusExtensionEvent *event,
-+ guint prop_id,
-+ GValue *value,
-+ GParamSpec *pspec);
-+static gboolean ibus_extension_event_serialize (IBusExtensionEvent *event,
-+ GVariantBuilder
-+ *builder);
-+static gint ibus_extension_event_deserialize (IBusExtensionEvent *event,
-+ GVariant
-+ *variant);
-+static gboolean ibus_extension_event_copy (IBusExtensionEvent
-+ *dest,
-+ const IBusExtensionEvent
-+ *src);
-+static void ibus_x_event_destroy (IBusXEvent *event);
-+static void ibus_x_event_set_property (IBusXEvent *event,
-+ guint prop_id,
-+ const GValue *value,
-+ GParamSpec *pspec);
-+static void ibus_x_event_get_property (IBusXEvent *event,
-+ guint prop_id,
-+ GValue *value,
-+ GParamSpec *pspec);
-+static gboolean ibus_x_event_serialize (IBusXEvent *event,
-+ GVariantBuilder
-+ *builder);
-+static gint ibus_x_event_deserialize (IBusXEvent *event,
-+ GVariant
-+ *variant);
-+static gboolean ibus_x_event_copy (IBusXEvent *dest,
-+ const IBusXEvent *src);
-+
-+G_DEFINE_TYPE (IBusExtensionEvent, ibus_extension_event, IBUS_TYPE_SERIALIZABLE)
- G_DEFINE_TYPE (IBusXEvent, ibus_x_event, IBUS_TYPE_SERIALIZABLE)
-
-+static void
-+ibus_extension_event_class_init (IBusExtensionEventClass *class)
-+{
-+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
-+ IBusObjectClass *object_class = IBUS_OBJECT_CLASS (class);
-+ IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (class);
-+
-+ gobject_class->set_property =
-+ (GObjectSetPropertyFunc) ibus_extension_event_set_property;
-+ gobject_class->get_property =
-+ (GObjectGetPropertyFunc) ibus_extension_event_get_property;
-+
-+ object_class->destroy =
-+ (IBusObjectDestroyFunc) ibus_extension_event_destroy;
-+
-+ serializable_class->serialize =
-+ (IBusSerializableSerializeFunc) ibus_extension_event_serialize;
-+ serializable_class->deserialize =
-+ (IBusSerializableDeserializeFunc) ibus_extension_event_deserialize;
-+ serializable_class->copy =
-+ (IBusSerializableCopyFunc) ibus_extension_event_copy;
-+
-+ /* install properties */
-+ /**
-+ * IBusExtensionEvent:version:
-+ *
-+ * Version of the #IBusExtensionEvent.
-+ */
-+ g_object_class_install_property (gobject_class,
-+ PROP_VERSION,
-+ g_param_spec_uint ("version",
-+ "version",
-+ "version",
-+ 0,
-+ G_MAXUINT32,
-+ IBUS_EXTENSION_EVENT_VERSION,
-+ G_PARAM_READABLE));
-+
-+ /**
-+ * IBusExtensionEvent:name:
-+ *
-+ * Name of the extension in the #IBusExtensionEvent.
-+ */
-+ g_object_class_install_property (gobject_class,
-+ PROP_NAME,
-+ g_param_spec_string ("name",
-+ "name",
-+ "name of the extension",
-+ "",
-+ G_PARAM_READWRITE |
-+ G_PARAM_CONSTRUCT_ONLY));
-+
-+ /**
-+ * IBusExtensionEvent:is-enabled:
-+ *
-+ * %TRUE if the extension is enabled in the #IBusExtensionEvent.
-+ */
-+ g_object_class_install_property (gobject_class,
-+ PROP_IS_ENABLED,
-+ g_param_spec_boolean ("is-enabled",
-+ "is enabled",
-+ "if the extension is enabled",
-+ FALSE,
-+ G_PARAM_READWRITE |
-+ G_PARAM_CONSTRUCT_ONLY));
-+
-+ /**
-+ * IBusExtensionEvent:is-extension:
-+ *
-+ * %TRUE if the #IBusExtensionEvent is called by an extension.
-+ * %FALSE if the #IBusExtensionEvent is called by an active engine or
-+ * panel.
-+ * If this value is %TRUE, the event is send to ibus-daemon, an active
-+ * engine. If it's %FALSE, the event is sned to ibus-daemon, panels.
-+ */
-+ g_object_class_install_property (gobject_class,
-+ PROP_IS_EXTENSION,
-+ g_param_spec_boolean ("is-extension",
-+ "is extension",
-+ "if the event is called by an extension",
-+ FALSE,
-+ G_PARAM_READWRITE |
-+ G_PARAM_CONSTRUCT_ONLY));
-+
-+ /**
-+ * IBusExtensionEvent:params:
-+ *
-+ * Parameters to enable the extension in the #IBusExtensionEvent.
-+ */
-+ g_object_class_install_property (gobject_class,
-+ PROP_PARAMS,
-+ g_param_spec_string ("params",
-+ "params",
-+ "Parameters to enable the extension",
-+ "",
-+ G_PARAM_READWRITE |
-+ G_PARAM_CONSTRUCT_ONLY));
-+
-+ g_type_class_add_private (class, sizeof (IBusExtensionEventPrivate));
-+}
-+
-+static void
-+ibus_extension_event_init (IBusExtensionEvent *event)
-+{
-+ event->priv = IBUS_EXTENSION_EVENT_GET_PRIVATE (event);
-+ event->priv->version = IBUS_EXTENSION_EVENT_VERSION;
-+}
-+
-+static void
-+ibus_extension_event_destroy (IBusExtensionEvent *event)
-+{
-+ g_clear_pointer (&event->priv->name, g_free);
-+
-+ IBUS_OBJECT_CLASS(ibus_extension_event_parent_class)->
-+ destroy (IBUS_OBJECT (event));
-+}
-+
-+static void
-+ibus_extension_event_set_property (IBusExtensionEvent *event,
-+ guint prop_id,
-+ const GValue *value,
-+ GParamSpec *pspec)
-+{
-+ IBusExtensionEventPrivate *priv = event->priv;
-+
-+ switch (prop_id) {
-+ case PROP_NAME:
-+ g_free (priv->name);
-+ priv->name = g_value_dup_string (value);
-+ break;
-+ case PROP_IS_ENABLED:
-+ priv->is_enabled = g_value_get_boolean (value);
-+ break;
-+ case PROP_IS_EXTENSION:
-+ priv->is_extension = g_value_get_boolean (value);
-+ break;
-+ case PROP_PARAMS:
-+ priv->params = g_value_dup_string (value);
-+ break;
-+ default:
-+ G_OBJECT_WARN_INVALID_PROPERTY_ID (event, prop_id, pspec);
-+ }
-+}
-+
-+static void
-+ibus_extension_event_get_property (IBusExtensionEvent *event,
-+ guint prop_id,
-+ GValue *value,
-+ GParamSpec *pspec)
-+{
-+ IBusExtensionEventPrivate *priv = event->priv;
-+ switch (prop_id) {
-+ case PROP_VERSION:
-+ g_value_set_uint (value, priv->version);
-+ break;
-+ case PROP_NAME:
-+ g_value_set_string (value, priv->name);
-+ break;
-+ case PROP_IS_ENABLED:
-+ g_value_set_boolean (value, priv->is_enabled);
-+ break;
-+ case PROP_IS_EXTENSION:
-+ g_value_set_boolean (value, priv->is_extension);
-+ break;
-+ case PROP_PARAMS:
-+ g_value_set_string (value, priv->params);
-+ break;
-+ default:
-+ G_OBJECT_WARN_INVALID_PROPERTY_ID (event, prop_id, pspec);
-+ }
-+}
-+
-+static gboolean
-+ibus_extension_event_serialize (IBusExtensionEvent *event,
-+ GVariantBuilder *builder)
-+{
-+ gboolean retval;
-+ IBusExtensionEventPrivate *priv;
-+
-+ retval = IBUS_SERIALIZABLE_CLASS (ibus_extension_event_parent_class)->
-+ serialize ((IBusSerializable *)event, builder);
-+ g_return_val_if_fail (retval, FALSE);
-+ /* End dict iter */
-+
-+ priv = event->priv;
-+#define NOTNULL(s) ((s) != NULL ? (s) : "")
-+ /* If you will add a new property, you can append it at the end and
-+ * you should not change the serialized order of name, longname,
-+ * description, ... because the order is also used in other applications
-+ * likes ibus-qt. */
-+ g_variant_builder_add (builder, "u", priv->version);
-+ g_variant_builder_add (builder, "s", NOTNULL (priv->name));
-+ g_variant_builder_add (builder, "b", priv->is_enabled);
-+ g_variant_builder_add (builder, "b", priv->is_extension);
-+ g_variant_builder_add (builder, "s", NOTNULL (priv->params));
-+#undef NOTNULL
-+
-+ return TRUE;
-+}
-+
-+static gint
-+ibus_extension_event_deserialize (IBusExtensionEvent *event,
-+ GVariant *variant)
-+{
-+ gint retval;
-+ IBusExtensionEventPrivate *priv;
-+
-+ retval = IBUS_SERIALIZABLE_CLASS (ibus_extension_event_parent_class)->
-+ deserialize ((IBusSerializable *)event, variant);
-+ g_return_val_if_fail (retval, 0);
-+
-+ priv = event->priv;
-+ /* If you will add a new property, you can append it at the end and
-+ * you should not change the serialized order of name, longname,
-+ * description, ... because the order is also used in other applications
-+ * likes ibus-qt. */
-+ g_variant_get_child (variant, retval++, "u", &priv->version);
-+ ibus_g_variant_get_child_string (variant, retval++,
-+ &priv->name);
-+ g_variant_get_child (variant, retval++, "b", &priv->is_enabled);
-+ g_variant_get_child (variant, retval++, "b", &priv->is_extension);
-+ ibus_g_variant_get_child_string (variant, retval++,
-+ &priv->params);
-+
-+ return retval;
-+}
-+
-+static gboolean
-+ibus_extension_event_copy (IBusExtensionEvent *dest,
-+ const IBusExtensionEvent *src)
-+{
-+ gboolean retval;
-+ IBusExtensionEventPrivate *dest_priv = dest->priv;
-+ IBusExtensionEventPrivate *src_priv = src->priv;
-+
-+ retval = IBUS_SERIALIZABLE_CLASS (ibus_extension_event_parent_class)->
-+ copy ((IBusSerializable *)dest, (IBusSerializable *)src);
-+ g_return_val_if_fail (retval, FALSE);
-+
-+ dest_priv->version = src_priv->version;
-+ dest_priv->name = g_strdup (src_priv->name);
-+ dest_priv->is_enabled = src_priv->is_enabled;
-+ dest_priv->is_extension = src_priv->is_extension;
-+ dest_priv->params = g_strdup (src_priv->params);
-+ return TRUE;
-+}
-+
-+IBusExtensionEvent *
-+ibus_extension_event_new (const gchar *first_property_name,
-+ ...)
-+{
-+ va_list var_args;
-+ IBusExtensionEvent *event;
-+
-+ va_start (var_args, first_property_name);
-+ event = (IBusExtensionEvent *) g_object_new_valist (
-+ IBUS_TYPE_EXTENSION_EVENT,
-+ first_property_name,
-+ var_args);
-+ va_end (var_args);
-+ g_assert (event->priv->version != 0);
-+ return event;
-+}
-+
-+guint
-+ibus_extension_event_get_version (IBusExtensionEvent *event)
-+{
-+ g_return_val_if_fail (IBUS_IS_EXTENSION_EVENT (event), 0);
-+ return event->priv->version;
-+}
-+
-+const gchar *
-+ibus_extension_event_get_name (IBusExtensionEvent *event)
-+{
-+ g_return_val_if_fail (IBUS_IS_EXTENSION_EVENT (event), "");
-+ return event->priv->name;
-+}
-+
-+gboolean
-+ibus_extension_event_is_enabled (IBusExtensionEvent *event)
-+{
-+ g_return_val_if_fail (IBUS_IS_EXTENSION_EVENT (event), FALSE);
-+ return event->priv->is_enabled;
-+}
-+
-+gboolean
-+ibus_extension_event_is_extension (IBusExtensionEvent *event)
-+{
-+ g_return_val_if_fail (IBUS_IS_EXTENSION_EVENT (event), FALSE);
-+ return event->priv->is_extension;
-+}
-+
-+const gchar *
-+ibus_extension_event_get_params (IBusExtensionEvent *event)
-+{
-+ g_return_val_if_fail (IBUS_IS_EXTENSION_EVENT (event), "");
-+ return event->priv->params;
-+}
-+
-+
- static void
- ibus_x_event_class_init (IBusXEventClass *class)
- {
-@@ -454,6 +794,7 @@ static void
- ibus_x_event_destroy (IBusXEvent *event)
- {
- g_clear_pointer (&event->priv->string, g_free);
-+ g_clear_pointer (&event->priv->purpose, g_free);
-
- IBUS_OBJECT_CLASS(ibus_x_event_parent_class)->destroy (IBUS_OBJECT (event));
- }
-diff --git a/src/ibusxevent.h b/src/ibusxevent.h
-index f35f14e4..d44cc8f4 100644
---- a/src/ibusxevent.h
-+++ b/src/ibusxevent.h
-@@ -29,8 +29,8 @@
-
- /**
- * SECTION: ibusxevent
-- * @short_description: XEvent wrapper object
-- * @title: IBusXEvent
-+ * @short_description: Extension Event wrapper object
-+ * @title: IBusExtensionEvent
- * @stability: Unstable
- *
- * An IBusXEvent provides a wrapper of XEvent.
-@@ -45,25 +45,150 @@
- */
-
- /* define GOBJECT macros */
--#define IBUS_TYPE_X_EVENT \
-+#define IBUS_TYPE_EXTENSION_EVENT \
-+ (ibus_extension_event_get_type ())
-+#define IBUS_EXTENSION_EVENT(obj) \
-+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-+ IBUS_TYPE_EXTENSION_EVENT, \
-+ IBusExtensionEvent))
-+#define IBUS_EXTENSION_EVENT_CLASS(klass) \
-+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
-+ IBUS_TYPE_EXTENSION_EVENT, \
-+ IBusExtensionEventClass))
-+#define IBUS_IS_EXTENSION_EVENT(obj) \
-+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_EXTENSION_EVENT))
-+#define IBUS_IS_EXTENSION_EVENT_CLASS(klass) \
-+ (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_EXTENSION_EVENT))
-+#define IBUS_EXTENSION_EVENT_GET_CLASS(obj) \
-+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-+ IBUS_TYPE_EXTENSION_EVENT, \
-+ IBusExtensionEventClass))
-+
-+#define IBUS_TYPE_X_EVENT \
- (ibus_x_event_get_type ())
--#define IBUS_X_EVENT(obj) \
-+#define IBUS_X_EVENT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_X_EVENT, IBusXEvent))
--#define IBUS_X_EVENT_CLASS(klass) \
-+#define IBUS_X_EVENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_X_EVENT, IBusXEventClass))
--#define IBUS_IS_X_EVENT(obj) \
-+#define IBUS_IS_X_EVENT(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_X_EVENT))
--#define IBUS_IS_X_EVENT_CLASS(klass) \
-+#define IBUS_IS_X_EVENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_X_EVENT))
--#define IBUS_X_EVENT_GET_CLASS(obj) \
-+#define IBUS_X_EVENT_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_X_EVENT, IBusXEventClass))
-
- G_BEGIN_DECLS
-
-+typedef struct _IBusProcessKeyEventData IBusProcessKeyEventData;
-+typedef struct _IBusExtensionEvent IBusExtensionEvent;
-+typedef struct _IBusExtensionEventClass IBusExtensionEventClass;
-+typedef struct _IBusExtensionEventPrivate IBusExtensionEventPrivate;
- typedef struct _IBusXEvent IBusXEvent;
- typedef struct _IBusXEventClass IBusXEventClass;
- typedef struct _IBusXEventPrivate IBusXEventPrivate;
-
-+/**
-+ * IBusProcessKeyEventData:
-+ *
-+ * IBuProcessKeyEventData properties.
-+ */
-+struct _IBusProcessKeyEventData {
-+ /*< public >*/
-+ guint keyval;
-+ guint keycode;
-+ guint state;
-+};
-+
-+/**
-+ * IBusExtensionEvent:
-+ *
-+ * IBusExtensionEvent properties.
-+ */
-+struct _IBusExtensionEvent {
-+ /*< private >*/
-+ IBusSerializable parent;
-+ IBusExtensionEventPrivate *priv;
-+
-+ /* instance members */
-+ /*< public >*/
-+};
-+
-+struct _IBusExtensionEventClass {
-+ /*< private >*/
-+ IBusSerializableClass parent;
-+
-+ /* class members */
-+ /*< public >*/
-+
-+ /*< private >*/
-+ /* padding */
-+ gpointer pdummy[10];
-+};
-+
-+
-+GType ibus_extension_event_get_type (void);
-+
-+/**
-+ * ibus_extension_event_new:
-+ * @first_property_name: Name of the first property.
-+ * @...: the NULL-terminated arguments of the properties and values.
-+ *
-+ * Create a new #IBusExtensionEvent.
-+ *
-+ * Returns: A newly allocated #IBusExtensionEvent. E.g.
-+ * ibus_extension_event_new ("name", "emoji", "is-enabled", TRUE, NULL);
-+ */
-+IBusExtensionEvent *ibus_extension_event_new (const gchar
-+ *first_property_name,
-+ ...);
-+
-+/**
-+ * ibus_extension_event_get_version:
-+ * @event: An #IBusExtensionEvent.
-+ *
-+ * Returns: Version of #IBusExtensionEvent
-+ */
-+guint ibus_extension_event_get_version (IBusExtensionEvent *event);
-+
-+/**
-+ * ibus_extension_event_get_purpose:
-+ * @event: An #IBusExtensionEvent.
-+ *
-+ * Returns: name of the extension for #IBusXEvent
-+ */
-+const gchar * ibus_extension_event_get_name (IBusExtensionEvent *event);
-+
-+/**
-+ * ibus_extension_event_is_enabled:
-+ * @event: An #IBusExtensionEvent.
-+ *
-+ * Returns: %TRUE if the extension is enabled for #IBusExtensionEvent
-+ */
-+gboolean ibus_extension_event_is_enabled (IBusExtensionEvent *event);
-+
-+/**
-+ * ibus_extension_event_is_extension:
-+ * @event: An #IBusExtensionEvent.
-+ *
-+ * Returns: %TRUE if the #IBusExtensionEvent is called by an extension.
-+ * %FALSE if the #IBusExtensionEvent is called by an active engine or
-+ * panel.
-+ * If this value is %TRUE, the event is send to ibus-daemon, an active
-+ * engine. If it's %FALSE, the event is sned to ibus-daemon, panels.
-+ */
-+gboolean ibus_extension_event_is_extension
-+ (IBusExtensionEvent *event);
-+
-+/**
-+ * ibus_extension_event_get_params:
-+ * @event: An #IBusExtensionEvent.
-+ *
-+ * Returns: Parameters to enable the extension for #IBusXEvent
-+ */
-+const gchar * ibus_extension_event_get_params (IBusExtensionEvent *event);
-+
-+
-+
- typedef enum {
- IBUS_X_EVENT_NOTHING = -1,
- IBUS_X_EVENT_KEY_PRESS = 0,
-@@ -76,7 +201,7 @@ typedef enum {
- * IBusXEvent:
- * @type: event type
- *
-- * IBusEngine properties.
-+ * IBusXEvent properties.
- */
- struct _IBusXEvent {
- /*< private >*/
-diff --git a/ui/gtk3/Makefile.am b/ui/gtk3/Makefile.am
-index bf9f98d7..aaba7a4d 100644
---- a/ui/gtk3/Makefile.am
-+++ b/ui/gtk3/Makefile.am
-@@ -78,6 +78,7 @@ AM_VALAFLAGS = \
- --pkg=ibus-1.0 \
- --pkg=config \
- --pkg=xi \
-+ --pkg=gdk-wayland \
- --target-glib="$(VALA_TARGET_GLIB_VERSION)" \
- $(NULL)
-
-@@ -176,6 +177,7 @@ ibus_ui_emojier_VALASOURCES = \
- emojier.vala \
- iconwidget.vala \
- separator.vala \
-+ pango.vala \
- $(NULL)
- ibus_ui_emojier_SOURCES = \
- $(ibus_ui_emojier_VALASOURCES:.vala=.c) \
-@@ -213,6 +215,7 @@ ibus_extension_gtk3_VALASOURCES = \
- iconwidget.vala \
- keybindingmanager.vala \
- panelbinding.vala \
-+ pango.vala \
- $(NULL)
- ibus_extension_gtk3_SOURCES = \
- $(ibus_extension_gtk3_VALASOURCES:.vala=.c) \
-diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala
-index 0c0865f1..cd98c9d7 100644
---- a/ui/gtk3/emojier.vala
-+++ b/ui/gtk3/emojier.vala
-@@ -226,43 +226,6 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- }
- }
- }
-- private class ETitleLabelBox : Gtk.HeaderBar {
-- private Gtk.Label m_lang_label;
-- private Gtk.Label m_title_label;
--
-- public ETitleLabelBox(string title) {
-- GLib.Object(
-- name : "IBusEmojierTitleLabelBox",
-- show_close_button: true,
-- decoration_layout: ":close",
-- title: title
-- );
-- var vbox = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
-- set_custom_title(vbox);
-- m_title_label = new Gtk.Label(title);
-- m_title_label.get_style_context().add_class(Gtk.STYLE_CLASS_TITLE);
-- vbox.pack_start(m_title_label, true, false, 0);
-- m_lang_label = new Gtk.Label(null);
-- m_lang_label.get_style_context().add_class(
-- Gtk.STYLE_CLASS_SUBTITLE);
-- vbox.pack_start(m_lang_label, true, false, 0);
--
-- var menu = new GLib.Menu();
-- menu.append(_("Show emoji variants"), "win.variant");
-- var menu_button = new Gtk.MenuButton();
-- menu_button.set_direction(Gtk.ArrowType.NONE);
-- menu_button.set_valign(Gtk.Align.CENTER);
-- menu_button.set_menu_model(menu);
-- menu_button.set_tooltip_text(_("Menu"));
-- pack_end(menu_button);
-- }
-- public new void set_title(string title) {
-- m_title_label.set_text(title);
-- }
-- public void set_lang_label(string str) {
-- m_lang_label.set_text(str);
-- }
-- }
- private class LoadProgressObject : GLib.Object {
- public LoadProgressObject() {
- }
-@@ -275,6 +238,8 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- BACKWARD,
- }
-
-+ public const uint BUTTON_CLOSE_BUTTON = 1000;
-+
- private const uint EMOJI_GRID_PAGE = 10;
- private const string EMOJI_CATEGORY_FAVORITES = N_("Favorites");
- private const string EMOJI_CATEGORY_OTHERS = N_("Others");
-@@ -313,11 +278,19 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- private static bool m_show_unicode = false;
- private static LoadProgressObject m_unicode_progress_object;
- private static bool m_loaded_unicode = false;
-+ private static string m_warning_message = "";
-
- private ThemedRGBA m_rgba;
- private Gtk.Box m_vbox;
-- private ETitleLabelBox m_title;
- private EEntry m_entry;
-+ /* If emojier is emoji category list or Unicode category list,
-+ * m_annotation is "" and preedit is also "".
-+ * If emojier is candidate mode, m_annotation is an annotation and
-+ * get_current_candidate() returns the current emoji.
-+ * But the current preedit can be "" in candidate mode in case that
-+ * Unicode candidate window has U+0000.
-+ */
-+ private string m_annotation = "";
- private string? m_backward;
- private int m_backward_index = -1;
- private EScrolledWindow? m_scrolled_window = null;
-@@ -326,8 +299,20 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- private string m_input_context_path = "";
- private GLib.MainLoop? m_loop;
- private string? m_result;
-- private string? m_unicode_point = null;
-+ /* If m_candidate_panel_is_visible is true, emojier is candidate mode and
-+ * the emoji lookup window is visible.
-+ * If m_candidate_panel_is_visible is false, the emoji lookup window is
-+ * not visible but the mode is not clear.
-+ */
- private bool m_candidate_panel_is_visible;
-+ /* If m_candidate_panel_mode is true, emojier is candidate mode and
-+ * it does not depend on whether the window is visible or not.
-+ * I.E. the first candidate does not show the lookup window and the
-+ * second one shows the window.
-+ * If m_candidate_panel_mode is false, emojier is emoji category list or
-+ * Unicode category list.
-+ */
-+ private bool m_candidate_panel_mode;
- private int m_category_active_index = -1;
- private IBus.LookupTable m_lookup_table;
- private Gtk.Label[] m_candidates;
-@@ -337,23 +322,18 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- protected static double m_mouse_x;
- protected static double m_mouse_y;
- private Gtk.ProgressBar m_unicode_progress_bar;
-+ private uint m_unicode_progress_id;
- private Gtk.Label m_unicode_percent_label;
- private double m_unicode_percent;
-+ private Gdk.Rectangle m_cursor_location;
-+ private bool m_is_up_side_down = false;
-+ private uint m_redraw_window_id;
-
- public signal void candidate_clicked(uint index, uint button, uint state);
-
- public IBusEmojier() {
- GLib.Object(
-- type : Gtk.WindowType.TOPLEVEL,
-- events : Gdk.EventMask.KEY_PRESS_MASK |
-- Gdk.EventMask.KEY_RELEASE_MASK |
-- Gdk.EventMask.BUTTON_PRESS_MASK |
-- Gdk.EventMask.BUTTON_RELEASE_MASK,
-- window_position : Gtk.WindowPosition.CENTER,
-- icon_name: "ibus-setup",
-- accept_focus : true,
-- resizable : true,
-- focus_visible : true
-+ type : Gtk.WindowType.POPUP
- );
-
- // GLib.ActionEntry accepts const variables only.
-@@ -363,6 +343,9 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- new GLib.Variant.boolean(m_show_emoji_variant));
- action.activate.connect(check_action_variant_cb);
- add_action(action);
-+ action = new GLib.SimpleAction("close", null);
-+ action.activate.connect(action_close_cb);
-+ add_action(action);
- if (m_current_lang_id == null)
- m_current_lang_id = "en";
- if (m_emoji_font_family == null)
-@@ -448,14 +431,12 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- css_provider,
- Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
-
-- m_title = new ETitleLabelBox(_("Emoji Choice"));
-- set_titlebar(m_title);
- m_vbox = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
- add(m_vbox);
-
- m_entry = new EEntry();
- m_entry.set_placeholder_text(_("Type annotation or choose emoji"));
-- m_vbox.add(m_entry);
-+ //m_vbox.add(m_entry);
- m_entry.changed.connect(() => {
- update_candidate_window();
- });
-@@ -480,10 +461,16 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- m_loop.quit();
- });
-
-+ size_allocate.connect((w, a) => {
-+ adjust_window_position();
-+ });
-+
- candidate_clicked.connect((i, b, s) => {
-- candidate_panel_select_index(i);
-+ if (m_input_context_path != "")
-+ candidate_panel_select_index(i, b);
- });
-
-+
- if (m_annotation_to_emojis_dict == null) {
- reload_emoji_dict();
- }
-@@ -814,6 +801,12 @@ public class IBusEmojier : Gtk.ApplicationWindow {
-
-
- private void remove_all_children() {
-+ if (m_list_box != null) {
-+ foreach (Gtk.Widget w in m_list_box.get_children()) {
-+ w.destroy();
-+ }
-+ m_list_box = null;
-+ }
- foreach (Gtk.Widget w in m_vbox.get_children()) {
- if (w.name == "IBusEmojierEntry" ||
- w.name == "IBusEmojierTitleLabelBox") {
-@@ -824,15 +817,40 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- }
-
-
-+ private void clamp_page() {
-+ Gtk.ListBoxRow row;
-+ if (m_category_active_index >= 0) {
-+ row = m_list_box.get_row_at_index(m_category_active_index);
-+ m_list_box.select_row(row);
-+ } else {
-+ row = m_list_box.get_row_at_index(0);
-+ }
-+ Gtk.Allocation alloc = { 0, 0, 0, 0 };
-+ row.get_allocation(out alloc);
-+ var adjustment = m_scrolled_window.get_vadjustment();
-+ adjustment.clamp_page(alloc.y, alloc.y + alloc.height);
-+ return_val_if_fail(m_category_active_index >= 0, false);
-+ m_lookup_table.set_cursor_pos((uint)m_category_active_index);
-+ }
-+
-+
- private void show_category_list() {
-+ // Do not call remove_all_children() to work adjustment.clamp_page()
-+ // with PageUp/Down.
-+ // After show_candidate_panel() is called, m_category_active_index
-+ // is saved for Escape key but m_list_box is null by
-+ // remove_all_children().
-+ if (m_category_active_index >= 0 && m_list_box != null) {
-+ var row = m_list_box.get_row_at_index(m_category_active_index);
-+ m_list_box.select_row(row);
-+ return;
-+ }
-+ if (m_category_active_index < 0)
-+ m_category_active_index = 0;
- remove_all_children();
- m_scrolled_window = new EScrolledWindow();
- set_fixed_size();
-
-- m_title.set_title(_("Emoji Choice"));
-- string language =
-- IBus.get_language_name(m_current_lang_id);
-- m_title.set_lang_label(language);
- m_vbox.add(m_scrolled_window);
- Gtk.Viewport viewport = new Gtk.Viewport(null, null);
- m_scrolled_window.add(viewport);
-@@ -842,53 +860,21 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- Gtk.Adjustment adjustment = m_scrolled_window.get_vadjustment();
- m_list_box.set_adjustment(adjustment);
- m_list_box.row_activated.connect((box, gtkrow) => {
-- m_category_active_index = -1;
-+ m_category_active_index = gtkrow.get_index();
- EBoxRow row = gtkrow as EBoxRow;
- show_emoji_for_category(row.text);
-+ show_all();
- });
-
-- uint n = 0;
-- if (m_favorites.length > 0) {
-- EBoxRow row = new EBoxRow(EMOJI_CATEGORY_FAVORITES);
-- EPaddedLabelBox widget =
-- new EPaddedLabelBox(_(EMOJI_CATEGORY_FAVORITES),
-- Gtk.Align.CENTER);
-- row.add(widget);
-- m_list_box.add(row);
-- if (n++ == m_category_active_index)
-- m_list_box.select_row(row);
-- }
-- GLib.List<unowned string> categories =
-- m_category_to_emojis_dict.get_keys();
-- // FIXME: How to cast GLib.CompareFunc<string> to strcmp?
-- categories.sort((a, b) => {
-- if (a == EMOJI_CATEGORY_OTHERS && b != EMOJI_CATEGORY_OTHERS)
-- return 1;
-- else if (a != EMOJI_CATEGORY_OTHERS && b == EMOJI_CATEGORY_OTHERS)
-- return -1;
-- return GLib.strcmp(_(a), _(b));
-- });
-- foreach (unowned string category in categories) {
-- // "Others" category includes next unicode chars and fonts do not support
-- // the base and varints yet.
-- if (category == EMOJI_CATEGORY_OTHERS)
-- continue;
-+ uint ncandidates = m_lookup_table.get_number_of_candidates();
-+ for (uint i = 0; i < ncandidates; i++) {
-+ string category = m_lookup_table.get_candidate(i).text;
- EBoxRow row = new EBoxRow(category);
- EPaddedLabelBox widget =
- new EPaddedLabelBox(_(category), Gtk.Align.CENTER);
- row.add(widget);
- m_list_box.add(row);
-- if (n++ == m_category_active_index)
-- m_list_box.select_row(row);
-- }
-- if (m_unicode_block_list.length() > 0) {
-- EBoxRow row = new EBoxRow(EMOJI_CATEGORY_UNICODE);
-- EPaddedLabelBox widget =
-- new EPaddedLabelBox(_(EMOJI_CATEGORY_UNICODE),
-- Gtk.Align.CENTER);
-- row.add(widget);
-- m_list_box.add(row);
-- if (n++ == m_category_active_index)
-+ if (i == m_category_active_index)
- m_list_box.select_row(row);
- }
-
-@@ -903,6 +889,7 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- private void show_emoji_for_category(string category) {
- if (category == EMOJI_CATEGORY_FAVORITES) {
- m_lookup_table.clear();
-+ m_candidate_panel_mode = true;
- foreach (unowned string favorate in m_favorites) {
- IBus.Text text = new IBus.Text.from_string(favorate);
- m_lookup_table.append_candidate(text);
-@@ -911,25 +898,26 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- } else if (category == EMOJI_CATEGORY_UNICODE) {
- m_category_active_index = -1;
- m_show_unicode = true;
-- show_unicode_blocks();
-+ update_unicode_blocks();
- return;
- } else {
- unowned GLib.SList<unowned string> emojis =
- m_category_to_emojis_dict.lookup(category);
- m_lookup_table.clear();
-+ m_candidate_panel_mode = true;
- foreach (unowned string emoji in emojis) {
- IBus.Text text = new IBus.Text.from_string(emoji);
- m_lookup_table.append_candidate(text);
- }
- m_backward = category;
- }
-+ m_annotation = m_lookup_table.get_candidate(0).text;
- // Restore the cursor position before the special table of
- // emoji variants is shown.
- if (m_backward_index >= 0) {
- m_lookup_table.set_cursor_pos((uint)m_backward_index);
- m_backward_index = -1;
- }
-- show_candidate_panel();
- }
-
-
-@@ -940,18 +928,28 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- IBus.Text text = new IBus.Text.from_string(emoji);
- m_lookup_table.append_candidate(text);
- }
-- show_candidate_panel();
- }
-
-
- private void show_unicode_blocks() {
-+ // Do not call remove_all_children() to work adjustment.clamp_page()
-+ // with PageUp/Down.
-+ // After show_candidate_panel() is called, m_category_active_index
-+ // is saved for Escape key but m_list_box is null by
-+ // remove_all_children().
-+ if (m_category_active_index >= 0 && m_list_box != null) {
-+ var row = m_list_box.get_row_at_index(m_category_active_index);
-+ m_list_box.select_row(row);
-+ return;
-+ }
-+ if (m_category_active_index < 0)
-+ m_category_active_index = 0;
- m_show_unicode = true;
- if (m_default_window_width == 0 && m_default_window_height == 0)
- get_size(out m_default_window_width, out m_default_window_height);
- remove_all_children();
- set_fixed_size();
-
-- m_title.set_title(_("Unicode Choice"));
- EPaddedLabelBox label =
- new EPaddedLabelBox(_("Bring back emoji choice"),
- Gtk.Align.CENTER,
-@@ -964,10 +962,10 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- m_category_active_index = -1;
- m_show_unicode = false;
- hide_candidate_panel();
-+ show_all();
- return true;
- });
- m_scrolled_window = new EScrolledWindow();
-- m_title.set_lang_label("");
- m_vbox.add(m_scrolled_window);
- Gtk.Viewport viewport = new Gtk.Viewport(null, null);
- m_scrolled_window.add(viewport);
-@@ -977,9 +975,10 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- Gtk.Adjustment adjustment = m_scrolled_window.get_vadjustment();
- m_list_box.set_adjustment(adjustment);
- m_list_box.row_activated.connect((box, gtkrow) => {
-- m_category_active_index = -1;
-+ m_category_active_index = gtkrow.get_index();
- EBoxRow row = gtkrow as EBoxRow;
- show_unicode_for_block(row.text);
-+ show_candidate_panel();
- });
-
- uint n = 0;
-@@ -1007,44 +1006,18 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- m_list_box.unselect_all();
- m_list_box.invalidate_filter();
- m_list_box.set_selection_mode(Gtk.SelectionMode.SINGLE);
-+ Gtk.ListBoxRow row = m_list_box.get_row_at_index((int)n - 1);
-+
-+ // If clamp_page() would be called without the allocation signal,
-+ // the jumping page could be failed when returns from
-+ // show_unicode_for_block() with Escape key.
-+ row.size_allocate.connect((w, a) => {
-+ clamp_page();
-+ });
- }
-
-+
- private void show_unicode_for_block(string block_name) {
-- if (!m_loaded_unicode) {
-- remove_all_children();
-- set_fixed_size();
-- m_unicode_progress_bar = new Gtk.ProgressBar();
-- m_unicode_progress_bar.set_ellipsize(Pango.EllipsizeMode.MIDDLE);
-- m_unicode_progress_bar.set_halign(Gtk.Align.CENTER);
-- m_unicode_progress_bar.set_valign(Gtk.Align.CENTER);
-- m_vbox.add(m_unicode_progress_bar);
-- m_unicode_progress_bar.show();
-- var hbox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 5);
-- hbox.set_halign(Gtk.Align.CENTER);
-- hbox.set_valign(Gtk.Align.CENTER);
-- m_vbox.add(hbox);
-- var label = new Gtk.Label(_("Loading a Unicode dictionary:"));
-- hbox.pack_start(label, false, true, 0);
-- m_unicode_percent_label = new Gtk.Label("");
-- hbox.pack_start(m_unicode_percent_label, false, true, 0);
-- hbox.show_all();
--
-- m_unicode_progress_object.deserialize_unicode.connect((i, n) => {
-- m_unicode_percent = (double)i / n;
-- });
-- GLib.Timeout.add(100, () => {
-- m_unicode_progress_bar.set_fraction(m_unicode_percent);
-- m_unicode_percent_label.set_text(
-- "%.0f%%\n".printf(m_unicode_percent * 100));
-- m_unicode_progress_bar.show();
-- m_unicode_percent_label.show();
-- if (m_loaded_unicode) {
-- show_unicode_for_block(block_name);
-- }
-- return !m_loaded_unicode;
-- });
-- return;
-- }
- unichar start = 0;
- unichar end = 0;
- foreach (unowned IBus.UnicodeBlock block in m_unicode_block_list) {
-@@ -1055,6 +1028,7 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- }
- }
- m_lookup_table.clear();
-+ m_candidate_panel_mode = true;
- for (unichar ch = start; ch < end; ch++) {
- unowned IBus.UnicodeData? data =
- m_unicode_to_data_dict.lookup(ch);
-@@ -1064,7 +1038,7 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- m_lookup_table.append_candidate(text);
- }
- m_backward = block_name;
-- show_candidate_panel();
-+ m_annotation = m_lookup_table.get_candidate(0).text;
- }
-
-
-@@ -1091,6 +1065,41 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- prev_button.set_relief(Gtk.ReliefStyle.NONE);
- prev_button.set_tooltip_text(_("Page Up"));
-
-+ var menu = new GLib.Menu();
-+ menu.append(_("Show emoji variants"), "win.variant");
-+ menu.append(_("Close"), "win.close");
-+ var menu_button = new Gtk.MenuButton();
-+ menu_button.set_direction(Gtk.ArrowType.NONE);
-+ menu_button.set_valign(Gtk.Align.CENTER);
-+ menu_button.set_menu_model(menu);
-+ menu_button.set_relief(Gtk.ReliefStyle.NONE);
-+ menu_button.set_tooltip_text(_("Menu"));
-+
-+ IBus.Text text = this.get_title_text();
-+ Pango.AttrList attrs = get_pango_attr_list_from_ibus_text(text);
-+ Gtk.Label title_label = new Gtk.Label(text.get_text());
-+ title_label.set_attributes(attrs);
-+
-+ Gtk.Button? warning_button = null;
-+ if (m_warning_message != "") {
-+ warning_button = new Gtk.Button();
-+ warning_button.set_tooltip_text(
-+ _("Click to view a warning message"));
-+ warning_button.set_image(new Gtk.Image.from_icon_name(
-+ "dialog-warning",
-+ Gtk.IconSize.MENU));
-+ warning_button.set_relief(Gtk.ReliefStyle.NONE);
-+ warning_button.clicked.connect(() => {
-+ Gtk.Label warning_label = new Gtk.Label(m_warning_message);
-+ warning_label.set_line_wrap(true);
-+ warning_label.set_max_width_chars(40);
-+ Gtk.Popover popover = new Gtk.Popover(warning_button);
-+ popover.add(warning_label);
-+ popover.show_all();
-+ popover.popup();
-+ });
-+ }
-+
- Gtk.Box buttons_hbox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
- Gtk.Label state_label = new Gtk.Label(null);
- state_label.set_size_request(10, -1);
-@@ -1099,14 +1108,55 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- buttons_hbox.pack_start(state_label, false, true, 0);
- buttons_hbox.pack_start(prev_button, false, false, 0);
- buttons_hbox.pack_start(next_button, false, false, 0);
-+ buttons_hbox.pack_start(title_label, false, false, 0);
-+ if (warning_button != null)
-+ buttons_hbox.pack_start(warning_button, false, false, 0);
-+ buttons_hbox.pack_end(menu_button, false, false, 0);
- m_vbox.pack_start(buttons_hbox, false, false, 0);
- buttons_hbox.show_all();
- }
-
-
-- private bool check_unicode_point() {
-- string annotation = m_entry.get_text();
-- m_unicode_point = null;
-+ private void show_unicode_progress_bar() {
-+ m_unicode_progress_bar = new Gtk.ProgressBar();
-+ m_unicode_progress_bar.set_ellipsize(Pango.EllipsizeMode.MIDDLE);
-+ m_unicode_progress_bar.set_halign(Gtk.Align.CENTER);
-+ m_unicode_progress_bar.set_valign(Gtk.Align.CENTER);
-+ m_vbox.add(m_unicode_progress_bar);
-+ m_unicode_progress_bar.show();
-+ var hbox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 5);
-+ hbox.set_halign(Gtk.Align.CENTER);
-+ hbox.set_valign(Gtk.Align.CENTER);
-+ m_vbox.add(hbox);
-+ var label = new Gtk.Label(_("Loading a Unicode dictionary:"));
-+ hbox.pack_start(label, false, true, 0);
-+ m_unicode_percent_label = new Gtk.Label("");
-+ hbox.pack_start(m_unicode_percent_label, false, true, 0);
-+ hbox.show_all();
-+
-+ m_unicode_progress_object.deserialize_unicode.connect((i, n) => {
-+ m_unicode_percent = (double)i / n;
-+ });
-+ if (m_unicode_progress_id > 0) {
-+ GLib.Source.remove(m_unicode_progress_id);
-+ }
-+ m_unicode_progress_id = GLib.Timeout.add(100, () => {
-+ m_unicode_progress_id = 0;
-+ m_unicode_progress_bar.set_fraction(m_unicode_percent);
-+ m_unicode_percent_label.set_text(
-+ "%.0f%%\n".printf(m_unicode_percent * 100));
-+ m_unicode_progress_bar.show();
-+ m_unicode_percent_label.show();
-+ if (m_loaded_unicode) {
-+ show_candidate_panel();
-+ }
-+ return !m_loaded_unicode;
-+ });
-+ }
-+
-+
-+ private static string? check_unicode_point(string annotation) {
-+ string unicode_point = null;
- // Add "0x" because uint64.ascii_strtoull() is not accessible
- // and need to use uint64.parse()
- var buff = new GLib.StringBuilder("0x");
-@@ -1114,33 +1164,31 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- for (int i = 0; i < annotation.char_count(); i++) {
- unichar ch = annotation.get_char(i);
- if (ch == 0)
-- return false;
-+ return null;
- if (ch.isspace()) {
- unichar code = (unichar)uint64.parse(buff.str);
- buff.assign("0x");
- if (!code.validate())
-- return false;
-+ return null;
- retval.append(code.to_string());
- continue;
- }
- if (!ch.isxdigit())
-- return false;
-+ return null;
- buff.append_unichar(ch);
- }
- unichar code = (unichar)uint64.parse(buff.str);
- if (!code.validate())
-- return false;
-+ return null;
- retval.append(code.to_string());
-- m_unicode_point = retval.str;
-- if (m_unicode_point == null)
-- return true;
-- IBus.Text text = new IBus.Text.from_string(m_unicode_point);
-- m_lookup_table.append_candidate(text);
-- return true;
-+ unicode_point = retval.str;
-+ if (unicode_point == null)
-+ return null;
-+ return unicode_point;
- }
-
-
-- private GLib.SList<string>?
-+ private static GLib.SList<string>?
- lookup_emojis_from_annotation(string annotation) {
- GLib.SList<string>? total_emojis = null;
- unowned GLib.SList<string>? sub_emojis = null;
-@@ -1221,19 +1269,19 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- return total_emojis;
- }
-
-+
- private void update_candidate_window() {
-- string annotation = m_entry.get_text();
-+ string annotation = m_annotation;
- if (annotation.length == 0) {
-- hide_candidate_panel();
- m_backward = null;
- return;
- }
-+ m_lookup_table.clear();
-+ m_category_active_index = -1;
- if (annotation.length > m_emoji_max_seq_len) {
-- hide_candidate_panel();
- return;
- }
-- // Call check_unicode_point() to get m_unicode_point
-- check_unicode_point();
-+ string? unicode_point = check_unicode_point(annotation);
- GLib.SList<string>? total_emojis =
- lookup_emojis_from_annotation(annotation);
- if (total_emojis == null) {
-@@ -1246,18 +1294,75 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- annotation = annotation.down();
- total_emojis = lookup_emojis_from_annotation(annotation);
- }
-- if (total_emojis == null && m_unicode_point == null) {
-- hide_candidate_panel();
-+ if (total_emojis == null && unicode_point == null) {
- return;
- }
-- m_lookup_table.clear();
-- // Call check_unicode_point() to update m_lookup_table
-- check_unicode_point();
-+ if (unicode_point != null) {
-+ IBus.Text text = new IBus.Text.from_string(unicode_point);
-+ m_lookup_table.append_candidate(text);
-+ }
- foreach (unowned string emoji in total_emojis) {
- IBus.Text text = new IBus.Text.from_string(emoji);
- m_lookup_table.append_candidate(text);
- }
-- show_candidate_panel();
-+ m_candidate_panel_is_visible =
-+ (m_lookup_table.get_number_of_candidates() > 0) ? true : false;
-+ m_candidate_panel_mode = true;
-+ }
-+
-+
-+ private void update_category_list() {
-+ // Always update m_lookup_table even if the contents are same
-+ // because m_category_active_index needs to be kept after
-+ // bring back this API from show_emoji_for_category().
-+ reset_window_mode();
-+ m_lookup_table.clear();
-+ IBus.Text text;
-+ if (m_favorites.length > 0) {
-+ text = new IBus.Text.from_string(EMOJI_CATEGORY_FAVORITES);
-+ m_lookup_table.append_candidate(text);
-+ }
-+ GLib.List<unowned string> categories =
-+ m_category_to_emojis_dict.get_keys();
-+ // FIXME: How to cast GLib.CompareFunc<string> to strcmp?
-+ categories.sort((a, b) => {
-+ if (a == EMOJI_CATEGORY_OTHERS && b != EMOJI_CATEGORY_OTHERS)
-+ return 1;
-+ else if (a != EMOJI_CATEGORY_OTHERS && b == EMOJI_CATEGORY_OTHERS)
-+ return -1;
-+ return GLib.strcmp(_(a), _(b));
-+ });
-+ foreach (unowned string category in categories) {
-+ // "Others" category includes next unicode chars and fonts do not
-+ // support the base and varints yet.
-+ if (category == EMOJI_CATEGORY_OTHERS)
-+ continue;
-+ text = new IBus.Text.from_string(category);
-+ m_lookup_table.append_candidate(text);
-+ }
-+ if (m_unicode_block_list.length() > 0) {
-+ text = new IBus.Text.from_string(EMOJI_CATEGORY_UNICODE);
-+ m_lookup_table.append_candidate(text);
-+ }
-+ // Do not set m_category_active_index to 0 here so that
-+ // show_category_list() handles it.
-+ }
-+
-+
-+ private void update_unicode_blocks() {
-+ // Always update m_lookup_table even if the contents are same
-+ // because m_category_active_index needs to be kept after
-+ // bring back this API from show_emoji_for_category().
-+ reset_window_mode();
-+ m_lookup_table.clear();
-+ m_show_unicode = true;
-+ foreach (unowned IBus.UnicodeBlock block in m_unicode_block_list) {
-+ string name = block.get_name();
-+ IBus.Text text = new IBus.Text.from_string(name);
-+ m_lookup_table.append_candidate(text);
-+ }
-+ // Do not set m_category_active_index to 0 here so that
-+ // show_unicode_blocks() handles it.
- }
-
-
-@@ -1283,27 +1388,27 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- uint page_size = m_lookup_table.get_page_size();
- uint ncandidates = m_lookup_table.get_number_of_candidates();
- uint cursor = m_lookup_table.get_cursor_pos();
--
- uint page_start_pos = cursor / page_size * page_size;
- uint page_end_pos = uint.min(page_start_pos + page_size, ncandidates);
-+ Gtk.Button? backward_button = null;
- if (m_backward != null) {
-- string backward_desc =
-- "%s (%u / %u)".printf(_(m_backward), cursor, ncandidates - 1);
-+ string backward_desc = _(m_backward);
- EPaddedLabelBox label =
- new EPaddedLabelBox(backward_desc,
- Gtk.Align.CENTER,
- TravelDirection.BACKWARD);
-- Gtk.Button button = new Gtk.Button();
-- button.add(label);
-- m_vbox.add(button);
-- button.show_all();
-- button.button_press_event.connect((w, e) => {
-+ backward_button = new Gtk.Button();
-+ backward_button.add(label);
-+ backward_button.button_press_event.connect((w, e) => {
- // Bring back to emoji candidate panel in case
- // m_show_emoji_variant is enabled and shows variants.
-- if (m_backward_index >= 0 && m_backward != null)
-+ if (m_backward_index >= 0 && m_backward != null) {
- show_emoji_for_category(m_backward);
-- else
-+ show_candidate_panel();
-+ } else {
- hide_candidate_panel();
-+ show_all();
-+ }
- return true;
- });
- }
-@@ -1385,34 +1490,60 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- }
- if (n > 0) {
- m_candidate_panel_is_visible = true;
-- show_arrow_buttons();
-- m_vbox.add(grid);
-- grid.show_all();
-- string text = m_lookup_table.get_candidate(cursor).text;
-- unowned IBus.EmojiData? data = m_emoji_to_data_dict.lookup(text);
-- if (data != null) {
-- show_emoji_description(data, text);
-- return;
-+ if (!m_is_up_side_down) {
-+ show_arrow_buttons();
-+ if (backward_button != null) {
-+ m_vbox.add(backward_button);
-+ backward_button.show_all();
-+ }
-+ m_vbox.add(grid);
-+ grid.show_all();
-+ show_description();
-+ if (!m_loaded_unicode)
-+ show_unicode_progress_bar();
- }
-- if (text.char_count() <= 1) {
-- unichar code = text.get_char();
-- unowned IBus.UnicodeData? udata =
-- m_unicode_to_data_dict.lookup(code);
-- if (udata != null) {
-- show_unicode_description(udata, text);
-- return;
-+ if (m_is_up_side_down) {
-+ if (!m_loaded_unicode)
-+ show_unicode_progress_bar();
-+ show_description();
-+ m_vbox.add(grid);
-+ grid.show_all();
-+ if (backward_button != null) {
-+ m_vbox.add(backward_button);
-+ backward_button.show_all();
- }
-+ show_arrow_buttons();
- }
-- EPaddedLabelBox widget = new EPaddedLabelBox(
-- _("Description: %s").printf(_("None")),
-- Gtk.Align.START);
-- m_vbox.add(widget);
-- widget.show_all();
-- show_code_point_description(text);
- }
- }
-
-
-+ private void show_description() {
-+ uint cursor = m_lookup_table.get_cursor_pos();
-+ string text = m_lookup_table.get_candidate(cursor).text;
-+ unowned IBus.EmojiData? data = m_emoji_to_data_dict.lookup(text);
-+ if (data != null) {
-+ show_emoji_description(data, text);
-+ return;
-+ }
-+ if (text.char_count() <= 1) {
-+ unichar code = text.get_char();
-+ unowned IBus.UnicodeData? udata =
-+ m_unicode_to_data_dict.lookup(code);
-+ if (udata != null) {
-+ show_unicode_description(udata, text);
-+ return;
-+ }
-+ }
-+ EPaddedLabelBox widget = new EPaddedLabelBox(
-+ _("Description: %s").printf(_("None")),
-+ Gtk.Align.START);
-+ m_vbox.add(widget);
-+ widget.show_all();
-+ show_code_point_description(text);
-+ }
-+
-+
- private void show_emoji_description(IBus.EmojiData data,
- string text) {
- unowned string description = data.get_description();
-@@ -1473,14 +1604,17 @@ public class IBusEmojier : Gtk.ApplicationWindow {
-
-
- private void hide_candidate_panel() {
-+ hide();
- m_enter_notify_enable = true;
-- m_candidate_panel_is_visible = false;
-- if (m_loop.is_running()) {
-- if (m_show_unicode)
-- show_unicode_blocks();
-- else
-- show_category_list();
-- }
-+ m_annotation = "";
-+ // Call remove_all_children() instead of show_category_list()
-+ // so that show_category_list do not remove children with
-+ // PageUp/PageDown.
-+ remove_all_children();
-+ if (m_show_unicode)
-+ update_unicode_blocks();
-+ else
-+ update_category_list();
- }
-
-
-@@ -1498,20 +1632,34 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- }
-
-
-- private void candidate_panel_select_index(uint index) {
-+ private void candidate_panel_select_index(uint index,
-+ uint button) {
-+ if (button == BUTTON_CLOSE_BUTTON) {
-+ hide();
-+ if (m_candidate_panel_mode &&
-+ m_lookup_table.get_number_of_candidates() > 0) {
-+ // Call remove_all_children() instead of show_category_list()
-+ // so that show_category_list do not remove children with
-+ // PageUp/PageDown.
-+ remove_all_children();
-+ }
-+ m_result = "";
-+ return;
-+ }
- string text = m_lookup_table.get_candidate(index).text;
- unowned GLib.SList<string>? emojis =
- m_emoji_to_emoji_variants_dict.lookup(text);
- if (m_show_emoji_variant && emojis != null &&
- m_backward_index < 0) {
- show_emoji_variants(emojis);
-+ show_all();
- } else {
- m_result = text;
-- m_loop.quit();
-- hide_candidate_panel();
-+ hide();
- }
- }
-
-+
- private void candidate_panel_cursor_down() {
- enter_notify_disable_with_timer();
- uint ncandidates = m_lookup_table.get_number_of_candidates();
-@@ -1523,7 +1671,6 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- } else {
- m_lookup_table.set_cursor_pos(0);
- }
-- show_candidate_panel();
- }
-
-
-@@ -1541,7 +1688,6 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- } else {
- m_lookup_table.set_cursor_pos(0);
- }
-- show_candidate_panel();
- }
-
-
-@@ -1558,7 +1704,9 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- return page_num;
- }
-
-+
- private bool category_list_cursor_move(uint keyval) {
-+ return_val_if_fail (m_list_box != null, false);
- GLib.List<weak Gtk.Widget> list = m_list_box.get_children();
- int length = (int)list.length();
- if (length == 0)
-@@ -1600,32 +1748,37 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- var row = m_list_box.get_selected_row();
- if (row != null)
- m_list_box.unselect_row(row);
-- if (m_category_active_index >= 0) {
-- row = m_list_box.get_row_at_index(m_category_active_index);
-- m_list_box.select_row(row);
-- } else {
-- row = m_list_box.get_row_at_index(0);
-- }
-- Gtk.Allocation alloc = { 0, 0, 0, 0 };
-- row.get_allocation(out alloc);
-- var adjustment = m_scrolled_window.get_vadjustment();
-- adjustment.clamp_page(alloc.y, alloc.y + alloc.height);
-+ clamp_page ();
- return true;
- }
-
-
-- private bool key_press_cursor_horizontal(uint keyval,
-- uint modifiers) {
-+ public bool has_variants(uint index) {
-+ if (index >= m_lookup_table.get_number_of_candidates())
-+ return false;
-+ string text = m_lookup_table.get_candidate(index).text;
-+ unowned GLib.SList<string>? emojis =
-+ m_emoji_to_emoji_variants_dict.lookup(text);
-+ if (m_show_emoji_variant && emojis != null &&
-+ m_backward_index < 0) {
-+ show_emoji_variants(emojis);
-+ return true;
-+ }
-+ return false;
-+ }
-+
-+
-+ public bool key_press_cursor_horizontal(uint keyval,
-+ uint modifiers) {
- assert (keyval == Gdk.Key.Left || keyval == Gdk.Key.Right);
-
-- uint ncandidates = m_lookup_table.get_number_of_candidates();
-- if (m_candidate_panel_is_visible && ncandidates > 1) {
-+ if (m_candidate_panel_mode &&
-+ m_lookup_table.get_number_of_candidates() > 0) {
- enter_notify_disable_with_timer();
- if (keyval == Gdk.Key.Left)
- m_lookup_table.cursor_up();
- else if (keyval == Gdk.Key.Right)
- m_lookup_table.cursor_down();
-- show_candidate_panel();
- } else if (m_entry.get_text().length > 0) {
- int step = 0;
- if (keyval == Gdk.Key.Left)
-@@ -1650,8 +1803,8 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- }
-
-
-- private bool key_press_cursor_vertical(uint keyval,
-- uint modifiers) {
-+ public bool key_press_cursor_vertical(uint keyval,
-+ uint modifiers) {
- assert (keyval == Gdk.Key.Down || keyval == Gdk.Key.Up ||
- keyval == Gdk.Key.Page_Down || keyval == Gdk.Key.Page_Up);
-
-@@ -1661,8 +1814,8 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- else if (keyval == Gdk.Key.Up)
- keyval = Gdk.Key.Page_Up;
- }
-- uint ncandidates = m_lookup_table.get_number_of_candidates();
-- if (m_candidate_panel_is_visible && ncandidates > 1) {
-+ if ((m_candidate_panel_is_visible || m_annotation.length > 0)
-+ && m_lookup_table.get_number_of_candidates() > 0) {
- switch (keyval) {
- case Gdk.Key.Down:
- candidate_panel_cursor_down();
-@@ -1673,12 +1826,10 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- case Gdk.Key.Page_Down:
- enter_notify_disable_with_timer();
- m_lookup_table.page_down();
-- show_candidate_panel();
- break;
- case Gdk.Key.Page_Up:
- enter_notify_disable_with_timer();
- m_lookup_table.page_up();
-- show_candidate_panel();
- break;
- }
- } else {
-@@ -1688,19 +1839,18 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- }
-
-
-- private bool key_press_cursor_home_end(uint keyval,
-- uint modifiers) {
-+ public bool key_press_cursor_home_end(uint keyval,
-+ uint modifiers) {
- assert (keyval == Gdk.Key.Home || keyval == Gdk.Key.End);
-
- uint ncandidates = m_lookup_table.get_number_of_candidates();
-- if (m_candidate_panel_is_visible && ncandidates > 1) {
-+ if (m_candidate_panel_mode && ncandidates > 0) {
- enter_notify_disable_with_timer();
- if (keyval == Gdk.Key.Home) {
- m_lookup_table.set_cursor_pos(0);
- } else if (keyval == Gdk.Key.End) {
- m_lookup_table.set_cursor_pos(ncandidates - 1);
- }
-- show_candidate_panel();
- return true;
- }
- if (m_entry.get_text().length > 0) {
-@@ -1717,44 +1867,41 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- ? true : false);
- return true;
- }
-- if (!m_candidate_panel_is_visible)
-- return category_list_cursor_move(keyval);
-- return false;
-+ return category_list_cursor_move(keyval);
- }
-
-
-- private bool key_press_escape() {
-+ public bool key_press_escape() {
- if (m_show_unicode) {
-- if (m_candidate_panel_is_visible) {
-- m_candidate_panel_is_visible = false;
-- show_unicode_blocks();
-- return true;
-- } else {
-+ if (!m_candidate_panel_is_visible) {
- m_show_unicode = false;
- m_category_active_index = -1;
-- hide_candidate_panel();
-- return true;
- }
-+ hide_candidate_panel();
-+ return true;
- } else if (m_backward_index >= 0 && m_backward != null) {
- show_emoji_for_category(m_backward);
- return true;
-- } else if (m_candidate_panel_is_visible) {
-- hide_candidate_panel();
-- return true;
-- } else if (m_entry.get_text().length == 0) {
-- m_loop.quit();
-+ } else if (m_candidate_panel_is_visible && m_backward != null) {
- hide_candidate_panel();
- return true;
- }
-- m_entry.delete_text(0, -1);
-- return true;
-+ hide();
-+ if (m_candidate_panel_mode &&
-+ m_lookup_table.get_number_of_candidates() > 0) {
-+ // Call remove_all_children() instead of show_category_list()
-+ // so that show_category_list do not remove children with
-+ // PageUp/PageDown.
-+ remove_all_children();
-+ }
-+ return false;
- }
-
-
-- private bool key_press_enter() {
-+ public bool key_press_enter() {
- if (m_candidate_panel_is_visible) {
- uint index = m_lookup_table.get_cursor_pos();
-- candidate_panel_select_index(index);
-+ return has_variants(index);
- } else if (m_category_active_index >= 0) {
- Gtk.ListBoxRow gtkrow = m_list_box.get_selected_row();
- EBoxRow row = gtkrow as EBoxRow;
-@@ -1789,13 +1936,111 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- }
-
-
-+ private Gdk.Rectangle get_monitor_geometry() {
-+ Gdk.Rectangle monitor_area = { 0, };
-+
-+ // Use get_monitor_geometry() instead of get_monitor_area().
-+ // get_monitor_area() excludes docks, but the lookup window should be
-+ // shown over them.
-+#if VALA_0_34
-+ Gdk.Monitor monitor = Gdk.Display.get_default().get_monitor_at_point(
-+ m_cursor_location.x,
-+ m_cursor_location.y);
-+ monitor_area = monitor.get_geometry();
-+#else
-+ Gdk.Screen screen = Gdk.Screen.get_default();
-+ int monitor_num = screen.get_monitor_at_point(m_cursor_location.x,
-+ m_cursor_location.y);
-+ screen.get_monitor_geometry(monitor_num, out monitor_area);
-+#endif
-+ return monitor_area;
-+ }
-+
-+
-+ private void adjust_window_position() {
-+ Gdk.Point cursor_right_bottom = {
-+ m_cursor_location.x + m_cursor_location.width,
-+ m_cursor_location.y + m_cursor_location.height
-+ };
-+
-+ Gtk.Allocation allocation;
-+ get_allocation(out allocation);
-+ Gdk.Point window_right_bottom = {
-+ cursor_right_bottom.x + allocation.width,
-+ cursor_right_bottom.y + allocation.height
-+ };
-+
-+ Gdk.Rectangle monitor_area = get_monitor_geometry();
-+ int monitor_right = monitor_area.x + monitor_area.width;
-+ int monitor_bottom = monitor_area.y + monitor_area.height;
-+
-+ int x, y;
-+ if (window_right_bottom.x > monitor_right)
-+ x = monitor_right - allocation.width;
-+ else
-+ x = cursor_right_bottom.x;
-+ if (x < 0)
-+ x = 0;
-+
-+ bool changed = false;
-+ if (window_right_bottom.y > monitor_bottom) {
-+ y = m_cursor_location.y - allocation.height;
-+ // Do not up side down in Wayland
-+ if (m_input_context_path == "") {
-+ changed = (m_is_up_side_down == false);
-+ m_is_up_side_down = true;
-+ } else {
-+ changed = (m_is_up_side_down == true);
-+ m_is_up_side_down = false;
-+ }
-+ } else {
-+ y = cursor_right_bottom.y;
-+ changed = (m_is_up_side_down == true);
-+ m_is_up_side_down = false;
-+ }
-+ if (y < 0)
-+ y = 0;
-+
-+ move(x, y);
-+ if (changed) {
-+ if (m_redraw_window_id > 0)
-+ GLib.Source.remove(m_redraw_window_id);
-+ m_redraw_window_id = GLib.Timeout.add(100, () => {
-+ m_redraw_window_id = 0;
-+ this.show_all();
-+ return false;
-+ });
-+ }
-+ }
-+
-+
-+#if 0
-+ private void check_action_variant_cb(Gtk.MenuItem item) {
-+ Gtk.CheckMenuItem check = item as Gtk.CheckMenuItem;
-+ m_show_emoji_variant = check.get_active();
-+ // Redraw emoji candidate panel for m_show_emoji_variant
-+ if (m_candidate_panel_is_visible) {
-+ // DOTO: queue_draw() does not effect at the real time.
-+ this.queue_draw();
-+ }
-+ }
-+#else
- private void check_action_variant_cb(GLib.SimpleAction action,
- GLib.Variant? parameter) {
- m_show_emoji_variant = !action.get_state().get_boolean();
- action.set_state(new GLib.Variant.boolean(m_show_emoji_variant));
- // Redraw emoji candidate panel for m_show_emoji_variant
-- if (m_candidate_panel_is_visible)
-- show_candidate_panel();
-+ if (m_candidate_panel_is_visible) {
-+ // DOTO: queue_draw() does not effect at the real time.
-+ this.queue_draw();
-+ }
-+ }
-+#endif
-+
-+
-+ private void action_close_cb(GLib.SimpleAction action,
-+ GLib.Variant? parameter) {
-+ candidate_clicked(0, BUTTON_CLOSE_BUTTON, 0);
- }
-
-
-@@ -1842,6 +2087,123 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- }
-
-
-+ public void set_annotation(string annotation) {
-+ m_annotation = annotation;
-+ remove_all_children();
-+ if (annotation.length > 0) {
-+ update_candidate_window();
-+ } else {
-+ if (m_show_unicode)
-+ update_unicode_blocks();
-+ else
-+ update_category_list();
-+ }
-+ }
-+
-+
-+ public IBus.LookupTable get_one_dimension_lookup_table() {
-+ var lookup_table = new IBus.LookupTable(EMOJI_GRID_PAGE, 0, true, true);
-+ uint i = 0;
-+ for (; i < m_lookup_table.get_number_of_candidates(); i++) {
-+ IBus.Text text = new IBus.Text.from_string("");
-+ text.copy(m_lookup_table.get_candidate(i));
-+ lookup_table.append_candidate(text);
-+ }
-+ if (i > 0)
-+ lookup_table.set_cursor_pos(m_lookup_table.get_cursor_pos());
-+ return lookup_table;
-+ }
-+
-+
-+ public uint get_number_of_candidates() {
-+ return m_lookup_table.get_number_of_candidates();
-+ }
-+
-+
-+ public uint get_cursor_pos() {
-+ return m_lookup_table.get_cursor_pos();
-+ }
-+
-+
-+ public void set_cursor_pos(uint cursor_pos) {
-+ m_lookup_table.set_cursor_pos(cursor_pos);
-+ }
-+
-+
-+ public string get_current_candidate() {
-+ // If category_list mode, do not show the category name on preedit.
-+ // If candidate_panel mode, the first space key does not show the
-+ // lookup table but the first candidate is avaiable on preedit.
-+ if (!m_candidate_panel_mode)
-+ return "";
-+ uint cursor = m_lookup_table.get_cursor_pos();
-+ return m_lookup_table.get_candidate(cursor).text;
-+ }
-+
-+
-+ public IBus.Text get_title_text() {
-+ var language = _(IBus.get_language_name(m_current_lang_id));
-+ uint ncandidates = this.get_number_of_candidates();
-+ string main_title = _("Emoji Choice");
-+ if (m_show_unicode)
-+ main_title = _("Unicode Choice");
-+ var text = new IBus.Text.from_string(
-+ "%s (%s) (%u / %u)".printf(
-+ main_title,
-+ language,
-+ this.get_cursor_pos() + 1,
-+ ncandidates));
-+ int char_count = text.text.char_count();
-+ int start_index = -1;
-+ for (int i = 0; i < char_count; i++) {
-+ if (text.text.utf8_offset(i).has_prefix(language)) {
-+ start_index = i;
-+ break;
-+ }
-+ }
-+ if (start_index >= 0) {
-+ var attr = new IBus.Attribute(
-+ IBus.AttrType.FOREGROUND,
-+ 0x808080,
-+ start_index,
-+ start_index + language.char_count());
-+ var attrs = new IBus.AttrList();
-+ attrs.append(attr);
-+ text.set_attributes(attrs);
-+ }
-+ return text;
-+ }
-+
-+
-+#if 0
-+ public GLib.SList<string>? get_candidates() {
-+ if (m_annotation.length == 0) {
-+ return null;
-+ }
-+ if (m_annotation.length > m_emoji_max_seq_len) {
-+ return null;
-+ }
-+ string? unicode_point = check_unicode_point(m_annotation);
-+ GLib.SList<string>? total_emojis =
-+ lookup_emojis_from_annotation(m_annotation);
-+ if (total_emojis == null) {
-+ /* Users can type title strings against lower case.
-+ * E.g. "Smile" against "smile"
-+ * But the dictionary has the case sensitive annotations.
-+ * E.g. ":D" and ":q"
-+ * So need to call lookup_emojis_from_annotation() twice.
-+ */
-+ string lower_annotation = m_annotation.down();
-+ total_emojis = lookup_emojis_from_annotation(lower_annotation);
-+ }
-+ if (unicode_point != null)
-+ total_emojis.prepend(unicode_point);
-+ return total_emojis;
-+ }
-+#endif
-+
-+
-+#if 0
- public string run(string input_context_path,
- Gdk.Event event) {
- assert (m_loop == null);
-@@ -1915,12 +2277,34 @@ public class IBusEmojier : Gtk.ApplicationWindow {
-
- return m_result;
- }
-+#endif
-
-
- /* override virtual functions */
-- public override void show() {
-- base.show();
-- set_focus_visible(true);
-+ public override void show_all() {
-+ base.show_all();
-+ if (m_candidate_panel_mode)
-+ show_candidate_panel();
-+ else if (m_show_unicode)
-+ show_unicode_blocks();
-+ else
-+ show_category_list();
-+ }
-+
-+
-+ public override void hide() {
-+ base.hide();
-+ m_candidate_panel_is_visible = false;
-+ // m_candidate_panel_mode is not false in when you type something
-+ // during enabling the candidate panel.
-+ if (m_redraw_window_id > 0) {
-+ GLib.Source.remove(m_redraw_window_id);
-+ m_redraw_window_id = 0;
-+ }
-+ if (m_unicode_progress_id > 0) {
-+ GLib.Source.remove(m_unicode_progress_id);
-+ m_unicode_progress_id = 0;
-+ }
- }
-
-
-@@ -1935,11 +2319,16 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- switch (keyval) {
- case Gdk.Key.Escape:
- if (key_press_escape())
-- return true;
-- break;
-+ show_all();
-+ return true;
- case Gdk.Key.Return:
- case Gdk.Key.KP_Enter:
-- key_press_enter();
-+ if (key_press_enter()) {
-+ show_all();
-+ } else {
-+ m_result = get_current_candidate();
-+ hide();
-+ }
- return true;
- case Gdk.Key.BackSpace:
- if (m_entry.get_text().length > 0) {
-@@ -1977,42 +2366,49 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- }
- else {
- category_list_cursor_move(Gdk.Key.Down);
-+ show_all();
- }
- return true;
- case Gdk.Key.Right:
- case Gdk.Key.KP_Right:
- key_press_cursor_horizontal(Gdk.Key.Right, modifiers);
-+ show_all();
- return true;
- case Gdk.Key.Left:
- case Gdk.Key.KP_Left:
- key_press_cursor_horizontal(Gdk.Key.Left, modifiers);
-+ show_all();
- return true;
- case Gdk.Key.Down:
- case Gdk.Key.KP_Down:
- key_press_cursor_vertical(Gdk.Key.Down, modifiers);
-+ show_all();
- return true;
- case Gdk.Key.Up:
- case Gdk.Key.KP_Up:
- key_press_cursor_vertical(Gdk.Key.Up, modifiers);
-+ show_all();
- return true;
- case Gdk.Key.Page_Down:
- case Gdk.Key.KP_Page_Down:
- key_press_cursor_vertical(Gdk.Key.Page_Down, modifiers);
-+ show_all();
- return true;
- case Gdk.Key.Page_Up:
- case Gdk.Key.KP_Page_Up:
- key_press_cursor_vertical(Gdk.Key.Page_Up, modifiers);
-+ show_all();
- return true;
- case Gdk.Key.Home:
- case Gdk.Key.KP_Home:
-- if (key_press_cursor_home_end(Gdk.Key.Home, modifiers))
-- return true;
-- break;
-+ key_press_cursor_home_end(Gdk.Key.Home, modifiers);
-+ show_all();
-+ return true;
- case Gdk.Key.End:
- case Gdk.Key.KP_End:
-- if (key_press_cursor_home_end(Gdk.Key.End, modifiers))
-- return true;
-- break;
-+ key_press_cursor_home_end(Gdk.Key.End, modifiers);
-+ show_all();
-+ return true;
- case Gdk.Key.Insert:
- case Gdk.Key.KP_Insert:
- GLib.Signal.emit_by_name(m_entry, "toggle-overwrite");
-@@ -2023,26 +2419,30 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- switch (keyval) {
- case Gdk.Key.f:
- key_press_cursor_horizontal(Gdk.Key.Right, modifiers);
-+ show_all();
- return true;
- case Gdk.Key.b:
- key_press_cursor_horizontal(Gdk.Key.Left, modifiers);
-+ show_all();
- return true;
- case Gdk.Key.n:
- case Gdk.Key.N:
- key_press_cursor_vertical(Gdk.Key.Down, modifiers);
-+ show_all();
- return true;
- case Gdk.Key.p:
- case Gdk.Key.P:
- key_press_cursor_vertical(Gdk.Key.Up, modifiers);
-+ show_all();
- return true;
- case Gdk.Key.h:
-- if (key_press_cursor_home_end(Gdk.Key.Home, modifiers))
-- return true;
-- break;
-+ key_press_cursor_home_end(Gdk.Key.Home, modifiers);
-+ show_all();
-+ return true;
- case Gdk.Key.e:
-- if (key_press_cursor_home_end(Gdk.Key.End, modifiers))
-- return true;
-- break;
-+ key_press_cursor_home_end(Gdk.Key.End, modifiers);
-+ show_all();
-+ return true;
- case Gdk.Key.u:
- if (m_entry.get_text().length > 0) {
- GLib.Signal.emit_by_name(m_entry,
-@@ -2103,14 +2503,41 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- }
-
-
-+ public void set_input_context_path(string input_context_path) {
-+ m_input_context_path = input_context_path;
-+ if (input_context_path == "") {
-+ m_warning_message = _("" +
-+ "Failed to get the current text application. " +
-+ "Please re-focus your application. E.g. Press Esc key " +
-+ "several times to release the emoji typing mode, " +
-+ "click your desktop and click your text application again."
-+ );
-+ } else {
-+ m_warning_message = "";
-+ }
-+ }
-+
-+
- public string get_selected_string() {
- return m_result;
- }
-
-
-+ private void reset_window_mode() {
-+ m_backward_index = -1;
-+ m_backward = null;
-+ m_candidate_panel_is_visible = false;
-+ m_candidate_panel_mode = false;
-+ // Do not clear m_lookup_table to work with space key later.
-+ }
-+
-+
- public void reset() {
-+ reset_window_mode();
- m_input_context_path = "";
- m_result = null;
-+ m_category_active_index = -1;
-+ m_show_unicode = false;
- }
-
-
-@@ -2145,6 +2572,23 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- }
-
-
-+ public void set_cursor_location(int x,
-+ int y,
-+ int width,
-+ int height) {
-+ Gdk.Rectangle location = Gdk.Rectangle(){
-+ x = x, y = y, width = width, height = height };
-+ if (m_cursor_location == location)
-+ return;
-+ m_cursor_location = location;
-+ }
-+
-+
-+ public bool is_candidate_panel_mode() {
-+ return m_candidate_panel_mode;
-+ }
-+
-+
- public static bool has_loaded_emoji_dict() {
- if (m_emoji_to_data_dict == null)
- return false;
-@@ -2165,6 +2609,10 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- }
-
-
-+ public static string get_annotation_lang() {
-+ return m_current_lang_id;
-+ }
-+
- public static void set_emoji_font(string? emoji_font) {
- return_if_fail(emoji_font != null && emoji_font != "");
- Pango.FontDescription font_desc =
-@@ -2182,18 +2630,21 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- m_has_partial_match = has_partial_match;
- }
-
-+
- public static void set_partial_match_length(int length) {
- if (length < 1)
- return;
- m_partial_match_length = length;
- }
-
-+
- public static void set_partial_match_condition(int condition) {
- if (condition < 0)
- return;
- m_partial_match_condition = condition;
- }
-
-+
- public static void set_favorites(string[]? unowned_favorites,
- string[]? unowned_favorite_annotations) {
- m_favorites = {};
-diff --git a/ui/gtk3/emojierapp.vala b/ui/gtk3/emojierapp.vala
-index 9506a945..787d448f 100644
---- a/ui/gtk3/emojierapp.vala
-+++ b/ui/gtk3/emojierapp.vala
-@@ -28,8 +28,9 @@ int partial_match_condition = -1;
-
- public class EmojiApplication : Gtk.Application {
- private IBusEmojier? m_emojier;
-- GLib.Settings m_settings_emoji =
-+ private GLib.Settings m_settings_emoji =
- new GLib.Settings("org.freedesktop.ibus.panel.emoji");
-+ private ApplicationCommandLine? m_command_line = null;
-
-
- private EmojiApplication() {
-@@ -40,25 +41,39 @@ public class EmojiApplication : Gtk.Application {
-
-
- private void show_dialog(ApplicationCommandLine command_line) {
-- m_emojier = new IBusEmojier();
-- // For title handling in gnome-shell
-- add_window(m_emojier);
-- Gdk.Event event = Gtk.get_current_event();
-- // Plasma and GNOME3 desktop returns null event
-- if (event == null) {
-- event = new Gdk.Event(Gdk.EventType.KEY_PRESS);
-- event.key.time = Gdk.CURRENT_TIME;
-- // event.get_seat() refers event.any.window
-- event.key.window = Gdk.get_default_root_window();
-- event.key.window.ref();
-+ m_command_line = command_line;
-+ m_emojier.reset();
-+ m_emojier.set_annotation("");
-+ m_emojier.show_all();
-+ }
-+
-+
-+ public void candidate_clicked_lookup_table(uint index,
-+ uint button,
-+ uint state) {
-+ if (m_command_line == null)
-+ return;
-+ if (button == IBusEmojier.BUTTON_CLOSE_BUTTON) {
-+ m_emojier.hide();
-+ m_command_line.print("%s\n", _("Canceled to choose an emoji."));
-+ m_command_line = null;
-+ return;
- }
-- string emoji = m_emojier.run("", event);
-- remove_window(m_emojier);
-- if (emoji == null) {
-- m_emojier = null;
-- command_line.print("%s\n", _("Canceled to choose an emoji."));
-+ if (m_emojier == null)
-+ return;
-+ bool show_candidate = false;
-+ uint ncandidates = m_emojier.get_number_of_candidates();
-+ if (ncandidates > 0 && ncandidates >= index) {
-+ m_emojier.set_cursor_pos(index);
-+ show_candidate = m_emojier.has_variants(index);
-+ } else {
-+ return;
-+ }
-+ if (show_candidate) {
- return;
- }
-+ string emoji = m_emojier.get_current_candidate();
-+ m_emojier.hide();
- Gtk.Clipboard clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD);
- clipboard.set_text(emoji, -1);
- clipboard.store();
-@@ -75,9 +90,8 @@ public class EmojiApplication : Gtk.Application {
- emojier_favorites += emoji;
- m_settings_emoji.set_strv("favorites", emojier_favorites);
- }
--
-- m_emojier = null;
-- command_line.print("%s\n", _("Copied an emoji to your clipboard."));
-+ m_command_line.print("%s\n", _("Copied an emoji to your clipboard."));
-+ m_command_line = null;
- }
-
-
-@@ -88,7 +102,7 @@ public class EmojiApplication : Gtk.Application {
- }
-
-
-- private int _command_line (ApplicationCommandLine command_line) {
-+ private int _command_line(ApplicationCommandLine command_line) {
- // Set default font size
- IBusEmojier.set_emoji_font(m_settings_emoji.get_string("font"));
-
-@@ -181,13 +195,22 @@ public class EmojiApplication : Gtk.Application {
-
- IBusEmojier.load_unicode_dict();
-
-+ if (m_emojier == null) {
-+ m_emojier = new IBusEmojier();
-+ // For title handling in gnome-shell
-+ add_window(m_emojier);
-+ m_emojier.candidate_clicked.connect((i, b, s) => {
-+ candidate_clicked_lookup_table(i, b, s);
-+ });
-+ }
-+
- activate_dialog(command_line);
-
- return Posix.EXIT_SUCCESS;
- }
-
-
-- public override int command_line (ApplicationCommandLine command_line) {
-+ public override int command_line(ApplicationCommandLine command_line) {
- // keep the application running until we are done with this commandline
- this.hold();
- int result = _command_line(command_line);
-@@ -196,6 +219,13 @@ public class EmojiApplication : Gtk.Application {
- }
-
-
-+ public override void shutdown() {
-+ base.shutdown();
-+ remove_window(m_emojier);
-+ m_emojier = null;
-+ }
-+
-+
- public static int main (string[] args) {
- GLib.Intl.bindtextdomain(Config.GETTEXT_PACKAGE,
- Config.GLIB_LOCALE_DIR);
-diff --git a/ui/gtk3/extension.vala b/ui/gtk3/extension.vala
-index 7d6d76e7..c729fd7e 100644
---- a/ui/gtk3/extension.vala
-+++ b/ui/gtk3/extension.vala
-@@ -50,20 +50,20 @@ class ExtensionGtk : Gtk.Application {
- "org.freedesktop.DBus",
- "NameAcquired",
- "/org/freedesktop/DBus",
-- IBus.SERVICE_PANEL_EXTENSION,
-+ IBus.SERVICE_PANEL_EXTENSION_EMOJI,
- DBusSignalFlags.NONE,
- bus_name_acquired_cb);
- connection.signal_subscribe("org.freedesktop.DBus",
- "org.freedesktop.DBus",
- "NameLost",
- "/org/freedesktop/DBus",
-- IBus.SERVICE_PANEL_EXTENSION,
-+ IBus.SERVICE_PANEL_EXTENSION_EMOJI,
- DBusSignalFlags.NONE,
- bus_name_lost_cb);
- var flags =
- IBus.BusNameFlag.ALLOW_REPLACEMENT |
- IBus.BusNameFlag.REPLACE_EXISTING;
-- m_bus.request_name(IBus.SERVICE_PANEL_EXTENSION, flags);
-+ m_bus.request_name(IBus.SERVICE_PANEL_EXTENSION_EMOJI, flags);
- }
-
-
-diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala
-index d9238c89..4c3b00ca 100644
---- a/ui/gtk3/panel.vala
-+++ b/ui/gtk3/panel.vala
-@@ -1148,26 +1148,15 @@ class Panel : IBus.PanelService {
- #if EMOJI_DICT
- item = new Gtk.MenuItem.with_label(_("Emoji Choice"));
- item.activate.connect((i) => {
-- Gdk.Event event = Gtk.get_current_event();
-- if (event == null) {
-- event = new Gdk.Event(Gdk.EventType.KEY_PRESS);
-- event.key.time = Gdk.CURRENT_TIME;
-- // event.get_seat() refers event.any.window
-- event.key.window = Gdk.get_default_root_window();
-- event.key.window.ref();
-- }
-- IBus.XEvent xevent = new IBus.XEvent(
-- "event-type", IBus.XEventType.KEY_PRESS,
-- "window",
-- (event.key.window as Gdk.X11.Window).get_xid(),
-- "time", event.key.time,
-- "purpose", "emoji");
-- /* new GLib.Variant("(sv)", "emoji", xevent.serialize_object())
-+ IBus.ExtensionEvent event = new IBus.ExtensionEvent(
-+ "name", "emoji", "is-enabled", true,
-+ "params", "category-list");
-+ /* new GLib.Variant("(sv)", "emoji", event.serialize_object())
- * will call g_variant_unref() for the child variant by vala.
- * I have no idea not to unref the object so integrated
-- * the purpose to IBus.XEvent above.
-+ * the purpose to IBus.ExtensionEvent above.
- */
-- panel_extension(xevent.serialize_object());
-+ panel_extension(event);
- });
- m_sys_menu.append(item);
- #endif
-diff --git a/ui/gtk3/panelbinding.vala b/ui/gtk3/panelbinding.vala
-index 581f721e..52b78c17 100644
---- a/ui/gtk3/panelbinding.vala
-+++ b/ui/gtk3/panelbinding.vala
-@@ -21,7 +21,193 @@
- * USA
- */
-
-+class Preedit : Gtk.Window {
-+ private Gtk.Label m_extension_preedit_text;
-+ private Gtk.Label m_extension_preedit_emoji;
-+ private IBus.Text? m_engine_preedit_text;
-+ private bool m_engine_preedit_text_show;
-+ private uint m_engine_preedit_cursor_pos;
-+ private string m_prefix = "@";
-+ private bool m_is_shown = true;
-+
-+
-+ public Preedit() {
-+ GLib.Object(
-+ name : "IBusPreedit",
-+ type: Gtk.WindowType.POPUP
-+ );
-+ m_extension_preedit_text = new Gtk.Label("");
-+ m_extension_preedit_emoji = new Gtk.Label("");
-+ }
-+
-+
-+ public new void hide() {
-+ reset();
-+ base.hide();
-+ m_is_shown = false;
-+ }
-+
-+
-+ public bool is_shown() {
-+ return m_is_shown;
-+ }
-+
-+
-+ public void reset() {
-+ set_emoji("");
-+ set_text("");
-+ resize(1, 1);
-+ m_is_shown = true;
-+ }
-+
-+ public void append_text(string text) {
-+ if (text.length == 0)
-+ return;
-+ string total = m_extension_preedit_text.get_text();
-+ total += text;
-+ m_extension_preedit_text.set_text(total);
-+ }
-+
-+
-+ public string get_text() {
-+ return m_extension_preedit_text.get_text();
-+ }
-+
-+
-+ public void set_text(string text) {
-+ m_extension_preedit_text.set_text(text);
-+ }
-+
-+
-+ public string get_emoji() {
-+ return m_extension_preedit_emoji.get_text();
-+ }
-+
-+
-+ public void set_emoji(string text) {
-+ m_extension_preedit_emoji.set_text(text);
-+ }
-+
-+
-+ public bool backspace() {
-+ string total = m_extension_preedit_emoji.get_text();
-+ if (total.length > 0) {
-+ m_extension_preedit_emoji.set_text("");
-+ resize(1, 1);
-+ return false;
-+ }
-+ total = m_extension_preedit_text.get_text();
-+ int char_count = total.char_count();
-+ if (char_count == 0)
-+ return true;
-+ total = total[0:total.index_of_nth_char(char_count - 1)];
-+ resize(1, 1);
-+ m_extension_preedit_text.set_text(total);
-+ if (total.length == 0)
-+ resize(1, 1);
-+ return true;
-+ }
-+
-+
-+ private string get_extension_text () {
-+ string extension_text = m_extension_preedit_emoji.get_text();
-+ if (extension_text.length == 0)
-+ extension_text = m_extension_preedit_text.get_text();
-+ return m_prefix + extension_text;
-+ }
-+
-+
-+ private void set_preedit_color(IBus.Text text,
-+ uint start_index,
-+ uint end_index) {
-+ text.append_attribute(IBus.AttrType.UNDERLINE,
-+ IBus.AttrUnderline.SINGLE,
-+ start_index, (int)end_index);
-+ }
-+
-+
-+ public IBus.Text get_engine_preedit_text() {
-+ string extension_text = get_extension_text();
-+ uint char_count = extension_text.char_count();
-+ IBus.Text retval;
-+ if (m_engine_preedit_text == null || !m_engine_preedit_text_show) {
-+ retval = new IBus.Text.from_string(extension_text);
-+ set_preedit_color(retval, 0, char_count);
-+ return retval;
-+ }
-+ retval = new IBus.Text.from_string(
-+ extension_text + m_engine_preedit_text.get_text());
-+ set_preedit_color(retval, 0, char_count);
-+
-+ unowned IBus.AttrList attrs = m_engine_preedit_text.get_attributes();
-+
-+ if (attrs == null)
-+ return retval;
-+
-+ int i = 0;
-+ while (true) {
-+ IBus.Attribute attr = attrs.get(i++);
-+ if (attr == null)
-+ break;
-+ long start_index = attr.start_index;
-+ long end_index = attr.end_index;
-+ if (start_index < 0)
-+ start_index = 0;
-+ if (end_index < 0)
-+ end_index = m_engine_preedit_text.get_length();
-+ retval.append_attribute(attr.type, attr.value,
-+ char_count + (uint)start_index,
-+ (int)char_count + (int)end_index);
-+ }
-+ return retval;
-+ }
-+
-+
-+ public void set_engine_preedit_text(IBus.Text? text) {
-+ m_engine_preedit_text = text;
-+ }
-+
-+
-+ public void show_engine_preedit_text() {
-+ m_engine_preedit_text_show = true;
-+ }
-+
-+
-+ public void hide_engine_preedit_text() {
-+ m_engine_preedit_text_show = false;
-+ }
-+
-+
-+ public uint get_engine_preedit_cursor_pos() {
-+ return get_extension_text().char_count() + m_engine_preedit_cursor_pos;
-+ }
-+
-+
-+ public void set_engine_preedit_cursor_pos(uint cursor_pos) {
-+ m_engine_preedit_cursor_pos = cursor_pos;
-+ }
-+
-+
-+ public IBus.Text get_commit_text() {
-+ string extension_text = m_extension_preedit_emoji.get_text();
-+ if (extension_text.length == 0)
-+ extension_text = m_extension_preedit_text.get_text();
-+ return new IBus.Text.from_string(extension_text);
-+ }
-+
-+
-+ public void set_extension_name(string extension_name) {
-+ if (extension_name.length == 0)
-+ m_prefix = "@";
-+ else
-+ m_prefix = extension_name[0:1];
-+ }
-+}
-+
-+
- class PanelBinding : IBus.PanelService {
-+ private bool m_is_wayland;
-+ private bool m_wayland_lookup_table_is_visible;
- private IBus.Bus m_bus;
- private Gtk.Application m_application;
- private GLib.Settings m_settings_panel = null;
-@@ -38,18 +224,26 @@ class PanelBinding : IBus.PanelService {
- private bool m_loaded_emoji = false;
- private bool m_load_unicode_at_startup;
- private bool m_loaded_unicode = false;
-+ private bool m_enable_extension;
-+ private string m_extension_name = "";
-+ private Preedit m_preedit;
-
- public PanelBinding(IBus.Bus bus,
- Gtk.Application application) {
- GLib.assert(bus.is_connected());
- // Chain up base class constructor
- GLib.Object(connection : bus.get_connection(),
-- object_path : IBus.PATH_PANEL_EXTENSION);
-+ object_path : IBus.PATH_PANEL_EXTENSION_EMOJI);
-+
-+ Type instance_type = Gdk.Display.get_default().get_type();
-+ Type wayland_type = typeof(GdkWayland.Display);
-+ m_is_wayland = instance_type.is_a(wayland_type);
-
- m_bus = bus;
- m_application = application;
-
- init_settings();
-+ m_preedit = new Preedit();
- }
-
-
-@@ -69,12 +263,20 @@ class PanelBinding : IBus.PanelService {
- ref m_css_provider);
- });
-
-+ m_settings_emoji.changed["unicode-hotkey"].connect((key) => {
-+ set_emoji_hotkey();
-+ });
-+
- m_settings_emoji.changed["font"].connect((key) => {
- BindingCommon.set_custom_font(m_settings_panel,
- m_settings_emoji,
- ref m_css_provider);
- });
-
-+ m_settings_emoji.changed["hotkey"].connect((key) => {
-+ set_emoji_hotkey();
-+ });
-+
- m_settings_emoji.changed["favorites"].connect((key) => {
- set_emoji_favorites();
- });
-@@ -109,6 +311,54 @@ class PanelBinding : IBus.PanelService {
- }
-
-
-+ private unowned
-+ IBus.ProcessKeyEventData? parse_accelerator(string accelerator) {
-+ IBus.ProcessKeyEventData key = {};
-+ uint keysym = 0;
-+ IBus.ModifierType modifiers = 0;
-+ IBus.accelerator_parse(accelerator,
-+ out keysym, out modifiers);
-+ if (keysym == 0U && modifiers == 0) {
-+ warning("Failed to parse shortcut key '%s'".printf(accelerator));
-+ return null;
-+ }
-+ if ((modifiers & IBus.ModifierType.SUPER_MASK) != 0) {
-+ modifiers ^= IBus.ModifierType.SUPER_MASK;
-+ modifiers |= IBus.ModifierType.MOD4_MASK;
-+ }
-+ key.keyval = keysym;
-+ key.state = modifiers;
-+ return key;
-+ }
-+
-+
-+ private void set_emoji_hotkey() {
-+ IBus.ProcessKeyEventData[] emoji_keys = {};
-+ IBus.ProcessKeyEventData key;
-+ string[] accelerators = m_settings_emoji.get_strv("hotkey");
-+ foreach (var accelerator in accelerators) {
-+ key = parse_accelerator(accelerator);
-+ emoji_keys += key;
-+ }
-+
-+ /* Since {} is not allocated, parse_accelerator() should be unowned. */
-+ key = {};
-+ emoji_keys += key;
-+
-+ IBus.ProcessKeyEventData[] unicode_keys = {};
-+ accelerators = m_settings_emoji.get_strv("unicode-hotkey");
-+ foreach (var accelerator in accelerators) {
-+ key = parse_accelerator(accelerator);
-+ unicode_keys += key;
-+ }
-+ key = {};
-+ unicode_keys += key;
-+
-+ panel_extension_register_keys("emoji", emoji_keys,
-+ "unicode", unicode_keys);
-+ }
-+
-+
- private void set_emoji_favorites() {
- m_emojier_favorites = m_settings_emoji.get_strv("favorites");
- IBusEmojier.set_favorites(
-@@ -159,6 +409,7 @@ class PanelBinding : IBus.PanelService {
-
- public void load_settings() {
-
-+ set_emoji_hotkey();
- set_load_emoji_at_startup();
- set_load_unicode_at_startup();
- BindingCommon.set_custom_font(m_settings_panel,
-@@ -181,36 +432,37 @@ class PanelBinding : IBus.PanelService {
- GLib.Source.remove(m_emojier_set_emoji_lang_id);
- m_emojier_set_emoji_lang_id = 0;
- }
-- m_application = null;
-- }
--
--
-- private void show_emojier(Gdk.Event event) {
-- if (!m_loaded_emoji)
-- set_emoji_lang();
-- if (!m_loaded_unicode && m_loaded_emoji) {
-- IBusEmojier.load_unicode_dict();
-- m_loaded_unicode = true;
-- }
-- m_emojier = new IBusEmojier();
-- // For title handling in gnome-shell
-- m_application.add_window(m_emojier);
-- string emoji = m_emojier.run(m_real_current_context_path, event);
-- m_application.remove_window(m_emojier);
-- if (emoji == null) {
-+ if (m_emojier != null) {
-+ m_application.remove_window(m_emojier);
- m_emojier = null;
-- return;
- }
-- this.emojier_focus_commit();
-+ m_application = null;
- }
-
-
-- private void handle_emoji_typing(Gdk.Event event) {
-- if (m_emojier != null && m_emojier.is_running()) {
-- m_emojier.present_centralize(event);
-+ private void commit_text_update_favorites(IBus.Text text) {
-+ commit_text(text);
-+ IBus.ExtensionEvent event = new IBus.ExtensionEvent(
-+ "name", m_extension_name,
-+ "is-enabled", false,
-+ "is-extension", true);
-+ panel_extension(event);
-+ string committed_string = text.text;
-+ string preedit_string = m_preedit.get_text();
-+ m_preedit.hide();
-+ if (preedit_string == committed_string)
- return;
-+ bool has_favorite = false;
-+ foreach (unowned string favorite in m_emojier_favorites) {
-+ if (favorite == committed_string) {
-+ has_favorite = true;
-+ break;
-+ }
-+ }
-+ if (!has_favorite) {
-+ m_emojier_favorites += committed_string;
-+ m_settings_emoji.set_strv("favorites", m_emojier_favorites);
- }
-- show_emojier(event);
- }
-
-
-@@ -223,19 +475,8 @@ class PanelBinding : IBus.PanelService {
- prev_context_path != "" &&
- prev_context_path == m_current_context_path) {
- IBus.Text text = new IBus.Text.from_string(selected_string);
-- commit_text(text);
-- m_emojier = null;
-- bool has_favorite = false;
-- foreach (unowned string favorite in m_emojier_favorites) {
-- if (favorite == selected_string) {
-- has_favorite = true;
-- break;
-- }
-- }
-- if (!has_favorite) {
-- m_emojier_favorites += selected_string;
-- m_settings_emoji.set_strv("favorites", m_emojier_favorites);
-- }
-+ commit_text_update_favorites(text);
-+ m_emojier.reset();
- return true;
- }
-
-@@ -249,8 +490,7 @@ class PanelBinding : IBus.PanelService {
- string selected_string = m_emojier.get_selected_string();
- string prev_context_path = m_emojier.get_input_context_path();
- if (selected_string == null &&
-- prev_context_path != "" &&
-- m_emojier.is_running()) {
-+ prev_context_path != "") {
- var context = GLib.MainContext.default();
- if (m_emojier_focus_commit_text_id > 0 &&
- context.find_source_by_id(m_emojier_focus_commit_text_id)
-@@ -277,6 +517,243 @@ class PanelBinding : IBus.PanelService {
- }
-
-
-+ private bool key_press_escape() {
-+ if (is_emoji_lookup_table()) {
-+ bool show_candidate = m_emojier.key_press_escape();
-+ convert_preedit_text();
-+ return show_candidate;
-+ }
-+ if (m_preedit.get_emoji() != "") {
-+ m_preedit.set_emoji("");
-+ string annotation = m_preedit.get_text();
-+ m_emojier.set_annotation(annotation);
-+ return false;
-+ }
-+ m_enable_extension = false;
-+ hide_emoji_lookup_table();
-+ m_preedit.hide();
-+ IBus.ExtensionEvent event = new IBus.ExtensionEvent(
-+ "name", m_extension_name,
-+ "is-enabled", false,
-+ "is-extension", true);
-+ panel_extension(event);
-+ return false;
-+ }
-+
-+
-+ private bool key_press_enter() {
-+ if (m_extension_name != "unicode" && is_emoji_lookup_table()) {
-+ // Check if variats exist
-+ if (m_emojier.key_press_enter())
-+ return true;
-+ }
-+ IBus.Text text = m_preedit.get_commit_text();
-+ commit_text_update_favorites(text);
-+ return false;
-+ }
-+
-+
-+ private void convert_preedit_text() {
-+ if (m_emojier.get_number_of_candidates() > 0)
-+ m_preedit.set_emoji(m_emojier.get_current_candidate());
-+ else
-+ m_preedit.set_emoji("");
-+ }
-+
-+
-+ private bool key_press_space() {
-+ bool show_candidate = false;
-+ if (m_preedit.get_emoji() != "") {
-+ m_emojier.key_press_cursor_horizontal(Gdk.Key.Right, 0);
-+ show_candidate = true;
-+ } else {
-+ string annotation = m_preedit.get_text();
-+ if (annotation.length == 0) {
-+ show_candidate = true;
-+ if (is_emoji_lookup_table())
-+ m_emojier.key_press_cursor_horizontal(Gdk.Key.Right, 0);
-+ } else {
-+ m_emojier.set_annotation(annotation);
-+ }
-+ }
-+ convert_preedit_text();
-+ return show_candidate;
-+ }
-+
-+
-+ private bool key_press_cursor_horizontal(uint keyval,
-+ uint modifiers) {
-+ if (is_emoji_lookup_table()) {
-+ m_emojier.key_press_cursor_horizontal(keyval, modifiers);
-+ convert_preedit_text();
-+ return true;
-+ }
-+ return false;
-+ }
-+
-+
-+ private bool key_press_cursor_vertical(uint keyval,
-+ uint modifiers) {
-+ if (is_emoji_lookup_table()) {
-+ m_emojier.key_press_cursor_vertical(keyval, modifiers);
-+ convert_preedit_text();
-+ return true;
-+ }
-+ return false;
-+ }
-+
-+
-+ private bool key_press_cursor_home_end(uint keyval,
-+ uint modifiers) {
-+ if (is_emoji_lookup_table()) {
-+ m_emojier.key_press_cursor_home_end(keyval, modifiers);
-+ convert_preedit_text();
-+ return true;
-+ }
-+ return false;
-+ }
-+
-+
-+ private bool key_press_control_keyval(uint keyval,
-+ uint modifiers) {
-+ bool show_candidate = false;
-+ switch(keyval) {
-+ case Gdk.Key.f:
-+ show_candidate = key_press_cursor_horizontal(Gdk.Key.Right,
-+ modifiers);
-+ break;
-+ case Gdk.Key.b:
-+ show_candidate = key_press_cursor_horizontal(Gdk.Key.Left,
-+ modifiers);
-+ break;
-+ case Gdk.Key.n:
-+ case Gdk.Key.N:
-+ show_candidate = key_press_cursor_vertical(Gdk.Key.Down, modifiers);
-+ break;
-+ case Gdk.Key.p:
-+ case Gdk.Key.P:
-+ show_candidate = key_press_cursor_vertical(Gdk.Key.Up, modifiers);
-+ break;
-+ case Gdk.Key.h:
-+ show_candidate = key_press_cursor_home_end(Gdk.Key.Home, modifiers);
-+ break;
-+ case Gdk.Key.e:
-+ show_candidate = key_press_cursor_home_end(Gdk.Key.End, modifiers);
-+ break;
-+ case Gdk.Key.u:
-+ m_preedit.reset();
-+ m_emojier.set_annotation("");
-+ hide_emoji_lookup_table();
-+ break;
-+ case Gdk.Key.C:
-+ case Gdk.Key.c:
-+ if ((modifiers & Gdk.ModifierType.SHIFT_MASK) != 0) {
-+ if (!m_is_wayland && m_emojier != null &&
-+ m_emojier.get_number_of_candidates() > 0) {
-+ var text = m_emojier.get_current_candidate();
-+ Gtk.Clipboard clipboard =
-+ Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD);
-+ clipboard.set_text(text, -1);
-+ clipboard.store();
-+ }
-+ show_candidate = is_emoji_lookup_table();
-+ }
-+ break;
-+ default:
-+ show_candidate = is_emoji_lookup_table();
-+ break;
-+ }
-+ return show_candidate;
-+ }
-+
-+
-+ private void hide_wayland_lookup_table() {
-+ m_wayland_lookup_table_is_visible = false;
-+ var text = new IBus.Text.from_string("");
-+ update_auxiliary_text_received(text, false);
-+ update_lookup_table_received(
-+ new IBus.LookupTable(1, 0, false, true),
-+ false);
-+ }
-+
-+
-+ private void show_wayland_lookup_table(IBus.Text text) {
-+ m_wayland_lookup_table_is_visible = true;
-+ var table = m_emojier.get_one_dimension_lookup_table();
-+ uint ncandidates = table.get_number_of_candidates();
-+ update_auxiliary_text_received(
-+ text,
-+ ncandidates > 0 ? true : false);
-+ update_lookup_table_received(
-+ table,
-+ ncandidates > 0 ? true : false);
-+ }
-+
-+
-+ private bool is_visible_wayland_lookup_table() {
-+ return m_wayland_lookup_table_is_visible;
-+ }
-+
-+
-+ private void hide_emoji_lookup_table() {
-+ if (m_emojier == null)
-+ return;
-+ if (m_is_wayland)
-+ hide_wayland_lookup_table();
-+ else
-+ m_emojier.hide();
-+ }
-+
-+
-+ private void show_emoji_lookup_table() {
-+ /* Emojier category_list is shown in both Xorg and Wayland
-+ * because the annotation information is useful but the Wayland lookup
-+ * window is alway one dimension. So the category_list is shown
-+ * when the user annotation is null.
-+ */
-+ if (m_is_wayland && m_preedit.get_text() != "") {
-+ var text = m_emojier.get_title_text();
-+ show_wayland_lookup_table(text);
-+ } else {
-+ // POPUP window takes the focus in Wayland.
-+ if (m_is_wayland)
-+ m_emojier.set_input_context_path(m_real_current_context_path);
-+ m_emojier.show_all();
-+ }
-+ }
-+
-+
-+ private bool is_emoji_lookup_table() {
-+ if (m_is_wayland)
-+ return is_visible_wayland_lookup_table();
-+ else
-+ return m_emojier.get_visible();
-+ }
-+
-+
-+ private void show_preedit_and_candidate(bool show_candidate) {
-+ uint cursor_pos = 0;
-+ if (!show_candidate)
-+ cursor_pos = m_preedit.get_engine_preedit_cursor_pos();
-+ update_preedit_text_received(
-+ m_preedit.get_engine_preedit_text(),
-+ cursor_pos,
-+ true);
-+ if (!show_candidate) {
-+ hide_emoji_lookup_table();
-+ return;
-+ }
-+ if (m_emojier == null)
-+ return;
-+ /* Wayland gives the focus on Emojir which is a GTK popup window
-+ * and move the focus fom the current input context to Emojier.
-+ * This forwards the lookup table to gnome-shell's lookup table
-+ * but it enables one dimension lookup table only.
-+ */
-+ show_emoji_lookup_table();
-+ }
-+
-+
- public override void focus_in(string input_context_path) {
- m_current_context_path = input_context_path;
-
-@@ -299,48 +776,280 @@ class PanelBinding : IBus.PanelService {
- }
-
-
-- public override void panel_extension_received(GLib.Variant data) {
-- IBus.XEvent? xevent = IBus.Serializable.deserialize_object(data)
-- as IBus.XEvent;
-- if (xevent == null) {
-- warning ("Failed to deserialize IBusXEvent");
-+ public override void panel_extension_received(IBus.ExtensionEvent event) {
-+ m_extension_name = event.get_name();
-+ if (m_extension_name != "emoji" && m_extension_name != "unicode") {
-+ string format = "The name %s is not implemented in PanelExtension";
-+ warning (format.printf(m_extension_name));
-+ m_extension_name = "";
- return;
- }
-- if (xevent.get_purpose() != "emoji") {
-- string format = "The purpose %s is not implemented in PanelExtension";
-- warning (format.printf(xevent.get_purpose()));
-+ m_enable_extension = event.is_enabled;
-+ if (!m_enable_extension) {
-+ hide_emoji_lookup_table();
-+ return;
-+ }
-+ if (!m_loaded_emoji)
-+ set_emoji_lang();
-+ if (!m_loaded_unicode && m_loaded_emoji) {
-+ IBusEmojier.load_unicode_dict();
-+ m_loaded_unicode = true;
-+ }
-+ if (m_emojier == null) {
-+ m_emojier = new IBusEmojier();
-+ // For title handling in gnome-shell
-+ m_application.add_window(m_emojier);
-+ m_emojier.candidate_clicked.connect((i, b, s) => {
-+ if (!m_is_wayland)
-+ candidate_clicked_lookup_table(i, b, s);
-+ });
-+ }
-+ m_emojier.reset();
-+ m_emojier.set_annotation("");
-+ m_preedit.set_extension_name(m_extension_name);
-+ m_preedit.reset();
-+ update_preedit_text_received(
-+ m_preedit.get_engine_preedit_text(),
-+ m_preedit.get_engine_preedit_cursor_pos(),
-+ true);
-+ string params = event.get_params();
-+ if (params == "category-list") {
-+ key_press_space();
-+ show_preedit_and_candidate(true);
-+ }
-+ }
-+
-+
-+ public override void set_cursor_location(int x,
-+ int y,
-+ int width,
-+ int height) {
-+ if (m_emojier != null)
-+ m_emojier.set_cursor_location(x, y, width, height);
-+ }
-+
-+
-+ public override void update_preedit_text(IBus.Text text,
-+ uint cursor_pos,
-+ bool visible) {
-+ m_preedit.set_engine_preedit_text(text);
-+ if (visible)
-+ m_preedit.show_engine_preedit_text();
-+ else
-+ m_preedit.hide_engine_preedit_text();
-+ m_preedit.set_engine_preedit_cursor_pos(cursor_pos);
-+ update_preedit_text_received(m_preedit.get_engine_preedit_text(),
-+ m_preedit.get_engine_preedit_cursor_pos(),
-+ visible);
-+ }
-+
-+
-+ public override void show_preedit_text() {
-+ m_preedit.show_engine_preedit_text();
-+ show_preedit_and_candidate(false);
-+ }
-+
-+
-+ public override void hide_preedit_text() {
-+ m_preedit.hide_engine_preedit_text();
-+ show_preedit_and_candidate(false);
-+ }
-+
-+
-+ public override bool process_key_event(uint keyval,
-+ uint keycode,
-+ uint state) {
-+ if ((state & IBus.ModifierType.RELEASE_MASK) != 0)
-+ return false;
-+ uint modifiers = state;
-+ bool show_candidate = false;
-+ switch(keyval) {
-+ case Gdk.Key.Escape:
-+ show_candidate = key_press_escape();
-+ if (!m_preedit.is_shown())
-+ return true;
-+ break;
-+ case Gdk.Key.Return:
-+ case Gdk.Key.KP_Enter:
-+ if (m_extension_name == "unicode")
-+ key_press_space();
-+ show_candidate = key_press_enter();
-+ if (!m_preedit.is_shown()) {
-+ hide_emoji_lookup_table();
-+ return true;
-+ }
-+ break;
-+ case Gdk.Key.BackSpace:
-+ m_preedit.backspace();
-+ string annotation = m_preedit.get_text();
-+ if (annotation == "" && m_extension_name == "unicode") {
-+ key_press_escape();
-+ return true;
-+ }
-+ m_emojier.set_annotation(annotation);
-+ break;
-+ case Gdk.Key.space:
-+ case Gdk.Key.KP_Space:
-+ show_candidate = key_press_space();
-+ if (m_extension_name == "unicode") {
-+ key_press_enter();
-+ return true;
-+ }
-+ break;
-+ case Gdk.Key.Right:
-+ case Gdk.Key.KP_Right:
-+ /* one dimension in Wayland, two dimensions in X11 */
-+ if (m_is_wayland) {
-+ show_candidate = key_press_cursor_vertical(Gdk.Key.Down,
-+ modifiers);
-+ } else {
-+ show_candidate = key_press_cursor_horizontal(Gdk.Key.Right,
-+ modifiers);
-+ }
-+ break;
-+ case Gdk.Key.Left:
-+ case Gdk.Key.KP_Left:
-+ if (m_is_wayland) {
-+ show_candidate = key_press_cursor_vertical(Gdk.Key.Up,
-+ modifiers);
-+ } else {
-+ show_candidate = key_press_cursor_horizontal(Gdk.Key.Left,
-+ modifiers);
-+ }
-+ break;
-+ case Gdk.Key.Down:
-+ case Gdk.Key.KP_Down:
-+ if (m_is_wayland) {
-+ show_candidate = key_press_cursor_horizontal(Gdk.Key.Right,
-+ modifiers);
-+ } else {
-+ show_candidate = key_press_cursor_vertical(Gdk.Key.Down,
-+ modifiers);
-+ }
-+ break;
-+ case Gdk.Key.Up:
-+ case Gdk.Key.KP_Up:
-+ if (m_is_wayland) {
-+ show_candidate = key_press_cursor_horizontal(Gdk.Key.Left,
-+ modifiers);
-+ } else {
-+ show_candidate = key_press_cursor_vertical(Gdk.Key.Up,
-+ modifiers);
-+ }
-+ break;
-+ case Gdk.Key.Page_Down:
-+ case Gdk.Key.KP_Page_Down:
-+ if (m_is_wayland) {
-+ show_candidate = key_press_cursor_vertical(Gdk.Key.Down,
-+ modifiers);
-+ } else {
-+ show_candidate = key_press_cursor_vertical(Gdk.Key.Page_Down,
-+ modifiers);
-+ }
-+ break;
-+ case Gdk.Key.Page_Up:
-+ case Gdk.Key.KP_Page_Up:
-+ if (m_is_wayland) {
-+ show_candidate = key_press_cursor_vertical(Gdk.Key.Up,
-+ modifiers);
-+ } else {
-+ show_candidate = key_press_cursor_vertical(Gdk.Key.Page_Up,
-+ modifiers);
-+ }
-+ break;
-+ case Gdk.Key.Home:
-+ case Gdk.Key.KP_Home:
-+ show_candidate = key_press_cursor_home_end(Gdk.Key.Home, modifiers);
-+ break;
-+ case Gdk.Key.End:
-+ case Gdk.Key.KP_End:
-+ show_candidate = key_press_cursor_home_end(Gdk.Key.End, modifiers);
-+ break;
-+ default:
-+ if ((modifiers & Gdk.ModifierType.CONTROL_MASK) != 0) {
-+ show_candidate = key_press_control_keyval(keyval, modifiers);
-+ break;
-+ }
-+ unichar ch = IBus.keyval_to_unicode(keyval);
-+ if (ch.iscntrl())
-+ return true;
-+ string str = ch.to_string();
-+ m_preedit.append_text(str);
-+ string annotation = m_preedit.get_text();
-+ m_emojier.set_annotation(annotation);
-+ m_preedit.set_emoji("");
-+ show_candidate = is_emoji_lookup_table();
-+ break;
-+ }
-+ show_preedit_and_candidate(show_candidate);
-+ return true;
-+ }
-+
-+ public override void commit_text_received(IBus.Text text) {
-+ unowned string? str = text.text;
-+ if (str == null)
-+ return;
-+ /* Do not call convert_preedit_text() because it depends on
-+ * each IME whether process_key_event() receives Shift-space or not.
-+ */
-+ m_preedit.append_text(str);
-+ m_preedit.set_emoji("");
-+ string annotation = m_preedit.get_text();
-+ m_emojier.set_annotation(annotation);
-+ show_preedit_and_candidate(false);
-+ }
-+
-+ public override void page_up_lookup_table() {
-+ bool show_candidate = key_press_cursor_vertical(Gdk.Key.Up, 0);
-+ show_preedit_and_candidate(show_candidate);
-+ }
-+
-+ public override void page_down_lookup_table() {
-+ bool show_candidate = key_press_cursor_vertical(Gdk.Key.Down, 0);
-+ show_preedit_and_candidate(show_candidate);
-+ }
-+
-+ public override void cursor_up_lookup_table() {
-+ bool show_candidate = key_press_cursor_horizontal(Gdk.Key.Left, 0);
-+ show_preedit_and_candidate(show_candidate);
-+ }
-+
-+ public override void cursor_down_lookup_table() {
-+ bool show_candidate = key_press_cursor_horizontal(Gdk.Key.Right, 0);
-+ show_preedit_and_candidate(show_candidate);
-+ }
-+
-+ public override void candidate_clicked_lookup_table(uint index,
-+ uint button,
-+ uint state) {
-+ if (button == IBusEmojier.BUTTON_CLOSE_BUTTON) {
-+ m_enable_extension = false;
-+ hide_emoji_lookup_table();
-+ m_preedit.hide();
-+ IBus.ExtensionEvent event = new IBus.ExtensionEvent(
-+ "name", m_extension_name,
-+ "is-enabled", false,
-+ "is-extension", true);
-+ panel_extension(event);
- return;
- }
-- Gdk.EventType event_type;
-- if (xevent.get_event_type() == IBus.XEventType.KEY_PRESS) {
-- event_type = Gdk.EventType.KEY_PRESS;
-- } else if (xevent.get_event_type() == IBus.XEventType.KEY_RELEASE) {
-- event_type = Gdk.EventType.KEY_RELEASE;
-+ if (m_emojier == null)
-+ return;
-+ bool show_candidate = false;
-+ uint ncandidates = m_emojier.get_number_of_candidates();
-+ if (ncandidates > 0 && ncandidates >= index) {
-+ m_emojier.set_cursor_pos(index);
-+ show_candidate = m_emojier.has_variants(index);
-+ m_preedit.set_emoji(m_emojier.get_current_candidate());
- } else {
-- warning ("Not supported type %d".printf(xevent.get_event_type()));
- return;
- }
-- Gdk.Event event = new Gdk.Event(event_type);
-- uint32 time = xevent.get_time();
-- if (time == 0)
-- time = Gtk.get_current_event_time();
-- event.key.time = time;
-- X.Window xid = xevent.get_window();
-- Gdk.Display? display = Gdk.Display.get_default();
-- Gdk.Window? window = null;
-- if (window == null && xid != 0) {
-- window = Gdk.X11.Window.lookup_for_display(
-- display as Gdk.X11.Display, xid);
-- }
-- if (window == null && xid != 0) {
-- window = new Gdk.X11.Window.foreign_for_display(
-- display as Gdk.X11.Display, xid);
-- }
-- if (window == null) {
-- window = Gdk.get_default_root_window();
-- window.ref();
-- }
-- event.key.window = window;
-- handle_emoji_typing(event);
-+ if (!show_candidate) {
-+ IBus.Text text = m_preedit.get_commit_text();
-+ commit_text_update_favorites(text);
-+ hide_emoji_lookup_table();
-+ return;
-+ }
-+ show_preedit_and_candidate(show_candidate);
- }
- }
---
-2.14.3
-
-From 7cef5bf572596361bc502e8fa917569676a80372 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Wed, 20 Jun 2018 19:01:59 +0900
-Subject: [PATCH] setup: Replace emoji font with Unicode font
-
-Now the font settings of emoji is configurable in the session base
-but not the application base and the current font setting on ibus-setup
-effects on Unicode characters.
-Also fixed the progress bar on Unicode candidate table.
----
- setup/setup.ui | 4 +-
- src/tests/runtest | 2 +-
- ui/gtk3/emojier.vala | 213 ++++++++++++++++++++++++++++-----------------------
- 3 files changed, 120 insertions(+), 99 deletions(-)
-
-diff --git a/setup/setup.ui b/setup/setup.ui
-index f1beb1de..9d9d7ee9 100644
---- a/setup/setup.ui
-+++ b/setup/setup.ui
-@@ -1010,9 +1010,9 @@
- <object class="GtkLabel" id="label_emoji_font">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
-- <property name="tooltip_text" translatable="yes">Set a font of emoji candidates on the emoji dialog</property>
-+ <property name="tooltip_text" translatable="yes">Set a font of Unicode candidates on the emoji dialog</property>
- <property name="halign">start</property>
-- <property name="label" translatable="yes">Emoji font:</property>
-+ <property name="label" translatable="yes">Unicode font:</property>
- <property name="justify">right</property>
- </object>
- <packing>
-diff --git a/src/tests/runtest b/src/tests/runtest
-index b6b845d6..5c163083 100755
---- a/src/tests/runtest
-+++ b/src/tests/runtest
-@@ -142,7 +142,7 @@ run_test_case()
- --daemonize \
- --cache=none \
- --panel=disable \
-- --panel-extension=disable \
-+ --emoji-extension=disable \
- --config=default \
- --verbose;
-
-diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala
-index cd98c9d7..7beb6f0a 100644
---- a/ui/gtk3/emojier.vala
-+++ b/ui/gtk3/emojier.vala
-@@ -253,6 +253,7 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- private static string m_current_lang_id;
- private static string m_emoji_font_family;
- private static int m_emoji_font_size;
-+ private static bool m_emoji_font_changed = false;
- private static string[] m_favorites;
- private static string[] m_favorite_annotations;
- private static int m_emoji_max_seq_len;
-@@ -348,88 +349,20 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- add_action(action);
- if (m_current_lang_id == null)
- m_current_lang_id = "en";
-- if (m_emoji_font_family == null)
-+ if (m_emoji_font_family == null) {
- m_emoji_font_family = "Monospace";
-- if (m_emoji_font_size == 0)
-+ m_emoji_font_changed = true;
-+ }
-+ if (m_emoji_font_size == 0) {
- m_emoji_font_size = 16;
-+ m_emoji_font_changed = true;
-+ }
- if (m_favorites == null)
- m_favorites = {};
- if (m_favorite_annotations == null)
- m_favorite_annotations = {};
-
-- Gdk.Display display = Gdk.Display.get_default();
-- Gdk.Screen screen = (display != null) ?
-- display.get_default_screen() : null;
--
-- if (screen == null) {
-- warning("Could not open display.");
-- return;
-- }
-- // Set en locale because de_DE's decimal_point is ',' instead of '.'
-- string? backup_locale =
-- Intl.setlocale(LocaleCategory.NUMERIC, null).dup();
-- if (Intl.setlocale(LocaleCategory.NUMERIC, "en_US.UTF-8") == null) {
-- if (Intl.setlocale(LocaleCategory.NUMERIC, "C.UTF-8") == null) {
-- if (Intl.setlocale(LocaleCategory.NUMERIC, "C") == null) {
-- warning("You don't install either en_US.UTF-8 or C.UTF-8 " +
-- "or C locale");
-- }
-- }
-- }
-- m_rgba = new ThemedRGBA(this);
-- uint bg_red = (uint)(m_rgba.normal_bg.red * 255);
-- uint bg_green = (uint)(m_rgba.normal_bg.green * 255);
-- uint bg_blue = (uint)(m_rgba.normal_bg.blue * 255);
-- double bg_alpha = m_rgba.normal_bg.alpha;
-- string data =
-- "#IBusEmojierWhiteLabel { background-color: " +
-- "rgba(%u, %u, %u, %lf); ".printf(
-- bg_red, bg_green, bg_blue, bg_alpha) +
-- "font-family: %s; font-size: %dpt; ".printf(
-- m_emoji_font_family, m_emoji_font_size) +
-- "border-width: 4px; border-radius: 3px; } ";
--
-- uint fg_red = (uint)(m_rgba.selected_fg.red * 255);
-- uint fg_green = (uint)(m_rgba.selected_fg.green * 255);
-- uint fg_blue = (uint)(m_rgba.selected_fg.blue * 255);
-- double fg_alpha = m_rgba.selected_fg.alpha;
-- bg_red = (uint)(m_rgba.selected_bg.red * 255);
-- bg_green = (uint)(m_rgba.selected_bg.green * 255);
-- bg_blue = (uint)(m_rgba.selected_bg.blue * 255);
-- bg_alpha = m_rgba.selected_bg.alpha;
-- data += "#IBusEmojierSelectedLabel { color: " +
-- "rgba(%u, %u, %u, %lf); ".printf(
-- fg_red, fg_green, fg_blue, fg_alpha) +
-- "font-family: %s; font-size: %dpt; ".printf(
-- m_emoji_font_family, m_emoji_font_size) +
-- "background-color: " +
-- "rgba(%u, %u, %u, %lf); ".printf(
-- bg_red, bg_green, bg_blue, bg_alpha) +
-- "border-width: 4px; border-radius: 3px; }";
-- data += "#IBusEmojierGoldLabel { color: " +
-- "rgba(%u, %u, %u, %lf); ".printf(
-- fg_red, fg_green, fg_blue, fg_alpha) +
-- "font-family: %s; font-size: %dpt; ".printf(
-- m_emoji_font_family, m_emoji_font_size) +
-- "background-color: #b09c5f; " +
-- "border-width: 4px; border-radius: 3px; }";
--
-- Gtk.CssProvider css_provider = new Gtk.CssProvider();
-- try {
-- css_provider.load_from_data(data, -1);
-- } catch (GLib.Error e) {
-- warning("Failed css_provider_from_data: %s", e.message);
-- return;
-- }
-- if (backup_locale != null)
-- Intl.setlocale(LocaleCategory.NUMERIC, backup_locale);
-- else
-- Intl.setlocale(LocaleCategory.NUMERIC, "");
--
-- Gtk.StyleContext.add_provider_for_screen(
-- screen,
-- css_provider,
-- Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
-+ set_css_data();
-
- m_vbox = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
- add(m_vbox);
-@@ -795,6 +728,84 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- }
-
-
-+ private void set_css_data() {
-+ Gdk.Display display = Gdk.Display.get_default();
-+ Gdk.Screen screen = (display != null) ?
-+ display.get_default_screen() : null;
-+
-+ if (screen == null) {
-+ warning("Could not open display.");
-+ return;
-+ }
-+ // Set en locale because de_DE's decimal_point is ',' instead of '.'
-+ string? backup_locale =
-+ Intl.setlocale(LocaleCategory.NUMERIC, null).dup();
-+ if (Intl.setlocale(LocaleCategory.NUMERIC, "en_US.UTF-8") == null) {
-+ if (Intl.setlocale(LocaleCategory.NUMERIC, "C.UTF-8") == null) {
-+ if (Intl.setlocale(LocaleCategory.NUMERIC, "C") == null) {
-+ warning("You don't install either en_US.UTF-8 or C.UTF-8 " +
-+ "or C locale");
-+ }
-+ }
-+ }
-+ if (m_rgba == null)
-+ m_rgba = new ThemedRGBA(this);
-+ uint bg_red = (uint)(m_rgba.normal_bg.red * 255);
-+ uint bg_green = (uint)(m_rgba.normal_bg.green * 255);
-+ uint bg_blue = (uint)(m_rgba.normal_bg.blue * 255);
-+ double bg_alpha = m_rgba.normal_bg.alpha;
-+ string data =
-+ "#IBusEmojierWhiteLabel { background-color: " +
-+ "rgba(%u, %u, %u, %lf); ".printf(
-+ bg_red, bg_green, bg_blue, bg_alpha) +
-+ "font-family: %s; font-size: %dpt; ".printf(
-+ m_emoji_font_family, m_emoji_font_size) +
-+ "border-width: 4px; border-radius: 3px; } ";
-+
-+ uint fg_red = (uint)(m_rgba.selected_fg.red * 255);
-+ uint fg_green = (uint)(m_rgba.selected_fg.green * 255);
-+ uint fg_blue = (uint)(m_rgba.selected_fg.blue * 255);
-+ double fg_alpha = m_rgba.selected_fg.alpha;
-+ bg_red = (uint)(m_rgba.selected_bg.red * 255);
-+ bg_green = (uint)(m_rgba.selected_bg.green * 255);
-+ bg_blue = (uint)(m_rgba.selected_bg.blue * 255);
-+ bg_alpha = m_rgba.selected_bg.alpha;
-+ data += "#IBusEmojierSelectedLabel { color: " +
-+ "rgba(%u, %u, %u, %lf); ".printf(
-+ fg_red, fg_green, fg_blue, fg_alpha) +
-+ "font-family: %s; font-size: %dpt; ".printf(
-+ m_emoji_font_family, m_emoji_font_size) +
-+ "background-color: " +
-+ "rgba(%u, %u, %u, %lf); ".printf(
-+ bg_red, bg_green, bg_blue, bg_alpha) +
-+ "border-width: 4px; border-radius: 3px; }";
-+ data += "#IBusEmojierGoldLabel { color: " +
-+ "rgba(%u, %u, %u, %lf); ".printf(
-+ fg_red, fg_green, fg_blue, fg_alpha) +
-+ "font-family: %s; font-size: %dpt; ".printf(
-+ m_emoji_font_family, m_emoji_font_size) +
-+ "background-color: #b09c5f; " +
-+ "border-width: 4px; border-radius: 3px; }";
-+
-+ Gtk.CssProvider css_provider = new Gtk.CssProvider();
-+ try {
-+ css_provider.load_from_data(data, -1);
-+ } catch (GLib.Error e) {
-+ warning("Failed css_provider_from_data: %s", e.message);
-+ return;
-+ }
-+ if (backup_locale != null)
-+ Intl.setlocale(LocaleCategory.NUMERIC, backup_locale);
-+ else
-+ Intl.setlocale(LocaleCategory.NUMERIC, "");
-+
-+ Gtk.StyleContext.add_provider_for_screen(
-+ screen,
-+ css_provider,
-+ Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
-+ }
-+
-+
- private void set_fixed_size() {
- resize(20, 1);
- }
-@@ -1038,7 +1049,8 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- m_lookup_table.append_candidate(text);
- }
- m_backward = block_name;
-- m_annotation = m_lookup_table.get_candidate(0).text;
-+ if (m_lookup_table.get_number_of_candidates() > 0)
-+ m_annotation = m_lookup_table.get_candidate(0).text;
- }
-
-
-@@ -1385,6 +1397,10 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- private void show_candidate_panel() {
- remove_all_children();
- set_fixed_size();
-+ if (m_emoji_font_changed) {
-+ set_css_data();
-+ m_emoji_font_changed = false;
-+ }
- uint page_size = m_lookup_table.get_page_size();
- uint ncandidates = m_lookup_table.get_number_of_candidates();
- uint cursor = m_lookup_table.get_cursor_pos();
-@@ -1488,32 +1504,33 @@ public class IBusEmojier : Gtk.ApplicationWindow {
-
- m_candidates += label;
- }
-- if (n > 0) {
-- m_candidate_panel_is_visible = true;
-- if (!m_is_up_side_down) {
-- show_arrow_buttons();
-- if (backward_button != null) {
-- m_vbox.add(backward_button);
-- backward_button.show_all();
-- }
-+ m_candidate_panel_is_visible = true;
-+ if (!m_is_up_side_down) {
-+ show_arrow_buttons();
-+ if (backward_button != null) {
-+ m_vbox.add(backward_button);
-+ backward_button.show_all();
-+ }
-+ if (n > 0) {
- m_vbox.add(grid);
- grid.show_all();
- show_description();
-- if (!m_loaded_unicode)
-- show_unicode_progress_bar();
- }
-- if (m_is_up_side_down) {
-- if (!m_loaded_unicode)
-- show_unicode_progress_bar();
-+ if (!m_loaded_unicode)
-+ show_unicode_progress_bar();
-+ } else {
-+ if (!m_loaded_unicode)
-+ show_unicode_progress_bar();
-+ if (n > 0) {
- show_description();
- m_vbox.add(grid);
- grid.show_all();
-- if (backward_button != null) {
-- m_vbox.add(backward_button);
-- backward_button.show_all();
-- }
-- show_arrow_buttons();
- }
-+ if (backward_button != null) {
-+ m_vbox.add(backward_button);
-+ backward_button.show_all();
-+ }
-+ show_arrow_buttons();
- }
- }
-
-@@ -2618,11 +2635,15 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- Pango.FontDescription font_desc =
- Pango.FontDescription.from_string(emoji_font);
- string font_family = font_desc.get_family();
-- if (font_family != null)
-+ if (font_family != null) {
- m_emoji_font_family = font_family;
-+ m_emoji_font_changed = true;
-+ }
- int font_size = font_desc.get_size() / Pango.SCALE;
-- if (font_size != 0)
-+ if (font_size != 0) {
- m_emoji_font_size = font_size;
-+ m_emoji_font_changed = true;
-+ }
- }
-
-
---
-2.14.3
-
-From f9e30359d328054793e1e225dcf2fe537e6c8c48 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Wed, 27 Jun 2018 12:11:41 +0900
-Subject: [PATCH] ibusenginesimple: Enable preedit for compose keys
-
-BUG=https://github.com/ibus/ibus/issues/1935
----
- src/ibusenginesimple.c | 166 ++++++++++++++++++++++++++++++++++---------------
- 1 file changed, 115 insertions(+), 51 deletions(-)
-
-diff --git a/src/ibusenginesimple.c b/src/ibusenginesimple.c
-index 94ce53b7..61dfb89f 100644
---- a/src/ibusenginesimple.c
-+++ b/src/ibusenginesimple.c
-@@ -189,11 +189,12 @@ ibus_engine_simple_reset (IBusEngine *engine)
- priv->tentative_match = 0;
- priv->tentative_match_len = 0;
- ibus_engine_hide_preedit_text ((IBusEngine *)simple);
-- }
-- if (priv->tentative_emoji || priv->in_emoji_sequence) {
-+ } else if (priv->tentative_emoji || priv->in_emoji_sequence) {
- priv->in_emoji_sequence = FALSE;
- g_clear_pointer (&priv->tentative_emoji, g_free);
- ibus_engine_hide_preedit_text ((IBusEngine *)simple);
-+ } else if (!priv->in_hex_sequence && !priv->in_emoji_sequence) {
-+ ibus_engine_hide_preedit_text ((IBusEngine *)simple);
- }
- }
-
-@@ -209,18 +210,78 @@ ibus_engine_simple_commit_char (IBusEngineSimple *simple,
- priv->in_hex_sequence = FALSE;
- priv->tentative_match = 0;
- priv->tentative_match_len = 0;
-- ibus_engine_simple_update_preedit_text (simple);
- }
- if (priv->tentative_emoji || priv->in_emoji_sequence) {
- priv->in_emoji_sequence = FALSE;
- g_clear_pointer (&priv->tentative_emoji, g_free);
-- ibus_engine_simple_update_preedit_text (simple);
- }
--
- ibus_engine_commit_text ((IBusEngine *)simple,
- ibus_text_new_from_unichar (ch));
- }
-
-+#define COMPOSE_KEYSYM_TO_UNICHAR(keysym, unichar) { \
-+
-+static gunichar
-+ibus_keysym_to_unicode (guint16 keysym) {
-+#define CASE(keysym_suffix, unicode) \
-+ case IBUS_KEY_dead_##keysym_suffix: return unicode
-+ switch (keysym) {
-+ CASE(a, 0x03041);
-+ CASE(A, 0x03042);
-+ CASE(i, 0x03043);
-+ CASE(I, 0x03044);
-+ CASE(u, 0x03045);
-+ CASE(U, 0x03046);
-+ CASE(e, 0x03047);
-+ CASE(E, 0x03048);
-+ CASE(o, 0x03049);
-+ CASE(O, 0x0304a);
-+ CASE(abovecomma, 0x0313);
-+ CASE(abovedot, 0x0307);
-+ CASE(abovereversedcomma, 0x0314);
-+ CASE(abovering, 0x030a);
-+ CASE(acute, 0x0301);
-+ CASE(belowbreve, 0x032e);
-+ CASE(belowcircumflex, 0x032d);
-+ CASE(belowcomma, 0x0326);
-+ CASE(belowdiaeresis, 0x0324);
-+ CASE(belowdot, 0x0323);
-+ CASE(belowmacron, 0x0331);
-+ CASE(belowring, 0x030a);
-+ CASE(belowtilde, 0x0330);
-+ CASE(breve, 0x0306);
-+ CASE(capital_schwa, 0x018f);
-+ CASE(caron, 0x030c);
-+ CASE(cedilla, 0x0327);
-+ CASE(circumflex, 0x0302);
-+ CASE(currency, 0x00a4);
-+ // IBUS_KEY_dead_dasia == IBUS_KEY_dead_abovereversedcomma
-+ CASE(diaeresis, 0x0308);
-+ CASE(doubleacute, 0x030b);
-+ CASE(doublegrave, 0x030f);
-+ CASE(grave, 0x0300);
-+ CASE(greek, 0x03b1);
-+ CASE(hook, 0x0309);
-+ CASE(horn, 0x031b);
-+ CASE(invertedbreve, 0x032f);
-+ CASE(iota, 0x0345);
-+ CASE(macron, 0x0304);
-+ CASE(ogonek, 0x0328);
-+ // IBUS_KEY_dead_perispomeni == IBUS_KEY_dead_tilde
-+ // IBUS_KEY_dead_psili == IBUS_KEY_dead_abovecomma
-+ CASE(semivoiced_sound, 0x309a);
-+ CASE(small_schwa, 0x1d4a);
-+ CASE(stroke, 0x29f8);
-+ CASE(tilde, 0x0303);
-+ CASE(voiced_sound, 0x3099);
-+ case IBUS_KEY_Multi_key:
-+ return 0x2384;
-+ default:;
-+ }
-+ return 0x0;
-+#undef CASE
-+}
-+
- static void
- ibus_engine_simple_commit_str (IBusEngineSimple *simple,
- const gchar *str)
-@@ -278,8 +339,7 @@ ibus_engine_simple_update_preedit_text (IBusEngineSimple *simple)
- g_assert (len <= IBUS_MAX_COMPOSE_LEN + 1);
- else
- g_assert (len <= EMOJI_SOURCE_LEN + 1);
-- }
-- else if (priv->tentative_match) {
-+ } else if (priv->tentative_match) {
- outbuf[len++] = priv->tentative_match;
- } else if (priv->tentative_emoji && *priv->tentative_emoji) {
- IBusText *text = ibus_text_new_from_string (priv->tentative_emoji);
-@@ -288,6 +348,24 @@ ibus_engine_simple_update_preedit_text (IBusEngineSimple *simple)
- IBUS_ATTR_TYPE_UNDERLINE, IBUS_ATTR_UNDERLINE_SINGLE, 0, len);
- ibus_engine_update_preedit_text ((IBusEngine *)simple, text, len, TRUE);
- return;
-+ } else {
-+ int hexchars = 0;
-+ while (priv->compose_buffer[hexchars] != 0) {
-+ guint16 keysym= priv->compose_buffer[hexchars];
-+ gunichar unichar = ibus_keysym_to_unicode (keysym);
-+ if (unichar > 0)
-+ outbuf[len] = unichar;
-+ else
-+ outbuf[len] = ibus_keyval_to_unicode (keysym);
-+ if (!outbuf[len]) {
-+ g_warning (
-+ "Not found alternative character of compose key 0x%X",
-+ priv->compose_buffer[hexchars]);
-+ }
-+ ++len;
-+ ++hexchars;
-+ }
-+ g_assert (len <= IBUS_MAX_COMPOSE_LEN + 1);
- }
-
- outbuf[len] = L'\0';
-@@ -569,8 +647,9 @@ check_table (IBusEngineSimple *simple,
- }
-
- ibus_engine_simple_commit_char (simple, value);
-- // g_debug ("U+%04X\n", value);
- priv->compose_buffer[0] = 0;
-+ ibus_engine_simple_update_preedit_text (simple);
-+ // g_debug ("U+%04X\n", value);
- }
- return TRUE;
- }
-@@ -768,44 +847,10 @@ ibus_check_algorithmically (const guint16 *compose_buffer,
- combination_buffer[n_compose] = 0;
- i--;
- while (i >= 0) {
-- switch (compose_buffer[i]) {
--#define CASE(keysym, unicode) \
-- case IBUS_KEY_dead_##keysym: \
-- combination_buffer[i+1] = unicode; \
-- break
-- CASE (grave, 0x0300);
-- CASE (acute, 0x0301);
-- CASE (circumflex, 0x0302);
-- CASE (tilde, 0x0303); /* Also used with perispomeni, 0x342. */
-- CASE (macron, 0x0304);
-- CASE (breve, 0x0306);
-- CASE (abovedot, 0x0307);
-- CASE (diaeresis, 0x0308);
-- CASE (hook, 0x0309);
-- CASE (abovering, 0x030A);
-- CASE (doubleacute, 0x030B);
-- CASE (caron, 0x030C);
-- CASE (abovecomma, 0x0313); /* Equivalent to psili */
-- CASE (abovereversedcomma, 0x0314); /* Equivalent to dasia */
-- CASE (horn, 0x031B); /* Legacy use for psili, 0x313 (or 0x343). */
-- CASE (belowdot, 0x0323);
-- CASE (cedilla, 0x0327);
-- CASE (ogonek, 0x0328); /* Legacy use for dasia, 0x314.*/
-- CASE (iota, 0x0345);
-- CASE (voiced_sound, 0x3099); /* Per Markus Kuhn keysyms.txt file. */
-- CASE (semivoiced_sound, 0x309A); /* Per Markus Kuhn keysyms.txt file. */
--
-- /* The following cases are to be removed once xkeyboard-config,
-- * xorg are fully updated.
-- */
-- /* Workaround for typo in 1.4.x xserver-xorg */
-- case 0xfe66: combination_buffer[i+1] = 0x314; break;
-- /* CASE (dasia, 0x314); */
-- /* CASE (perispomeni, 0x342); */
-- /* CASE (psili, 0x343); */
--#undef CASE
-- default:
-- combination_buffer[i+1] = ibus_keyval_to_unicode (compose_buffer[i]);
-+ combination_buffer[i+1] = ibus_keysym_to_unicode (compose_buffer[i]);
-+ if (!combination_buffer[i+1]) {
-+ combination_buffer[i+1] =
-+ ibus_keyval_to_unicode (compose_buffer[i]);
- }
- i--;
- }
-@@ -853,6 +898,7 @@ no_sequence_matches (IBusEngineSimple *simple,
-
- ibus_engine_simple_commit_char (simple, priv->tentative_match);
- priv->compose_buffer[0] = 0;
-+ ibus_engine_simple_update_preedit_text (simple);
-
- for (i=0; i < n_compose - len - 1; i++) {
- ibus_engine_simple_process_key_event (
-@@ -872,20 +918,21 @@ no_sequence_matches (IBusEngineSimple *simple,
- if (n_compose > 1) {
- /* Invalid sequence */
- // FIXME beep_window (event->window);
-+ ibus_engine_simple_update_preedit_text (simple);
- return TRUE;
- }
-
-+ ibus_engine_simple_update_preedit_text (simple);
- ch = ibus_keyval_to_unicode (keyval);
- /* IBUS_CHANGE: RH#769133
- * Since we use ibus xkb engines as the disable state,
- * do not commit the characters locally without in_hex_sequence. */
- if (ch != 0 && !g_unichar_iscntrl (ch) &&
- priv->in_hex_sequence) {
-- ibus_engine_simple_commit_char (simple, ch);
- return TRUE;
-- }
-- else
-+ } else {
- return FALSE;
-+ }
- }
- return FALSE;
- }
-@@ -1027,6 +1074,7 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
- if (priv->tentative_match &&
- g_unichar_validate (priv->tentative_match)) {
- ibus_engine_simple_commit_char (simple, priv->tentative_match);
-+ ibus_engine_simple_update_preedit_text (simple);
- } else if (n_compose == 0) {
- priv->modifiers_dropped = TRUE;
- } else {
-@@ -1176,12 +1224,21 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
-
- return TRUE;
- }
-+ if (!priv->in_hex_sequence && !priv->in_emoji_sequence && is_backspace) {
-+ if (n_compose > 0) {
-+ n_compose--;
-+ priv->compose_buffer[n_compose] = 0;
-+ ibus_engine_simple_update_preedit_text (simple);
-+ return TRUE;
-+ }
-+ }
-
- /* Check for hex sequence restart */
- if (priv->in_hex_sequence && have_hex_mods && is_hex_start) {
- if (priv->tentative_match &&
- g_unichar_validate (priv->tentative_match)) {
- ibus_engine_simple_commit_char (simple, priv->tentative_match);
-+ ibus_engine_simple_update_preedit_text (simple);
- }
- else {
- /* invalid hex sequence */
-@@ -1283,6 +1340,12 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
- return TRUE;
- }
- } else {
-+ if (is_escape) {
-+ if (n_compose > 0) {
-+ ibus_engine_simple_reset (engine);
-+ return TRUE;
-+ }
-+ }
- SET_COMPOSE_BUFFER_ELEMENT_NEXT (priv->compose_buffer,
- n_compose,
- keyval);
-@@ -1302,6 +1365,7 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
- ibus_engine_simple_commit_char (simple,
- priv->tentative_match);
- priv->compose_buffer[0] = 0;
-+ ibus_engine_simple_update_preedit_text (simple);
- } else {
- // FIXME
- /* invalid hex sequence */
-@@ -1417,9 +1481,8 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
- if (compose_finish) {
- ibus_engine_simple_commit_char (simple, output_char);
- priv->compose_buffer[0] = 0;
-- } else {
-- ibus_engine_simple_update_preedit_text (simple);
- }
-+ ibus_engine_simple_update_preedit_text (simple);
- return TRUE;
- }
-
-@@ -1430,6 +1493,7 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
- ibus_engine_simple_commit_char (simple, output_char);
- priv->compose_buffer[0] = 0;
- }
-+ ibus_engine_simple_update_preedit_text (simple);
- return TRUE;
- }
- }
---
-2.14.3
-
-From 3a68ded197b3ad2e45ac08fe52c0514aff987367 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Fri, 29 Jun 2018 16:02:32 +0900
-Subject: [PATCH] ibusenginesimple: Do not show combined character on
- compose preedit
-
-Some applications could combine their committed string with compose
-character on preedit. E.g. dead_grave after 'e' on firefox
-
-BUG=https://github.com/ibus/ibus/issues/1935
----
- src/ibusenginesimple.c | 119 ++++++++++++++++++++++++++-----------------------
- 1 file changed, 63 insertions(+), 56 deletions(-)
-
-diff --git a/src/ibusenginesimple.c b/src/ibusenginesimple.c
-index 61dfb89f..68d6fb1e 100644
---- a/src/ibusenginesimple.c
-+++ b/src/ibusenginesimple.c
-@@ -219,67 +219,73 @@ ibus_engine_simple_commit_char (IBusEngineSimple *simple,
- ibus_text_new_from_unichar (ch));
- }
-
--#define COMPOSE_KEYSYM_TO_UNICHAR(keysym, unichar) { \
--
- static gunichar
--ibus_keysym_to_unicode (guint16 keysym) {
--#define CASE(keysym_suffix, unicode) \
-+ibus_keysym_to_unicode (guint16 keysym,
-+ gboolean combining) {
-+#define CASE(keysym_suffix, unicode) \
- case IBUS_KEY_dead_##keysym_suffix: return unicode
-+#define CASE_COMBINE(keysym_suffix, combined_unicode, isolated_unicode) \
-+ case IBUS_KEY_dead_##keysym_suffix: \
-+ if (combining) \
-+ return combined_unicode; \
-+ else \
-+ return isolated_unicode
- switch (keysym) {
-- CASE(a, 0x03041);
-- CASE(A, 0x03042);
-- CASE(i, 0x03043);
-- CASE(I, 0x03044);
-- CASE(u, 0x03045);
-- CASE(U, 0x03046);
-- CASE(e, 0x03047);
-- CASE(E, 0x03048);
-- CASE(o, 0x03049);
-- CASE(O, 0x0304a);
-- CASE(abovecomma, 0x0313);
-- CASE(abovedot, 0x0307);
-- CASE(abovereversedcomma, 0x0314);
-- CASE(abovering, 0x030a);
-- CASE(acute, 0x0301);
-- CASE(belowbreve, 0x032e);
-- CASE(belowcircumflex, 0x032d);
-- CASE(belowcomma, 0x0326);
-- CASE(belowdiaeresis, 0x0324);
-- CASE(belowdot, 0x0323);
-- CASE(belowmacron, 0x0331);
-- CASE(belowring, 0x030a);
-- CASE(belowtilde, 0x0330);
-- CASE(breve, 0x0306);
-- CASE(capital_schwa, 0x018f);
-- CASE(caron, 0x030c);
-- CASE(cedilla, 0x0327);
-- CASE(circumflex, 0x0302);
-- CASE(currency, 0x00a4);
-+ CASE (a, 0x03041);
-+ CASE (A, 0x03042);
-+ CASE (i, 0x03043);
-+ CASE (I, 0x03044);
-+ CASE (u, 0x03045);
-+ CASE (U, 0x03046);
-+ CASE (e, 0x03047);
-+ CASE (E, 0x03048);
-+ CASE (o, 0x03049);
-+ CASE (O, 0x0304A);
-+ CASE (abovecomma, 0x0313);
-+ CASE_COMBINE (abovedot, 0x0307, 0x02D9);
-+ CASE (abovereversedcomma, 0x0314);
-+ CASE_COMBINE (abovering, 0x030A, 0x02DA);
-+ CASE_COMBINE (acute, 0x0301, 0x00B4);
-+ CASE (belowbreve, 0x032E);
-+ CASE_COMBINE (belowcircumflex, 0x032D, 0xA788);
-+ CASE_COMBINE (belowcomma, 0x0326, 0x002C);
-+ CASE (belowdiaeresis, 0x0324);
-+ CASE_COMBINE (belowdot, 0x0323, 0x002E);
-+ CASE_COMBINE (belowmacron, 0x0331, 0x02CD);
-+ CASE_COMBINE (belowring, 0x030A, 0x02F3);
-+ CASE_COMBINE (belowtilde, 0x0330, 0x02F7);
-+ CASE_COMBINE (breve, 0x0306, 0x02D8);
-+ CASE_COMBINE (capital_schwa, 0x018F, 0x04D8);
-+ CASE_COMBINE (caron, 0x030C, 0x02C7);
-+ CASE_COMBINE (cedilla, 0x0327, 0x00B8);
-+ CASE_COMBINE (circumflex, 0x0302, 0x005E);
-+ CASE (currency, 0x00A4);
- // IBUS_KEY_dead_dasia == IBUS_KEY_dead_abovereversedcomma
-- CASE(diaeresis, 0x0308);
-- CASE(doubleacute, 0x030b);
-- CASE(doublegrave, 0x030f);
-- CASE(grave, 0x0300);
-- CASE(greek, 0x03b1);
-- CASE(hook, 0x0309);
-- CASE(horn, 0x031b);
-- CASE(invertedbreve, 0x032f);
-- CASE(iota, 0x0345);
-- CASE(macron, 0x0304);
-- CASE(ogonek, 0x0328);
-+ CASE_COMBINE (diaeresis, 0x0308, 0x00A8);
-+ CASE_COMBINE (doubleacute, 0x030B, 0x02DD);
-+ CASE_COMBINE (doublegrave, 0x030F, 0x02F5);
-+ CASE_COMBINE (grave, 0x0300, 0x0060);
-+ CASE (greek, 0x03BC);
-+ CASE (hook, 0x0309);
-+ CASE (horn, 0x031B);
-+ CASE (invertedbreve, 0x032F);
-+ CASE_COMBINE (iota, 0x0345, 0x037A);
-+ CASE_COMBINE (macron, 0x0304, 0x00AF);
-+ CASE_COMBINE (ogonek, 0x0328, 0x02DB);
- // IBUS_KEY_dead_perispomeni == IBUS_KEY_dead_tilde
- // IBUS_KEY_dead_psili == IBUS_KEY_dead_abovecomma
-- CASE(semivoiced_sound, 0x309a);
-- CASE(small_schwa, 0x1d4a);
-- CASE(stroke, 0x29f8);
-- CASE(tilde, 0x0303);
-- CASE(voiced_sound, 0x3099);
-+ CASE_COMBINE (semivoiced_sound, 0x309A, 0x309C);
-+ CASE_COMBINE (small_schwa, 0x1D4A, 0x04D9);
-+ CASE (stroke, 0x002F);
-+ CASE_COMBINE (tilde, 0x0303, 0x007E);
-+ CASE_COMBINE (voiced_sound, 0x3099, 0x309B);
- case IBUS_KEY_Multi_key:
- return 0x2384;
- default:;
- }
- return 0x0;
- #undef CASE
-+#undef CASE_COMBINE
- }
-
- static void
-@@ -352,7 +358,7 @@ ibus_engine_simple_update_preedit_text (IBusEngineSimple *simple)
- int hexchars = 0;
- while (priv->compose_buffer[hexchars] != 0) {
- guint16 keysym= priv->compose_buffer[hexchars];
-- gunichar unichar = ibus_keysym_to_unicode (keysym);
-+ gunichar unichar = ibus_keysym_to_unicode (keysym, FALSE);
- if (unichar > 0)
- outbuf[len] = unichar;
- else
-@@ -847,13 +853,14 @@ ibus_check_algorithmically (const guint16 *compose_buffer,
- combination_buffer[n_compose] = 0;
- i--;
- while (i >= 0) {
-- combination_buffer[i+1] = ibus_keysym_to_unicode (compose_buffer[i]);
-- if (!combination_buffer[i+1]) {
-- combination_buffer[i+1] =
-- ibus_keyval_to_unicode (compose_buffer[i]);
-+ combination_buffer[i+1] = ibus_keysym_to_unicode (compose_buffer[i],
-+ TRUE);
-+ if (!combination_buffer[i+1]) {
-+ combination_buffer[i+1] =
-+ ibus_keyval_to_unicode (compose_buffer[i]);
-+ }
-+ i--;
- }
-- i--;
-- }
-
- /* If the buffer normalizes to a single character,
- * then modify the order of combination_buffer accordingly, if necessary,
---
-2.14.3
-
-From caffeaeee5be121713104fba331b9cf30726aa91 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Fri, 29 Jun 2018 16:06:52 +0900
-Subject: [PATCH] panelbinding: Fix SEGV in panel_binding_parse_accelerator
-
-panel_binding_parse_accelerator() could return NULL of the unowned
-IBus.ProcessKeyEventData with gcc optimization.
-Since Vala does not provice a static local variable, the variable is
-moved to the class member to fix this SEGV.
-Also fixed an infinite loop to show a compose preedit in xterm.
-Also a NULL preedit is fixed in the first emoji candidate from the
-emoji category window.
----
- bus/inputcontext.c | 9 +++++++++
- bus/panelproxy.c | 38 ++++++++++++++++++++++++++++++++++++--
- ui/gtk3/panelbinding.vala | 28 ++++++++++++++++------------
- 3 files changed, 61 insertions(+), 14 deletions(-)
-
-diff --git a/bus/inputcontext.c b/bus/inputcontext.c
-index bf9eafcf..98639a24 100644
---- a/bus/inputcontext.c
-+++ b/bus/inputcontext.c
-@@ -1730,6 +1730,15 @@ bus_input_context_hide_auxiliary_text (BusInputContext *context)
- }
- }
-
-+/**
-+ * bus_input_context_update_lookup_table:
-+ * @context: #BusInputContext
-+ * @table: #IBusLookupTable
-+ * @visible: %TRUE if the lookup table is visible, otherwise %FALSE.
-+ * @is_extension: %TRUE if the lookup table is called by a panel extension.
-+ * %FALSE if it's called by an engine.
-+ * I.e. is_extension_lookup_table means the owner of the lookup table.
-+ */
- void
- bus_input_context_update_lookup_table (BusInputContext *context,
- IBusLookupTable *table,
-diff --git a/bus/panelproxy.c b/bus/panelproxy.c
-index 1c0fcca2..3e6d5be2 100644
---- a/bus/panelproxy.c
-+++ b/bus/panelproxy.c
-@@ -743,6 +743,16 @@ _context_update_preedit_text_cb (BusInputContext *context,
-
- g_return_if_fail (panel->focused_context == context);
-
-+ /* The callback is called with X11 applications but
-+ * the callback is not called for extensions and panel
-+ * extensions are always calls by
-+ * bus_panel_proxy_update_preedit_text() directly
-+ * because panel extensions foward UpdatePreeditText to
-+ * UpdatePreeditTextReceived and it can be an infinite
-+ * loop.
-+ */
-+ if (panel->panel_type != PANEL_TYPE_PANEL)
-+ return;
- bus_panel_proxy_update_preedit_text (panel,
- text,
- cursor_pos,
-@@ -847,8 +857,31 @@ _context_set_content_type_cb (BusInputContext *context,
- bus_panel_proxy_##name (panel); \
- }
-
--DEFINE_FUNCTION (show_preedit_text)
--DEFINE_FUNCTION (hide_preedit_text)
-+#define DEFINE_FUNCTION_NO_EXTENSION(name) \
-+ static void _context_##name##_cb (BusInputContext *context, \
-+ BusPanelProxy *panel) \
-+ { \
-+ g_assert (BUS_IS_INPUT_CONTEXT (context)); \
-+ g_assert (BUS_IS_PANEL_PROXY (panel)); \
-+ \
-+ g_return_if_fail (panel->focused_context == context); \
-+ \
-+ /* The callback is called with X11 applications but \
-+ * the callback is not called for extensions and panel \
-+ * extensions are always calls by \
-+ * bus_panel_proxy_update_preedit_text() directly \
-+ * because panel extensions foward UpdatePreeditText to \
-+ * UpdatePreeditTextReceived and it can be an infinite \
-+ * loop. \
-+ */ \
-+ if (panel->panel_type != PANEL_TYPE_PANEL) \
-+ return; \
-+ bus_panel_proxy_##name (panel); \
-+ }
-+
-+
-+DEFINE_FUNCTION_NO_EXTENSION (show_preedit_text)
-+DEFINE_FUNCTION_NO_EXTENSION (hide_preedit_text)
- DEFINE_FUNCTION (show_auxiliary_text)
- DEFINE_FUNCTION (hide_auxiliary_text)
- DEFINE_FUNCTION (show_lookup_table)
-@@ -860,6 +893,7 @@ DEFINE_FUNCTION (cursor_down_lookup_table)
- DEFINE_FUNCTION (state_changed)
-
- #undef DEFINE_FUNCTION
-+#undef DEFINE_FUNCTION_NO_EXTENSION
-
- static const struct {
- gchar *name;
-diff --git a/ui/gtk3/panelbinding.vala b/ui/gtk3/panelbinding.vala
-index 52b78c17..95115b13 100644
---- a/ui/gtk3/panelbinding.vala
-+++ b/ui/gtk3/panelbinding.vala
-@@ -227,6 +227,8 @@ class PanelBinding : IBus.PanelService {
- private bool m_enable_extension;
- private string m_extension_name = "";
- private Preedit m_preedit;
-+ private IBus.ProcessKeyEventData m_key_event_data =
-+ IBus.ProcessKeyEventData();
-
- public PanelBinding(IBus.Bus bus,
- Gtk.Application application) {
-@@ -311,24 +313,24 @@ class PanelBinding : IBus.PanelService {
- }
-
-
-- private unowned
-- IBus.ProcessKeyEventData? parse_accelerator(string accelerator) {
-- IBus.ProcessKeyEventData key = {};
-+ // Returning unowned IBus.KeyEventData causes NULL with gcc optimization
-+ // and use m_key_event_data.
-+ private void parse_accelerator(string accelerator) {
-+ m_key_event_data = {};
- uint keysym = 0;
- IBus.ModifierType modifiers = 0;
- IBus.accelerator_parse(accelerator,
- out keysym, out modifiers);
- if (keysym == 0U && modifiers == 0) {
- warning("Failed to parse shortcut key '%s'".printf(accelerator));
-- return null;
-+ return;
- }
- if ((modifiers & IBus.ModifierType.SUPER_MASK) != 0) {
- modifiers ^= IBus.ModifierType.SUPER_MASK;
- modifiers |= IBus.ModifierType.MOD4_MASK;
- }
-- key.keyval = keysym;
-- key.state = modifiers;
-- return key;
-+ m_key_event_data.keyval = keysym;
-+ m_key_event_data.state = modifiers;
- }
-
-
-@@ -337,8 +339,8 @@ class PanelBinding : IBus.PanelService {
- IBus.ProcessKeyEventData key;
- string[] accelerators = m_settings_emoji.get_strv("hotkey");
- foreach (var accelerator in accelerators) {
-- key = parse_accelerator(accelerator);
-- emoji_keys += key;
-+ parse_accelerator(accelerator);
-+ emoji_keys += m_key_event_data;
- }
-
- /* Since {} is not allocated, parse_accelerator() should be unowned. */
-@@ -348,8 +350,8 @@ class PanelBinding : IBus.PanelService {
- IBus.ProcessKeyEventData[] unicode_keys = {};
- accelerators = m_settings_emoji.get_strv("unicode-hotkey");
- foreach (var accelerator in accelerators) {
-- key = parse_accelerator(accelerator);
-- unicode_keys += key;
-+ parse_accelerator(accelerator);
-+ unicode_keys += m_key_event_data;
- }
- key = {};
- unicode_keys += key;
-@@ -544,8 +546,10 @@ class PanelBinding : IBus.PanelService {
- private bool key_press_enter() {
- if (m_extension_name != "unicode" && is_emoji_lookup_table()) {
- // Check if variats exist
-- if (m_emojier.key_press_enter())
-+ if (m_emojier.key_press_enter()) {
-+ convert_preedit_text();
- return true;
-+ }
- }
- IBus.Text text = m_preedit.get_commit_text();
- commit_text_update_favorites(text);
---
-2.14.3
-
-From 6b47e41d66497dd35752a89ea80e4bac55b64e45 Mon Sep 17 00:00:00 2001
-From: Takuro Ashie <ashie@clear-code.com>
-Date: Fri, 20 Jul 2018 12:30:09 +0900
-Subject: [PATCH] Remove a misleading "const" modifier of a return value
-
-ibus_key_event_to_string() uses g_string_free(str, FALSE) to return
-a string so that users must free it. To clarify it, the const
-modifier should be removed.
----
- src/ibuskeynames.c | 2 +-
- src/ibusshare.h | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/ibuskeynames.c b/src/ibuskeynames.c
-index fe7836ee..c3665127 100644
---- a/src/ibuskeynames.c
-+++ b/src/ibuskeynames.c
-@@ -124,7 +124,7 @@ modifier_name[] = {
- NULL, // 31
- };
-
--const gchar *
-+gchar *
- ibus_key_event_to_string (guint keyval,
- guint modifiers)
- {
-diff --git a/src/ibusshare.h b/src/ibusshare.h
-index 4f5a306b..d70af29f 100644
---- a/src/ibusshare.h
-+++ b/src/ibusshare.h
-@@ -326,7 +326,7 @@ void ibus_free_strv (gchar **strv)
- *
- * Returns: The name of a key symbol and modifier.
- */
--const gchar *ibus_key_event_to_string
-+gchar *ibus_key_event_to_string
- (guint keyval,
- guint modifiers);
-
---
-2.17.1
-
-From 0dde239a3c786dcc479e3103ccd49938fcb47191 Mon Sep 17 00:00:00 2001
-From: Kentaro Hayashi <hayashi@clear-code.com>
-Date: Tue, 24 Jul 2018 15:20:51 +0900
-Subject: [PATCH] bus: warn deprecated --mem-profile option
-
-Since GLib 2.46, memory profiling feature does not work anymore.
-
-GLib 2.46 or later means that Ubuntu 16.04 or later. Ubuntu
-14.04 (trusty) are still supported as LTS phase, but it seems that
-GLib is old enough (2.40) to drop support.
-
-As a result:
-
- * older than GLib 2.46: Just drop support
- * GLib 2.46 or later: Show a warning message if --mem-profile is
- used.
----
- bus/main.c | 15 +--------------
- configure.ac | 4 ++--
- 2 files changed, 3 insertions(+), 16 deletions(-)
-
-diff --git a/bus/main.c b/bus/main.c
-index 2fb37b69..6f1f39ca 100644
---- a/bus/main.c
-+++ b/bus/main.c
-@@ -160,18 +160,6 @@ daemon (gint nochdir, gint noclose)
- }
- #endif
-
--/*
-- * _sig_usr2_handler:
-- * @sig: the signal number, which is usually SIGUSR2.
-- *
-- * A signal handler for SIGUSR2 signal. Dump a summary of memory usage to stderr.
-- */
--static void
--_sig_usr2_handler (int sig)
--{
-- g_mem_profile ();
--}
--
- gint
- main (gint argc, gchar **argv)
- {
-@@ -196,8 +184,7 @@ main (gint argc, gchar **argv)
- }
-
- if (g_mempro) {
-- g_mem_set_vtable (glib_mem_profiler_table);
-- signal (SIGUSR2, _sig_usr2_handler);
-+ g_warning ("--mem-profile no longer works with the GLib 2.46 or later");
- }
-
- /* check uid */
-diff --git a/configure.ac b/configure.ac
-index f332a775..8e01c266 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -52,12 +52,12 @@ m4_define([ibus_binary_version],
- [ibus_major_version.ibus_abi_current_minus_age.ibus_abi_age.ibus_abi_revision])
-
- # Required versions of other packages.
--m4_define([glib_required_version], [2.36.0])
-+m4_define([glib_required_version], [2.46.0])
-
- # VALA_TARGET_GLIB_VERSION is used by valac --ccode --target-glib .
- # VALA_TARGET_GLIB_VERSION and glib_required_version will be different
- # in the future.
--VALA_TARGET_GLIB_VERSION=2.36
-+VALA_TARGET_GLIB_VERSION=2.46
- AC_SUBST(VALA_TARGET_GLIB_VERSION)
-
- # Init automake.
---
-2.17.1
-
-From 8d302c853f4e88f81652e0aeeca86ff1b5779ecb Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Tue, 24 Jul 2018 16:04:31 +0900
-Subject: [PATCH] RHEL code reviews
-
----
- client/x11/main.c | 4 ++--
- setup/enginetreeview.py | 10 ++--------
- setup/ibus-setup.in | 5 ++---
- src/emoji-parser.c | 8 +++++---
- src/ibusbus.c | 9 ++++++---
- src/ibuscomposetable.c | 4 ++--
- src/ibusenginesimple.c | 22 +++++++++++++++++-----
- src/ibushotkey.c | 5 +++--
- src/ibuskeymap.c | 10 ++++++----
- src/ibuskeynames.c | 3 +--
- src/ibusregistry.c | 4 ++--
- src/ibusservice.c | 13 +++++++++----
- src/ibusxml.c | 9 ++++++---
- src/unicode-parser.c | 3 ++-
- util/IMdkit/FrameMgr.c | 7 +++++++
- util/IMdkit/IMConn.c | 6 ++++--
- util/IMdkit/i18nClbk.c | 10 ++++++++++
- util/IMdkit/i18nIc.c | 11 +++++++++--
- util/IMdkit/i18nMethod.c | 4 ++++
- util/IMdkit/i18nOffsetCache.c | 21 +++++++++++++++++----
- util/IMdkit/i18nPtHdr.c | 28 +++++++++++++++++++++++-----
- util/IMdkit/i18nUtil.c | 12 +++++++++---
- util/IMdkit/i18nX.c | 10 ++++++++--
- 23 files changed, 156 insertions(+), 62 deletions(-)
-
-diff --git a/client/x11/main.c b/client/x11/main.c
-index 159f4303..3bea94b7 100644
---- a/client/x11/main.c
-+++ b/client/x11/main.c
-@@ -2,7 +2,7 @@
- /* vim:set et sts=4: */
- /* ibus
- * Copyright (C) 2007-2015 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2015-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2015-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
- * Copyright (C) 2007-2015 Red Hat, Inc.
- *
- * main.c:
-@@ -196,7 +196,7 @@ _xim_preedit_callback_draw (XIMS xims, X11IC *x11ic, const gchar *preedit_string
- }
- }
-
-- for (i = 0; i < len; i++) {
-+ for (i = 0; feedback && i < len; i++) {
- feedback[i] = 0;
- }
-
-diff --git a/setup/enginetreeview.py b/setup/enginetreeview.py
-index 4de4a516..aea84593 100644
---- a/setup/enginetreeview.py
-+++ b/setup/enginetreeview.py
-@@ -3,7 +3,8 @@
- # ibus - The Input Bus
- #
- # Copyright (c) 2007-2015 Peng Huang <shawn.p.huang@gmail.com>
--# Copyright (c) 2007-2015 Red Hat, Inc.
-+# Copyright (c) 2014-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+# Copyright (c) 2007-2018 Red Hat, Inc.
- #
- # This library is free software; you can redistribute it and/or
- # modify it under the terms of the GNU Lesser General Public
-@@ -91,7 +92,6 @@ class EngineTreeView(Gtk.TreeView):
- renderer.set_property("text-column", 0)
- renderer.set_property("has-entry", False)
- renderer.set_property("editable", True)
-- renderer.connect("changed", self.__engine_layout_changed_cb)
-
- column = Gtk.TreeViewColumn(_("Kbd"))
- column.set_expand(False)
-@@ -167,12 +167,6 @@ class EngineTreeView(Gtk.TreeView):
- renderer.set_property("text", layout)
- renderer.set_property("weight", Pango.Weight.NORMAL)
-
-- def __engine_layout_changed_cb(self, combo, path, it):
-- return
-- i = self.__model.get_iter(path)
-- layout = combo.get_property("model").get_value(it, 0)
-- self.__model.set_value(i, 1, layout)
--
- def do_get_property(self, prop):
- if prop.name == "active-engine":
- it = self.get_selected_iter()
-diff --git a/setup/ibus-setup.in b/setup/ibus-setup.in
-index e0ed9ff5..bb5c85cf 100644
---- a/setup/ibus-setup.in
-+++ b/setup/ibus-setup.in
-@@ -3,7 +3,8 @@
- # ibus - The Input Bus
- #
- # Copyright (c) 2007-2010 Peng Huang <shawn.p.huang@gmail.com>
--# Copyright (c) 2007-2010 Red Hat, Inc.
-+# Copyright (c) 2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+# Copyright (c) 2007-2018 Red Hat, Inc.
- #
- # This library is free software; you can redistribute it and/or
- # modify it under the terms of the GNU Lesser General Public
-@@ -21,8 +22,6 @@
- # USA
-
- prefix=@prefix@
--exec_prefix=@exec_prefix@
--datarootdir=@datarootdir@
- libexecdir=@libexecdir@
- export IBUS_PREFIX=@prefix@
- export IBUS_DATAROOTDIR=@datarootdir@
-diff --git a/src/emoji-parser.c b/src/emoji-parser.c
-index 0f7c8cfb..b8f4dcf1 100644
---- a/src/emoji-parser.c
-+++ b/src/emoji-parser.c
-@@ -466,7 +466,8 @@ unicode_annotations_parse_xml_file (const gchar *filename,
- g_return_val_if_fail (list != NULL, FALSE);
-
- if (!g_file_get_contents (filename, &content, &length, &error)) {
-- g_warning ("Failed to load %s: %s", filename, error->message);
-+ g_warning ("Failed to load %s: %s", filename,
-+ error ? error->message : "");
- goto failed_to_parse_unicode_annotations;
- }
-
-@@ -611,7 +612,7 @@ unicode_emoji_test_parse_line (const gchar *line,
- int i;
- gchar *amp;
- segments = g_strsplit(data->subcategory, "-", -1);
-- for (i = 0; segments[i]; i++) {
-+ for (i = 0; segments && segments[i]; i++) {
- if ((amp = strchr (segments[i], '&')) != NULL) {
- if (amp - segments[i] <= 1) {
- g_warning ("Wrong ampersand");
-@@ -665,7 +666,8 @@ unicode_emoji_test_parse_file (const gchar *filename,
- g_return_val_if_fail (list != NULL, FALSE);
-
- if (!g_file_get_contents (filename, &content, &length, &error)) {
-- g_warning ("Failed to load %s: %s", filename, error->message);
-+ g_warning ("Failed to load %s: %s",
-+ filename, error ? error->message : "");
- goto failed_to_parse_unicode_emoji_test;
- }
- head = end = content;
-diff --git a/src/ibusbus.c b/src/ibusbus.c
-index 98820e8a..30c2e321 100644
---- a/src/ibusbus.c
-+++ b/src/ibusbus.c
-@@ -2,7 +2,7 @@
- /* vim:set et sts=4: */
- /* ibus - The Input Bus
- * Copyright (C) 2008-2015 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2015-2016 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2015-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
- * Copyright (C) 2008-2016 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
-@@ -22,6 +22,7 @@
- */
-
- #include "ibusbus.h"
-+#include <errno.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
-@@ -565,7 +566,9 @@ ibus_bus_init (IBusBus *bus)
- return;
- }
- if (buf.st_mode != (S_IFDIR | S_IRWXU)) {
-- g_chmod (path, 0700);
-+ errno = 0;
-+ if (g_chmod (path, 0700))
-+ g_warning ("chmod failed: %s", errno ? g_strerror (errno) : "");
- }
- }
-
-@@ -673,7 +676,7 @@ ibus_bus_constructor (GType type,
- ibus_bus_connect (_bus);
- }
- else {
-- object = g_object_ref (_bus);
-+ object = g_object_ref (G_OBJECT (_bus));
- }
-
- return object;
-diff --git a/src/ibuscomposetable.c b/src/ibuscomposetable.c
-index d473f581..b843e7e1 100644
---- a/src/ibuscomposetable.c
-+++ b/src/ibuscomposetable.c
-@@ -1,7 +1,7 @@
- /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
- /* ibus - The Input Bus
- * Copyright (C) 2013-2014 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2013-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2013-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
-@@ -532,7 +532,7 @@ ibus_compose_table_serialize (IBusComposeTable *compose_table)
-
- variant_data = g_variant_new_fixed_array (G_VARIANT_TYPE_UINT16,
- compose_table->data,
-- index_stride * n_seqs,
-+ (gsize)index_stride * n_seqs,
- sizeof (guint16));
- if (variant_data == NULL) {
- g_warning ("Could not change compose data to GVariant.");
-diff --git a/src/ibusenginesimple.c b/src/ibusenginesimple.c
-index 68d6fb1e..aae6b8df 100644
---- a/src/ibusenginesimple.c
-+++ b/src/ibusenginesimple.c
-@@ -2,7 +2,7 @@
- /* vim:set et sts=4: */
- /* ibus - The Input Bus
- * Copyright (C) 2014 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2015-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2015-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
- * Copyright (C) 2014-2017 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
-@@ -814,9 +814,21 @@ check_normalize_nfc (gunichar* combination_buffer, gint n_compose)
- g_free (nfc_temp);
-
- if (n_compose > 2) {
-- temp_swap = combination_buffer_temp[i % (n_compose - 1) + 1];
-- combination_buffer_temp[i % (n_compose - 1) + 1] = combination_buffer_temp[(i+1) % (n_compose - 1) + 1];
-- combination_buffer_temp[(i+1) % (n_compose - 1) + 1] = temp_swap;
-+ gint j = i % (n_compose - 1) + 1;
-+ gint k = (i+1) % (n_compose - 1) + 1;
-+ if (j >= IBUS_MAX_COMPOSE_LEN) {
-+ g_warning ("j >= IBUS_MAX_COMPOSE_LEN for " \
-+ "combination_buffer_temp");
-+ break;
-+ }
-+ if (k >= IBUS_MAX_COMPOSE_LEN) {
-+ g_warning ("k >= IBUS_MAX_COMPOSE_LEN for " \
-+ "combination_buffer_temp");
-+ break;
-+ }
-+ temp_swap = combination_buffer_temp[j];
-+ combination_buffer_temp[j] = combination_buffer_temp[k];
-+ combination_buffer_temp[k] = temp_swap;
- }
- else
- break;
-@@ -1067,7 +1079,7 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
- gboolean compose_finish;
- gunichar output_char;
-
-- while (priv->compose_buffer[n_compose] != 0 && n_compose < EMOJI_SOURCE_LEN)
-+ while (n_compose < EMOJI_SOURCE_LEN && priv->compose_buffer[n_compose] != 0)
- n_compose++;
- if (n_compose >= EMOJI_SOURCE_LEN) {
- g_warning ("copmose table buffer is full.");
-diff --git a/src/ibushotkey.c b/src/ibushotkey.c
-index 0cdfa78b..00d502fc 100644
---- a/src/ibushotkey.c
-+++ b/src/ibushotkey.c
-@@ -2,7 +2,8 @@
- /* vim:set et sts=4: */
- /* IBus - The Input Bus
- * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2008-2010 Red Hat, Inc.
-+ * Copyright (C) 2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2008-2018 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
-@@ -453,7 +454,7 @@ ibus_hotkey_profile_remove_hotkey (IBusHotkeyProfile *profile,
- break;
- }
-
-- g_assert (p2->event == event);
-+ g_assert (p2 && p2->event == event);
-
- p2->hotkeys = g_list_remove (p2->hotkeys, p1);
- if (p2->hotkeys == NULL) {
-diff --git a/src/ibuskeymap.c b/src/ibuskeymap.c
-index d7428c5d..27a56754 100644
---- a/src/ibuskeymap.c
-+++ b/src/ibuskeymap.c
-@@ -2,7 +2,8 @@
- /* vim:set et sts=4: */
- /* IBus - The Input Bus
- * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2008-2010 Red Hat, Inc.
-+ * Copyright (C) 2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2008-2018 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
-@@ -72,7 +73,7 @@ static gboolean
- ibus_keymap_parse_line (gchar *str,
- KEYMAP keymap)
- {
-- gchar *p1, *p2;
-+ gchar *p1, *p2, ch;
- gint i;
- guint keycode;
- guint keysym;
-@@ -139,11 +140,12 @@ ibus_keymap_parse_line (gchar *str,
- if (keysym == IBUS_KEY_VoidSymbol)
- return FALSE;
-
-+ /* Do not assign *p1 to g_ascii_isalpha() directly for the syntax check */
- if (i == 0 &&
- strncmp (p2, "addupper", sizeof ("addupper") - 1) == 0 &&
-- g_ascii_isalpha (*p1)) {
-+ (ch = *p1) && g_ascii_isalpha (ch)) {
- gchar buf[] = "a";
-- buf[0] = g_ascii_toupper(*p1);
-+ buf[0] = g_ascii_toupper(ch);
- keymap[keycode][0] = keymap[keycode][3] = keysym;
- keymap[keycode][1] = keymap[keycode][2] = ibus_keyval_from_name (buf);
-
-diff --git a/src/ibuskeynames.c b/src/ibuskeynames.c
-index c3665127..08505598 100644
---- a/src/ibuskeynames.c
-+++ b/src/ibuskeynames.c
-@@ -192,8 +192,7 @@ ibus_key_event_from_string (const gchar *string,
- if (*keyval != IBUS_KEY_VoidSymbol)
- retval = TRUE;
- _out:
-- if (tokens)
-- g_strfreev (tokens);
-+ g_strfreev (tokens);
- return retval;
- }
-
-diff --git a/src/ibusregistry.c b/src/ibusregistry.c
-index dfda2af3..b0483998 100644
---- a/src/ibusregistry.c
-+++ b/src/ibusregistry.c
-@@ -2,7 +2,7 @@
- /* vim:set et sts=4: */
- /* bus - The Input Bus
- * Copyright (C) 2015 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2015 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2015-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
- * Copyright (C) 2015 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
-@@ -472,7 +472,7 @@ ibus_registry_save_cache_file (IBusRegistry *registry,
- }
-
- if (g_str_has_prefix (filename, g_get_user_cache_dir ())) {
-- g_chmod (filename, 0644);
-+ g_warn_if_fail (!g_chmod (filename, 0644));
- }
-
- return TRUE;
-diff --git a/src/ibusservice.c b/src/ibusservice.c
-index 2199d61d..8023527b 100644
---- a/src/ibusservice.c
-+++ b/src/ibusservice.c
-@@ -2,7 +2,8 @@
- /* vim:set et sts=4: */
- /* ibus - The Input Bus
- * Copyright (C) 2008-2015 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2008-2015 Red Hat, Inc.
-+ * Copyright (C) 2015-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2008-2018 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
-@@ -500,12 +501,14 @@ ibus_service_register (IBusService *service,
- GDBusConnection *connection,
- GError **error)
- {
-+ GArray *array = NULL;
-+ GArray *interfaces;
-+ GDBusInterfaceInfo **p;
-+
- g_return_val_if_fail (IBUS_IS_SERVICE (service), FALSE);
- g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-- GArray *array = NULL;
--
- if (g_hash_table_lookup (service->priv->table, connection)) {
- if (error) {
- *error = g_error_new (G_DBUS_ERROR, G_DBUS_ERROR_OBJECT_PATH_IN_USE,
-@@ -515,7 +518,9 @@ ibus_service_register (IBusService *service,
- goto error_out;
- }
-
-- GDBusInterfaceInfo **p = (GDBusInterfaceInfo **)IBUS_SERVICE_GET_CLASS (service)->interfaces->data;
-+ interfaces = IBUS_SERVICE_GET_CLASS (service)->interfaces;
-+ g_assert (interfaces);
-+ p = (GDBusInterfaceInfo **)interfaces->data;
- if (*p == NULL) {
- if (error) {
- *error = g_error_new (G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
-diff --git a/src/ibusxml.c b/src/ibusxml.c
-index 5cacc5af..266a8207 100644
---- a/src/ibusxml.c
-+++ b/src/ibusxml.c
-@@ -2,7 +2,8 @@
- /* vim:set et sts=4: */
- /* bus - The Input Bus
- * Copyright (C) 2008-2015 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2008-2015 Red Hat, Inc.
-+ * Copyright (C) 2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2008-2018 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
-@@ -240,8 +241,10 @@ ibus_xml_parse_file (const gchar *filename)
- return node;
- } while (0);
-
-- g_warning ("Parse %s failed: %s", filename, error->message);
-- g_error_free (error);
-+ if (error) {
-+ g_warning ("Parse %s failed: %s", filename, error->message);
-+ g_error_free (error);
-+ }
- g_markup_parse_context_free (context);
- return NULL;
- }
-diff --git a/src/unicode-parser.c b/src/unicode-parser.c
-index e98c6d5f..0e4fe8b7 100644
---- a/src/unicode-parser.c
-+++ b/src/unicode-parser.c
-@@ -281,7 +281,8 @@ ucd_parse_file (const gchar *filename,
- g_return_val_if_fail (list != NULL, FALSE);
-
- if (!g_file_get_contents (filename, &content, &length, &error)) {
-- g_warning ("Failed to load %s: %s", filename, error->message);
-+ g_warning ("Failed to load %s: %s",
-+ filename, error ? error->message : "");
- goto failed_to_parse_ucd_names_list;
- }
- head = end = content;
-diff --git a/util/IMdkit/FrameMgr.c b/util/IMdkit/FrameMgr.c
-index 9b497948..084b8810 100644
---- a/util/IMdkit/FrameMgr.c
-+++ b/util/IMdkit/FrameMgr.c
-@@ -27,6 +27,7 @@ SOFTWARE.
- ******************************************************************/
-
- #include <X11/Xlibint.h>
-+#include <assert.h>
- #include <stdlib.h>
- #include "FrameMgr.h"
-
-@@ -989,6 +990,7 @@ static XimFrameType FrameInstGetNextType(FrameInst fi, XimFrameTypeInfo info)
- while (number > 0)
- {
- i = _FrameInstDecrement (fi->template, i);
-+ assert (i >= 0);
- size += _FrameInstGetItemSize (fi, i);
- number--;
- }
-@@ -1138,6 +1140,7 @@ static XimFrameType FrameInstPeekNextType (FrameInst fi, XimFrameTypeInfo info)
- while (number > 0)
- {
- i = _FrameInstDecrement (fi->template, i);
-+ assert (i >= 0);
- size += _FrameInstGetItemSize (fi, i);
- number--;
- }
-@@ -1356,6 +1359,7 @@ static FmStatus FrameInstSetSize (FrameInst fi, int num)
- break;
- }
- /*endswitch*/
-+ assert (i >= 0);
- i = _FrameInstIncrement(fi->template, i);
- }
- /*endwhile*/
-@@ -1457,6 +1461,7 @@ static FmStatus FrameInstSetIterCount (FrameInst fi, int num)
- break;
- }
- /*endswitch*/
-+ assert (i >= 0);
- i = _FrameInstIncrement (fi->template, i);
- }
- /*endwhile*/
-@@ -1474,6 +1479,7 @@ static int FrameInstGetTotalSize (FrameInst fi)
- while (fi->template[i].type != EOL)
- {
- size += _FrameInstGetItemSize (fi, i);
-+ assert (i >= 0);
- i = _FrameInstIncrement (fi->template, i);
- }
- /*endwhile*/
-@@ -2419,6 +2425,7 @@ static int _FrameInstGetItemSize (FrameInst fi, int cur_no)
- size = 0;
- while (number > 0)
- {
-+ assert (i >= 0);
- i = _FrameInstDecrement (fi->template, i);
- size += _FrameInstGetItemSize (fi, i);
- number--;
-diff --git a/util/IMdkit/IMConn.c b/util/IMdkit/IMConn.c
-index 6d365893..8e8b8ece 100644
---- a/util/IMdkit/IMConn.c
-+++ b/util/IMdkit/IMConn.c
-@@ -83,7 +83,7 @@ static char *_FindModifiers (XIMArg *args)
- {
- char *modifiers;
-
-- while (args->name)
-+ while (args && args->name)
- {
- if (strcmp (args->name, IMModifiers) == 0)
- {
-@@ -144,8 +144,10 @@ XIMS IMOpenIM (Display *display, ...)
- modifiers = _FindModifiers (args);
-
- ims = _GetIMS (modifiers);
-- if (ims == (XIMS) NULL)
-+ if (ims == (XIMS) NULL) {
-+ XFree (args);
- return (XIMS) NULL;
-+ }
- /*endif*/
-
- ims->core.display = display;
-diff --git a/util/IMdkit/i18nClbk.c b/util/IMdkit/i18nClbk.c
-index b3edf3ad..f55f970f 100644
---- a/util/IMdkit/i18nClbk.c
-+++ b/util/IMdkit/i18nClbk.c
-@@ -55,6 +55,7 @@ int _Xi18nGeometryCallback (XIMS ims, IMProtocol *call_data)
- if (!reply)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return False;
- }
- /*endif*/
-@@ -97,6 +98,7 @@ int _Xi18nPreeditStartCallback (XIMS ims, IMProtocol *call_data)
- if (!reply)
- {
- _Xi18nSendMessage(ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return False;
- }
- /*endif*/
-@@ -159,6 +161,7 @@ int _Xi18nPreeditDrawCallback (XIMS ims, IMProtocol *call_data)
- if (!reply)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return False;
- }
- /*endif*/
-@@ -212,6 +215,7 @@ int _Xi18nPreeditCaretCallback (XIMS ims, IMProtocol *call_data)
- if (!reply)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return False;
- }
- /*endif*/
-@@ -256,6 +260,7 @@ int _Xi18nPreeditDoneCallback (XIMS ims, IMProtocol *call_data)
- if (!reply)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return False;
- }
- /*endif*/
-@@ -297,6 +302,7 @@ int _Xi18nStatusStartCallback (XIMS ims, IMProtocol *call_data)
- if (!reply)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return False;
- }
- /*endif*/
-@@ -363,6 +369,7 @@ int _Xi18nStatusDrawCallback (XIMS ims, IMProtocol *call_data)
- if (!reply)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return False;
- }
- /*endif*/
-@@ -390,6 +397,7 @@ int _Xi18nStatusDrawCallback (XIMS ims, IMProtocol *call_data)
- if (!reply)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return False;
- }
- /*endif*/
-@@ -435,6 +443,7 @@ int _Xi18nStatusDoneCallback (XIMS ims, IMProtocol *call_data)
- if (!reply)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return False;
- }
- /*endif*/
-@@ -479,6 +488,7 @@ int _Xi18nStringConversionCallback (XIMS ims, IMProtocol *call_data)
- if (!reply)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return False;
- }
- /*endif*/
-diff --git a/util/IMdkit/i18nIc.c b/util/IMdkit/i18nIc.c
-index 87445986..289837a6 100644
---- a/util/IMdkit/i18nIc.c
-+++ b/util/IMdkit/i18nIc.c
-@@ -475,8 +475,10 @@ static XICAttribute *CreateNestedList (CARD16 attr_id,
- /*endif*/
- memset (nest_list, 0, sizeof (XICAttribute));
- nest_list->value = (void *) malloc (value_length);
-- if (nest_list->value == NULL)
-+ if (nest_list->value == NULL) {
-+ XFree (nest_list);
- return NULL;
-+ }
- /*endif*/
- memset (nest_list->value, 0, value_length);
-
-@@ -816,6 +818,7 @@ void _Xi18nChangeIC (XIMS ims,
- if (!reply)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return;
- }
- /*endif*/
-@@ -973,8 +976,10 @@ void _Xi18nGetIC (XIMS ims, IMProtocol *call_data, unsigned char *p)
- getic->ic_attr = ic_attr;
- if (i18n_core->address.improto)
- {
-- if (!(i18n_core->address.improto (ims, call_data)))
-+ if (!(i18n_core->address.improto (ims, call_data))) {
-+ XFree (attrID_list);
- return;
-+ }
- /*endif*/
- if (_Xi18nNeedSwap (i18n_core, connect_id))
- SwapAttributes(getic->ic_attr, getic->ic_attr_num);
-@@ -1020,6 +1025,8 @@ void _Xi18nGetIC (XIMS ims, IMProtocol *call_data, unsigned char *p)
- if (reply == NULL)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ XFree (attrID_list);
-+ FrameMgrFree (fm);
- return;
- }
- /*endif*/
-diff --git a/util/IMdkit/i18nMethod.c b/util/IMdkit/i18nMethod.c
-index 203f8315..36dd28ac 100644
---- a/util/IMdkit/i18nMethod.c
-+++ b/util/IMdkit/i18nMethod.c
-@@ -895,6 +895,7 @@ static Status xi18n_forwardEvent (XIMS ims, XPointer xp)
- 0,
- 0,
- 0);
-+ FrameMgrFree (fm);
- return False;
- }
- /*endif*/
-@@ -964,6 +965,7 @@ static Status xi18n_commit (XIMS ims, XPointer xp)
- 0,
- 0,
- 0);
-+ FrameMgrFree (fm);
- return False;
- }
- /*endif*/
-@@ -997,6 +999,7 @@ static Status xi18n_commit (XIMS ims, XPointer xp)
- 0,
- 0,
- 0);
-+ FrameMgrFree (fm);
- return False;
- }
- /*endif*/
-@@ -1132,6 +1135,7 @@ static int xi18n_syncXlib (XIMS ims, XPointer xp)
- reply = (unsigned char *) malloc (total_size);
- if (!reply) {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return False;
- }
- memset (reply, 0, total_size);
-diff --git a/util/IMdkit/i18nOffsetCache.c b/util/IMdkit/i18nOffsetCache.c
-index c952d5b4..d5379051 100644
---- a/util/IMdkit/i18nOffsetCache.c
-+++ b/util/IMdkit/i18nOffsetCache.c
-@@ -27,9 +27,11 @@
- */
-
- #include <X11/Xlib.h>
-+#include <assert.h>
- #include <stddef.h>
- #include "IMdkit.h"
- #include "Xi18n.h"
-+#include "Xi18n.h"
-
- /*
- * The XIM specification does not limit the number of window properties
-@@ -52,9 +54,11 @@ void _Xi18nInitOffsetCache (Xi18nOffsetCache *offset_cache)
- unsigned long _Xi18nLookupPropertyOffset (Xi18nOffsetCache *offset_cache,
- Atom key)
- {
-- Xi18nAtomOffsetPair *data = offset_cache->data;
-+ Xi18nAtomOffsetPair *data;
- size_t i;
-
-+ assert (offset_cache);
-+ data = offset_cache->data;
- for (i = 0; i < offset_cache->size; ++i) {
- if (data[i].key == key) {
- return data[i].offset;
-@@ -70,6 +74,7 @@ void _Xi18nSetPropertyOffset (Xi18nOffsetCache *offset_cache, Atom key,
- Xi18nAtomOffsetPair *data = offset_cache->data;
- size_t i;
-
-+ assert (data != NULL);
- for (i = 0; i < offset_cache->size; ++i) {
- if (data[i].key == key) {
- data[i].offset = offset;
-@@ -79,11 +84,19 @@ void _Xi18nSetPropertyOffset (Xi18nOffsetCache *offset_cache, Atom key,
-
- if (++offset_cache->size > offset_cache->capacity) {
- offset_cache->capacity *= OFFSET_CACHE_GROWTH_FACTOR;
-- offset_cache->data = data = (Xi18nAtomOffsetPair *) realloc (data,
-+ offset_cache->data = (Xi18nAtomOffsetPair *) realloc (data,
- offset_cache->capacity * sizeof (Xi18nAtomOffsetPair));
-+ if (offset_cache->data == NULL) {
-+ offset_cache->data = data;
-+ --offset_cache->size;
-+ }
-+ data = offset_cache->data;
- }
-
-- data[i].key = key;
-- data[i].offset = offset;
-+ assert (data != NULL);
-+ if (offset_cache->size > 0) {
-+ data[i].key = key;
-+ data[i].offset = offset;
-+ }
- }
-
-diff --git a/util/IMdkit/i18nPtHdr.c b/util/IMdkit/i18nPtHdr.c
-index 2e673541..eaeeee1c 100644
---- a/util/IMdkit/i18nPtHdr.c
-+++ b/util/IMdkit/i18nPtHdr.c
-@@ -110,6 +110,7 @@ static void ConnectMessageProc (XIMS ims,
- if (!reply)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return;
- }
- /*endif*/
-@@ -230,6 +231,7 @@ static void OpenMessageProc(XIMS ims, IMProtocol *call_data, unsigned char *p)
- if (!reply)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return;
- }
- /*endif*/
-@@ -312,6 +314,7 @@ static void CloseMessageProc (XIMS ims,
- 0,
- 0,
- 0);
-+ FrameMgrFree (fm);
- return;
- }
- /*endif*/
-@@ -513,6 +516,10 @@ static void QueryExtensionMessageProc (XIMS ims,
- 0,
- 0,
- 0);
-+ FrameMgrFree (fm);
-+ for (i = 0; i < reply_number; i++)
-+ XFree (ext_list[i].name);
-+ XFree ((char *) ext_list);
- return;
- }
- /*endif*/
-@@ -610,8 +617,10 @@ static void GetIMValueFromName (Xi18n i18n_core,
-
- total_size = FrameMgrGetTotalSize (fm);
- data = (unsigned char *) malloc (total_size);
-- if (!data)
-+ if (!data) {
-+ FrameMgrFree (fm);
- return;
-+ }
- /*endif*/
- memset (data, 0, total_size);
- FrameMgrSetBuffer (fm, data);
-@@ -666,11 +675,12 @@ static XIMAttribute *MakeIMAttributeList (Xi18n i18n_core,
- /*endfor*/
- }
- /*endfor*/
-- attrib_list = (XIMAttribute *) malloc (sizeof (XIMAttribute)*list_num);
-+ attrib_list =
-+ (XIMAttribute *) malloc (sizeof (XIMAttribute)*(list_num + 1));
- if (!attrib_list)
- return NULL;
- /*endif*/
-- memset (attrib_list, 0, sizeof (XIMAttribute)*list_num);
-+ memset (attrib_list, 0, sizeof (XIMAttribute)*(list_num + 1));
- number_ret = list_num;
- list_num = 0;
- for (i = 0; i < *number; i++)
-@@ -805,6 +815,10 @@ static void GetIMValuesMessageProc (XIMS ims,
- if (!reply)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
-+ for (i = 0; i < iter_count; i++)
-+ XFree(im_attribute_list[i].value);
-+ XFree (im_attribute_list);
- return;
- }
- /*endif*/
-@@ -961,6 +975,7 @@ static void DestroyICMessageProc (XIMS ims,
- if (!reply)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return;
- }
- /*endif*/
-@@ -1026,6 +1041,7 @@ static void ResetICMessageProc (XIMS ims,
- if (!reply)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return;
- }
- /*endif*/
-@@ -1072,7 +1088,7 @@ static int WireEventToEvent (Xi18n i18n_core,
- /* get & set serial */
- FrameMgrGetToken(fm, c16);
- ev->xany.serial = (unsigned long)c16;
-- ev->xany.serial |= serial << 16;
-+ ev->xany.serial |= ((unsigned long)serial) << 16;
- ev->xany.send_event = False;
- ev->xany.display = i18n_core->address.dpy;
-
-@@ -1308,6 +1324,7 @@ static void TriggerNotifyMessageProc (XIMS ims,
- if (!reply)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return;
- }
- /*endif*/
-@@ -1443,7 +1460,7 @@ static void EncodingNegotiatonMessageProc (XIMS ims,
- if (byte_length > 0)
- {
- enc_nego->encodinginfo = (XIMStr *) malloc (sizeof (XIMStr)*10);
-- memset (enc_nego->encoding, 0, sizeof (XIMStr)*10);
-+ memset (enc_nego->encodinginfo, 0, sizeof (XIMStr)*10);
- i = 0;
- while (FrameMgrIsIterLoopEnd (fm, &status) == False)
- {
-@@ -1488,6 +1505,7 @@ static void EncodingNegotiatonMessageProc (XIMS ims,
- if (!reply)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return;
- }
- /*endif*/
-diff --git a/util/IMdkit/i18nUtil.c b/util/IMdkit/i18nUtil.c
-index 6557bd1a..109dcdf9 100644
---- a/util/IMdkit/i18nUtil.c
-+++ b/util/IMdkit/i18nUtil.c
-@@ -148,6 +148,7 @@ void _Xi18nSendMessage (XIMS ims,
- if (reply_hdr == NULL)
- {
- _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-+ FrameMgrFree (fm);
- return;
- }
- /*endif*/
-@@ -163,7 +164,8 @@ void _Xi18nSendMessage (XIMS ims,
- replyp = reply;
- memmove (reply, reply_hdr, header_size);
- replyp += header_size;
-- memmove (replyp, data, length);
-+ if (length > 0 && data != NULL)
-+ memmove (replyp, data, length);
-
- i18n_core->methods.send (ims, connect_id, reply, reply_length);
-
-@@ -202,8 +204,10 @@ void _Xi18nSendTriggerKey (XIMS ims, CARD16 connect_id)
- total_size = FrameMgrGetTotalSize (fm);
-
- reply = (unsigned char *) malloc (total_size);
-- if (!reply)
-+ if (!reply) {
-+ FrameMgrFree (fm);
- return;
-+ }
- /*endif*/
- memset (reply, 0, total_size);
- FrameMgrSetBuffer (fm, reply);
-@@ -257,8 +261,10 @@ void _Xi18nSetEventMask (XIMS ims,
-
- total_size = FrameMgrGetTotalSize (fm);
- reply = (unsigned char *) malloc (total_size);
-- if (!reply)
-+ if (!reply) {
-+ FrameMgrFree (fm);
- return;
-+ }
- /*endif*/
- memset (reply, 0, total_size);
- FrameMgrSetBuffer (fm, reply);
-diff --git a/util/IMdkit/i18nX.c b/util/IMdkit/i18nX.c
-index 8385aba9..5e5c15fa 100644
---- a/util/IMdkit/i18nX.c
-+++ b/util/IMdkit/i18nX.c
-@@ -31,6 +31,7 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ******************************************************************/
-
-+#include <assert.h>
- #include <stddef.h>
- #include <limits.h>
- #include <X11/Xlib.h>
-@@ -92,6 +93,7 @@ static unsigned char *ReadXIMMessage (XIMS ims,
- client = client->next;
- }
-
-+ assert (client);
- if (ev->format == 8) {
- /* ClientMessage only */
- XimProtoHdr *hdr = (XimProtoHdr *) ev->data.b;
-@@ -158,6 +160,7 @@ static unsigned char *ReadXIMMessage (XIMS ims,
- /* The property data is retrieved in 32-bit chunks */
- long_begin = offset / 4;
- long_end = (end + 3) / 4;
-+ assert (x_client);
- return_code = XGetWindowProperty (i18n_core->address.dpy,
- x_client->accept_win,
- atom,
-@@ -276,11 +279,11 @@ static Bool Xi18nXEnd(XIMS ims)
- static char *MakeNewAtom (CARD16 connect_id, char *atomName)
- {
- static int sequence = 0;
--
- sprintf (atomName,
- "_server%d_%d",
- connect_id,
-- ((sequence > 20) ? (sequence = 0) : sequence++));
-+ ((sequence > 20) ? (sequence = 0) : (0x1f & sequence)));
-+ sequence++;
- return atomName;
- }
-
-@@ -418,13 +421,16 @@ static Bool Xi18nXWait (XIMS ims,
- &&
- (hdr->minor_opcode == minor_opcode))
- {
-+ XFree (packet);
- return True;
- }
- else if (hdr->major_opcode == XIM_ERROR)
- {
-+ XFree (packet);
- return False;
- }
- /*endif*/
-+ XFree (packet);
- }
- /*endif*/
- }
---
-2.17.1
-
-From be7554cea294aa13a65895b66b26e5f1fa4a1897 Mon Sep 17 00:00:00 2001
-From: Ryutaroh Matsumoto
- <36657667+ryutaroh-matsumoto@users.noreply.github.com>
-Date: Thu, 2 Aug 2018 08:10:04 +0900
-Subject: [PATCH] option --monitor-timeout should be removed
-
-ibus-daemon(1) has explanation of --monitor-timeout, but main.c does not accept it and make an error.
----
- bus/ibus-daemon.1.in | 3 ---
- 1 file changed, 3 deletions(-)
-
-diff --git a/bus/ibus-daemon.1.in b/bus/ibus-daemon.1.in
-index 2dc982b2..a3d0d03a 100644
---- a/bus/ibus-daemon.1.in
-+++ b/bus/ibus-daemon.1.in
-@@ -62,9 +62,6 @@ auto, refresh, none is available.
- \fB\-o\fR, \fB\-\-timeout\fR=\fItimeout\fR [default is 2000]
- dbus reply timeout in milliseconds.
- .TP
--\fB\-j\fR, \fB\-\-monitor\-timeout\fR=\fItimeout\fR [default is 0]
--timeout of poll changes of engines in seconds. 0 to disable it.
--.TP
- \fB\-m\fR, \fB\-\-mem\-profile\fR
- enable memory profile, send SIGUSR2 to print out the memory profile.
- .TP
---
-2.17.1
-
-From 5f44e7307771685c70202f996e39e9aa68d48d2e Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Fri, 3 Aug 2018 14:58:10 +0900
-Subject: [PATCH] data/dconf: Add man pages of 00-upstream-settings(5) and
- ibus(5)
-
-Also delete --mem-profile option in ibus-daemon(1)
----
- bus/ibus-daemon.1.in | 3 --
- data/dconf/00-upstream-settings.5.in | 40 ++++++++++++++++++++++
- data/dconf/Makefile.am | 50 ++++++++++++++++++----------
- data/dconf/ibus.5.in | 39 ++++++++++++++++++++++
- ui/gtk3/ibus-emoji.7.in | 6 ++--
- 5 files changed, 114 insertions(+), 24 deletions(-)
- create mode 100644 data/dconf/00-upstream-settings.5.in
- create mode 100644 data/dconf/ibus.5.in
-
-diff --git a/bus/ibus-daemon.1.in b/bus/ibus-daemon.1.in
-index a3d0d03a..ed975aed 100644
---- a/bus/ibus-daemon.1.in
-+++ b/bus/ibus-daemon.1.in
-@@ -62,9 +62,6 @@ auto, refresh, none is available.
- \fB\-o\fR, \fB\-\-timeout\fR=\fItimeout\fR [default is 2000]
- dbus reply timeout in milliseconds.
- .TP
--\fB\-m\fR, \fB\-\-mem\-profile\fR
--enable memory profile, send SIGUSR2 to print out the memory profile.
--.TP
- \fB\-v\fR, \fB\-\-verbose\fR
- verbose.
-
-diff --git a/data/dconf/00-upstream-settings.5.in b/data/dconf/00-upstream-settings.5.in
-new file mode 100644
-index 00000000..b7a56fda
---- /dev/null
-+++ b/data/dconf/00-upstream-settings.5.in
-@@ -0,0 +1,40 @@
-+.\" This file is distributed under the same license as the ibus
-+.\" package.
-+.\" Copyright (C) Takao Fujiwara <takao.fujiwara1@gmail.com>, 2018.
-+.\"
-+.TH 00\-UPSTREAM\-SETTINGS "5" "August 2018" "@VERSION@" "User Commands"
-+.SH NAME
-+.B 00\-upstream\-settings
-+\- dconf configuration file
-+
-+.SH SYNOPSIS
-+.B /etc/dconf/db/ibus.d/00\-upstream\-settings
-+
-+.SH DESCRIPTION
-+
-+.PP
-+IBus is an Intelligent Input Bus. It is a new input framework for Linux
-+OS. It provides full featured and user friendly input method user
-+interface. It also may help developers to develop input method easily.
-+
-+.PP
-+.B 00\-upstream\-settings
-+is a text configuration file of dconf and can be converted to
-+/etc/dconf/db/ibus by
-+.B dconf update
-+command with a write privilege in /etc/dconf/db. /etc/dconf/db/ibus is a
-+database file of dconf and saves the IBus default settings. The saved keys
-+and values can be readed by dconf command.
-+
-+.PP
-+.RS 4
-+.nf
-+env DCONF_PROFILE=ibus dconf list /desktop/ibus/
-+.RE
-+
-+.SH BUGS
-+If you find a bug, please report it at https://github.com/ibus/ibus/issues
-+
-+.SH "SEE ALSO"
-+.BR dconf (1)
-+.BR ibus (5)
-diff --git a/data/dconf/Makefile.am b/data/dconf/Makefile.am
-index 7f0d0fd8..433d9937 100644
---- a/data/dconf/Makefile.am
-+++ b/data/dconf/Makefile.am
-@@ -4,7 +4,7 @@
- #
- # Copyright (c) 2007-2010 Peng Huang <shawn.p.huang@gmail.com>
- # Copyright (c) 2011 Daiki Ueno <ueno@unixuser.org>
--# Copyright (c) 2007-2011 Red Hat, Inc.
-+# Copyright (c) 2007-2018 Red Hat, Inc.
- #
- # This library is free software; you can redistribute it and/or
- # modify it under the terms of the GNU Lesser General Public
-@@ -28,22 +28,6 @@ dist_gsettingsconvert_DATA = ibus.convert
- @GSETTINGS_RULES@
- @INTLTOOL_XML_NOMERGE_RULE@
-
--EXTRA_DIST = \
-- $(gsettings_schemas_in_files) \
-- make-dconf-override-db.sh \
-- profile/ibus \
-- 00-upstream-settings \
-- $(NULL)
--
--CLEANFILES = \
-- $(gsettings_SCHEMAS) \
-- $(NULL)
--
--MAINTAINERCLEANFILES = \
-- $(gsettings_schemas_in_files) \
-- 00-upstream-settings \
-- $(NULL)
--
- dconfprofiledir = $(sysconfdir)/dconf/profile
- dconfprofile_DATA = profile/ibus
-
-@@ -60,9 +44,39 @@ org.freedesktop.ibus.gschema.xml.in: $(top_srcdir)/data/ibus.schemas.in
- $(AM_V_GEN) $(srcdir)/make-dconf-override-db.sh > $@ || \
- { rc=$$?; $(RM) -rf $@; exit $$rc; }
-
-+man_5_in_files = 00-upstream-settings.5.in ibus.5.in
-+man_5_files = $(man_5_in_files:.5.in=.5)
-+man_5_DATA =$(man_5_files:.5=.5.gz)
-+man_5dir = $(mandir)/man5
-+%.5: %.5.in
-+ $(AM_V_GEN) sed \
-+ -e 's|@VERSION[@]|$(VERSION)|g' $< > $@.tmp && \
-+ mv $@.tmp $@
-+%.5.gz: %.5
-+ $(AM_V_GEN) gzip -c $< > $@.tmp && mv $@.tmp $@
-+
- install-data-hook:
- if test -z "$(DESTDIR)"; then \
-- dconf update; \
-+ dconf update; \
- fi
-
-+EXTRA_DIST = \
-+ $(gsettings_schemas_in_files) \
-+ $(man_5_in_files) \
-+ make-dconf-override-db.sh \
-+ profile/ibus \
-+ 00-upstream-settings \
-+ $(NULL)
-+
-+CLEANFILES = \
-+ $(gsettings_SCHEMAS) \
-+ $(man_5_DATA) \
-+ $(man_5_files) \
-+ $(NULL)
-+
-+MAINTAINERCLEANFILES = \
-+ $(gsettings_schemas_in_files) \
-+ 00-upstream-settings \
-+ $(NULL)
-+
- -include $(top_srcdir)/git.mk
-diff --git a/data/dconf/ibus.5.in b/data/dconf/ibus.5.in
-new file mode 100644
-index 00000000..d959c7e3
---- /dev/null
-+++ b/data/dconf/ibus.5.in
-@@ -0,0 +1,39 @@
-+.\" This file is distributed under the same license as the ibus
-+.\" package.
-+.\" Copyright (C) Takao Fujiwara <takao.fujiwara1@gmail.com>, 2018.
-+.\"
-+.TH IBUS "5" "August 2018" "@VERSION@" "User Commands"
-+.SH NAME
-+.B IBUS
-+\- dconf database file for IBus
-+
-+.SH SYNOPSIS
-+.B /etc/dconf/db/ibus
-+
-+.SH DESCRIPTION
-+
-+.PP
-+IBus is an Intelligent Input Bus. It is a new input framework for Linux
-+OS. It provides full featured and user friendly input method user
-+interface. It also may help developers to develop input method easily.
-+
-+.PP
-+.B /etc/dconf/db/ibus
-+is a database file dconf and saves the IBus default settings. It can be
-+generated from /etc/dconf/db/ibus.d/00\-upstream\-settings by
-+.B dconf update
-+command with a write privilege in /etc/dconf/db. The saved keys
-+and values can be readed by dconf command.
-+
-+.PP
-+.RS 4
-+.nf
-+env DCONF_PROFILE=ibus dconf list /desktop/ibus/
-+.RE
-+
-+.SH BUGS
-+If you find a bug, please report it at https://github.com/ibus/ibus/issues
-+
-+.SH "SEE ALSO"
-+.BR dconf (1)
-+.BR 00\-upstream\-settings (5)
-diff --git a/ui/gtk3/ibus-emoji.7.in b/ui/gtk3/ibus-emoji.7.in
-index 3a2db2c0..b8b43574 100644
---- a/ui/gtk3/ibus-emoji.7.in
-+++ b/ui/gtk3/ibus-emoji.7.in
-@@ -1,10 +1,10 @@
- .\" This file is distributed under the same license as the ibus
- .\" package.
--.\" Copyright (C) Takao Fujiwara <takao.fujiwara1@gmail.com>, 2017.
-+.\" Copyright (C) Takao Fujiwara <takao.fujiwara1@gmail.com>, 2017-2018.
- .\"
--.TH "IBUS EMOJI" 1 "May 2017" "@VERSION@" "User Commands"
-+.TH "IBUS EMOJI" 1 "August 2018" "@VERSION@" "User Commands"
- .SH NAME
--.B ibus emoji utility
-+.B ibus-emoji
- \- Call the IBus emoji utility by
- .B IBus Emojier
-
---
-2.17.1
-
-From f328fd67f479faa46ca87bf3c85eed7080ec5ec0 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Mon, 6 Aug 2018 12:33:44 +0900
-Subject: [PATCH] client/gtk2: Add IBUS_DISCARD_PASSWORD for firefox and
- chrome
-
-popup window in firefox is closed in Xorg GNOME when password entry
-is focus on. It's caused by gnome-shell [1].
-Now IBUS_DISCARD_PASSWORD and IBUS_DISCARD_PASSWORD_APPS enviroment
-variables are implemented in IBus GTK clients as a workaround.
-
-env IBUS_DISCARD_PASSWORD=1 firefox
-or
-export IBUS_DISCARD_PASSWORD_APPS='firefox,.*chrome.*'
-
-can discard typing characters on the password entries.
-
-[1] https://gitlab.gnome.org/GNOME/gnome-shell/issues/391
-
-BUG=https://github.com/ibus/ibus/issues/2002
----
- client/gtk2/ibusimcontext.c | 77 ++++++++++++++++++++++++++++---------
- 1 file changed, 58 insertions(+), 19 deletions(-)
-
-diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c
-index a806382d..e4de52d9 100644
---- a/client/gtk2/ibusimcontext.c
-+++ b/client/gtk2/ibusimcontext.c
-@@ -91,6 +91,9 @@ static guint _key_snooper_id = 0;
-
- static gboolean _use_sync_mode = FALSE;
-
-+static const gchar *_discard_password_apps = "";
-+static gboolean _use_discard_password = FALSE;
-+
- static GtkIMContext *_focus_im_context = NULL;
- static IBusInputContext *_fake_context = NULL;
- static GdkWindow *_input_window = NULL;
-@@ -157,7 +160,7 @@ static gboolean _slave_delete_surrounding_cb
- IBusIMContext *context);
- static void _request_surrounding_text (IBusIMContext *context);
- static void _create_fake_input_context (void);
--static void _set_content_type (IBusIMContext *context);
-+static gboolean _set_content_type (IBusIMContext *context);
-
-
-
-@@ -383,7 +386,7 @@ _request_surrounding_text (IBusIMContext *context)
- }
- }
-
--static void
-+static gboolean
- _set_content_type (IBusIMContext *context)
- {
- #if GTK_CHECK_VERSION (3, 6, 0)
-@@ -396,11 +399,18 @@ _set_content_type (IBusIMContext *context)
- "input-hints", &hints,
- NULL);
-
-+ if (_use_discard_password) {
-+ if (purpose == GTK_INPUT_PURPOSE_PASSWORD ||
-+ purpose == GTK_INPUT_PURPOSE_PIN) {
-+ return FALSE;
-+ }
-+ }
- ibus_input_context_set_content_type (context->ibuscontext,
- purpose,
- hints);
- }
- #endif
-+ return TRUE;
- }
-
-
-@@ -608,24 +618,45 @@ ibus_im_context_class_init (IBusIMContextClass *class)
- _use_key_snooper = !_get_boolean_env ("IBUS_DISABLE_SNOOPER",
- !(ENABLE_SNOOPER));
- _use_sync_mode = _get_boolean_env ("IBUS_ENABLE_SYNC_MODE", FALSE);
-+ _use_discard_password = _get_boolean_env ("IBUS_DISCARD_PASSWORD", FALSE);
-+
-+#define CHECK_APP_IN_CSV_ENV_VARIABLES(retval, \
-+ env_apps, \
-+ fallback_apps, \
-+ value_if_found) \
-+{ \
-+ const gchar * prgname = g_get_prgname (); \
-+ gchar **p; \
-+ gchar ** apps; \
-+ if (g_getenv ((#env_apps))) { \
-+ fallback_apps = g_getenv (#env_apps); \
-+ } \
-+ apps = g_strsplit ((fallback_apps), ",", 0); \
-+ for (p = apps; *p != NULL; p++) { \
-+ if (g_regex_match_simple (*p, prgname, 0, 0)) { \
-+ retval = (value_if_found); \
-+ break; \
-+ } \
-+ } \
-+ g_strfreev (apps); \
-+}
-
- /* env IBUS_DISABLE_SNOOPER does not exist */
- if (_use_key_snooper) {
- /* disable snooper if app is in _no_snooper_apps */
-- const gchar * prgname = g_get_prgname ();
-- if (g_getenv ("IBUS_NO_SNOOPER_APPS")) {
-- _no_snooper_apps = g_getenv ("IBUS_NO_SNOOPER_APPS");
-- }
-- gchar **p;
-- gchar ** apps = g_strsplit (_no_snooper_apps, ",", 0);
-- for (p = apps; *p != NULL; p++) {
-- if (g_regex_match_simple (*p, prgname, 0, 0)) {
-- _use_key_snooper = FALSE;
-- break;
-- }
-- }
-- g_strfreev (apps);
-+ CHECK_APP_IN_CSV_ENV_VARIABLES (_use_key_snooper,
-+ IBUS_NO_SNOOPER_APPS,
-+ _no_snooper_apps,
-+ FALSE);
- }
-+ if (!_use_discard_password) {
-+ CHECK_APP_IN_CSV_ENV_VARIABLES (_use_discard_password,
-+ IBUS_DISCARD_PASSWORD_APPS,
-+ _discard_password_apps,
-+ TRUE);
-+ }
-+
-+#undef CHECK_APP_IN_CSV_ENV_VARIABLES
-
- /* init bus object */
- if (_bus == NULL) {
-@@ -926,7 +957,10 @@ ibus_im_context_focus_in (GtkIMContext *context)
-
- ibusimcontext->has_focus = TRUE;
- if (ibusimcontext->ibuscontext) {
-- _set_content_type (ibusimcontext);
-+ if (!_set_content_type (ibusimcontext)) {
-+ ibusimcontext->has_focus = FALSE;
-+ return;
-+ }
- ibus_input_context_focus_in (ibusimcontext->ibuscontext);
- }
-
-@@ -958,9 +992,14 @@ ibus_im_context_focus_out (GtkIMContext *context)
- return;
- }
-
-- g_object_remove_weak_pointer ((GObject *) context,
-- (gpointer *) &_focus_im_context);
-- _focus_im_context = NULL;
-+ /* If _use_discard_password is TRUE or GtkEntry has no visibility,
-+ * _focus_im_context is NULL.
-+ */
-+ if (_focus_im_context) {
-+ g_object_remove_weak_pointer ((GObject *) context,
-+ (gpointer *) &_focus_im_context);
-+ _focus_im_context = NULL;
-+ }
-
- ibusimcontext->has_focus = FALSE;
- if (ibusimcontext->ibuscontext) {
---
-2.17.1
-
-From dc5e7eeba30d0bc2327ffa562cdf6ca0ae23aecc Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Mon, 6 Aug 2018 15:26:42 +0900
-Subject: [PATCH] ui/gtk3: Show previous emojis with "history" annotation
-
----
- ui/gtk3/emojier.vala | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
-diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala
-index 7beb6f0a..85dcdceb 100644
---- a/ui/gtk3/emojier.vala
-+++ b/ui/gtk3/emojier.vala
-@@ -1294,8 +1294,14 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- return;
- }
- string? unicode_point = check_unicode_point(annotation);
-- GLib.SList<string>? total_emojis =
-- lookup_emojis_from_annotation(annotation);
-+ GLib.SList<string>? total_emojis = null;
-+ if (annotation.ascii_casecmp("history") == 0) {
-+ for (int i = 0; i < m_favorites.length; i++) {
-+ total_emojis.append(m_favorites[i].dup());
-+ }
-+ }
-+ if (total_emojis == null)
-+ total_emojis = lookup_emojis_from_annotation(annotation);
- if (total_emojis == null) {
- /* Users can type title strings against lower case.
- * E.g. "Smile" against "smile"
---
-2.17.1
-
-From 428e64eac8f7dc3ff60234435fe5f34d50126432 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Mon, 6 Aug 2018 15:59:06 +0900
-Subject: [PATCH] src: Describe "default" layout in ibus_engine_desc_new()
-
-BUG=https://github.com/ibus/ibus/issues/2011
----
- src/ibusenginedesc.h | 11 ++++++++++-
- 1 file changed, 10 insertions(+), 1 deletion(-)
-
-diff --git a/src/ibusenginedesc.h b/src/ibusenginedesc.h
-index 45ec06bf..00a98e41 100644
---- a/src/ibusenginedesc.h
-+++ b/src/ibusenginedesc.h
-@@ -2,7 +2,8 @@
- /* vim:set et sts=4: */
- /* bus - The Input Bus
- * Copyright (C) 2008-2015 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2008-2015 Red Hat, Inc.
-+ * Copyright (C) 2011-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2008-2018 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
-@@ -107,6 +108,10 @@ GType ibus_engine_desc_get_type (void);
- * @layout: Keyboard layout
- *
- * Creates a new #IBusEngineDesc.
-+ * If layout is "default", the engine inherits the current layout and
-+ * does not change the layout. The layouts "default" and "" are same.
-+ * E.g. If you switch JP XKB engine and an input method engine (IME),
-+ * the IME inherits the JP layout.
- *
- * Returns: A newly allocated IBusEngineDesc.
- */
-@@ -128,6 +133,10 @@ IBusEngineDesc *ibus_engine_desc_new (const gchar *name,
- * ibus_engine_desc_new_varargs() supports the va_list format.
- * name property is required. e.g.
- * ibus_engine_desc_new_varargs("name", "ibus-foo", "language", "us", NULL)
-+ * If layout is "default", the engine inherits the current layout and
-+ * does not change the layout. The layouts "default" and "" are same.
-+ * E.g. If you switch JP XKB engine and an input method engine (IME),
-+ * the IME inherits the JP layout.
- *
- * Returns: A newly allocated IBusEngineDesc.
- */
---
-2.17.1
-
reply other threads:[~2026-05-31 2:06 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=178019321700.1.14459109162438851166.rpms-ibus-3032216b57aa@fedoraproject.org \
--to=tfujiwar@redhat.com \
--cc=git-commits@fedoraproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox