716b06dccf
- Fix SEGV in panel_binding_parse_accelerator
9388 lines
347 KiB
Diff
9388 lines
347 KiB
Diff
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 9b26a4b46fa2635033d315e8babb8c4ca9869898 Mon Sep 17 00:00:00 2001
|
|
From: fujiwarat <takao.fujiwara1@gmail.com>
|
|
Date: Wed, 27 Jun 2018 12:18:26 +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 a NULL preedit is fixed in the first emoji candidate from the
|
|
emoji category window.
|
|
---
|
|
ui/gtk3/panelbinding.vala | 28 ++++++++++++++++------------
|
|
1 file changed, 16 insertions(+), 12 deletions(-)
|
|
|
|
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
|
|
|