diff --git a/ibus-HEAD.patch b/ibus-HEAD.patch deleted file mode 100644 index 65b7db7..0000000 --- a/ibus-HEAD.patch +++ /dev/null @@ -1,4358 +0,0 @@ -From e6bab7ab78c69d238a70a64e60963dd5a6711ffe Mon Sep 17 00:00:00 2001 -From: Felix Yan -Date: Fri, 19 May 2017 12:13:04 +0900 -Subject: [PATCH] Fix a typo in configure.ac - -BUG=https://github.com/ibus/ibus/pull/1927 -R=Shawn.P.Huang@gmail.com - -Review URL: https://codereview.appspot.com/317640043 - -Patch from Felix Yan . ---- - configure.ac | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/configure.ac b/configure.ac -index 219b89d..2cc96d1 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -727,7 +727,7 @@ Build options: - Enable surrounding-text $enable_surrounding_text - Enable libnotify $enable_libnotify - Enable Emoji dict $enable_emoji_dict -- Uicode Emoji directory $UNICODE_EMOJI_DIR -+ Unicode Emoji directory $UNICODE_EMOJI_DIR - CLDR annotation directory $EMOJI_ANNOTATION_DIR - Run test cases $enable_tests - ]) --- -2.9.3 - -From 4fe3050efa7335f82870fb1d5a1d170d20afc160 Mon Sep 17 00:00:00 2001 -From: fujiwarat -Date: Mon, 22 May 2017 12:04:28 +0900 -Subject: [PATCH] configure: Change relative paths to absolute ones - -BUG=https://github.com/ibus/ibus/issues/1926 -R=Shawn.P.Huang@gmail.com - -Review URL: https://codereview.appspot.com/322990043 ---- - configure.ac | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/configure.ac b/configure.ac -index 2cc96d1..cb48ad4 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -634,10 +634,21 @@ if test x"$enable_emoji_dict" = x"yes"; then - if test ! -f $UNICODE_EMOJI_DIR/emoji-test.txt ; then - AC_MSG_ERROR(Not found $UNICODE_EMOJI_DIR/emoji-test.txt. You can get \ - the emoji files from http://www.unicode.org/Public/emoji/4.0/) -+ else -+ # POSIX SHELL has no ${FOO:0:1} -+ head=`echo "$UNICODE_EMOJI_DIR" | cut -c1`; -+ if test $head != "/" ; then -+ UNICODE_EMOJI_DIR=`realpath "$UNICODE_EMOJI_DIR"` -+ fi - fi - if test ! -f $EMOJI_ANNOTATION_DIR/en.xml ; then - AC_MSG_ERROR(Not found $EMOJI_ANNOTATION_DIR/en.xml. You can get \ - https://github.com/fujiwarat/cldr-emoji-annotation) -+ else -+ head=`echo "$EMOJI_ANNOTATION_DIR" | cut -c1`; -+ if test $head != "/" ; then -+ EMOJI_ANNOTATION_DIR=`realpath "$EMOJI_ANNOTATION_DIR"` -+ fi - fi - enable_emoji_dict="yes (enabled, use --disable-emoji-dict to disable)" - fi --- -2.9.3 - -From 44d053577a6ac115f3fd3b7beb7bdd65da81aa64 Mon Sep 17 00:00:00 2001 -From: fujiwarat -Date: Wed, 24 May 2017 11:52:19 +0900 -Subject: [PATCH] engine: Add Malay and Mongolian keymaps - -R=Shawn.P.Huang@gmail.com - -Review URL: https://codereview.appspot.com/325790043 ---- - engine/simple.xml.in | 22 ++++++++++++++++++++++ - 1 file changed, 22 insertions(+) - -diff --git a/engine/simple.xml.in b/engine/simple.xml.in -index c08000f..f35d7a5 100644 ---- a/engine/simple.xml.in -+++ b/engine/simple.xml.in -@@ -706,5 +706,27 @@ - ibus-keyboard - 1 - -+ -+ xkb:my::msa -+ ms -+ GPL -+ Peng Huang <shawn.p.huang@gmail.com> -+ my -+ Malay (Jawi) -+ Malay (Jawi) -+ ibus-keyboard -+ 1 -+ -+ -+ xkb:mn::mon -+ mn -+ GPL -+ Peng Huang <shawn.p.huang@gmail.com> -+ mn -+ Mongolian -+ Mongolian -+ ibus-keyboard -+ 1 -+ - - --- -2.9.3 - -From 081d09f1a927f459dacda3bcc59a1678ca2f9a95 Mon Sep 17 00:00:00 2001 -From: fujiwarat -Date: Mon, 29 May 2017 11:54:31 +0900 -Subject: [PATCH] ui/gtk3: Emojier supports Ctrl-c,v,x and Ctrl-Shift-c - -Ctrl-[c|v|x] copy, paste, or cut the emoji annotatons. -Ctrl-Shift-c copies the selected emoji. -Also Ctrl-Backspace is implemented to delete an annotation word. -Also updated ibus-emoji.7.in man page. - -R=penghuang@google.com - -Review URL: https://codereview.appspot.com/316650043 ---- - ui/gtk3/emojier.vala | 58 +++++++++++++++++++++++++++++++++++++++++++++++-- - ui/gtk3/ibus-emoji.7.in | 11 ++++++++++ - 2 files changed, 67 insertions(+), 2 deletions(-) - -diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala -index d0d69ed..1d105fd 100644 ---- a/ui/gtk3/emojier.vala -+++ b/ui/gtk3/emojier.vala -@@ -1392,7 +1392,26 @@ class IBusEmojier : Gtk.ApplicationWindow { - return true; - case Gdk.Key.BackSpace: - if (m_entry.get_text().len() > 0) { -- GLib.Signal.emit_by_name(m_entry, "backspace"); -+ if ((modifiers & Gdk.ModifierType.CONTROL_MASK) != 0) { -+ GLib.Signal.emit_by_name(m_entry, "delete-from-cursor", -+ Gtk.DeleteType.WORD_ENDS, -1); -+ } else { -+ GLib.Signal.emit_by_name(m_entry, "backspace"); -+ } -+ return true; -+ } -+ break; -+ case Gdk.Key.Delete: -+ case Gdk.Key.KP_Delete: -+ if (m_entry.get_text().len() > 0) { -+ if ((modifiers & Gdk.ModifierType.CONTROL_MASK) != 0) { -+ GLib.Signal.emit_by_name(m_entry, "delete-from-cursor", -+ Gtk.DeleteType.WORD_ENDS, 1); -+ } else { -+ GLib.Signal.emit_by_name(m_entry, "delete-from-cursor", -+ Gtk.DeleteType.CHARS, 1); -+ } -+ return true; - } - break; - case Gdk.Key.space: -@@ -1445,6 +1464,10 @@ class IBusEmojier : Gtk.ApplicationWindow { - if (key_press_cursor_home_end(keyval, modifiers)) - return true; - break; -+ case Gdk.Key.Insert: -+ case Gdk.Key.KP_Insert: -+ GLib.Signal.emit_by_name(m_entry, "toggle-overwrite"); -+ return true; - } - - if ((modifiers & Gdk.ModifierType.CONTROL_MASK) != 0) { -@@ -1470,8 +1493,13 @@ class IBusEmojier : Gtk.ApplicationWindow { - return true; - break; - case Gdk.Key.u: -- if (key_press_escape()) -+ if (m_entry.get_text().len() > 0) { -+ GLib.Signal.emit_by_name(m_entry, -+ "delete-from-cursor", -+ Gtk.DeleteType.PARAGRAPH_ENDS, -+ -1); - return true; -+ } - break; - case Gdk.Key.a: - if (m_entry.get_text().len() > 0) { -@@ -1479,6 +1507,32 @@ class IBusEmojier : Gtk.ApplicationWindow { - return true; - } - break; -+ case Gdk.Key.x: -+ if (m_entry.get_text().len() > 0) { -+ GLib.Signal.emit_by_name(m_entry, "cut-clipboard"); -+ return true; -+ } -+ break; -+ case Gdk.Key.C: -+ case Gdk.Key.c: -+ if ((modifiers & Gdk.ModifierType.SHIFT_MASK) != 0) { -+ if (m_candidate_panel_is_visible) { -+ uint index = m_lookup_table.get_cursor_pos(); -+ var text = m_lookup_table.get_candidate(index).text; -+ Gtk.Clipboard clipboard = -+ Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD); -+ clipboard.set_text(text, -1); -+ clipboard.store(); -+ return true; -+ } -+ } else if (m_entry.get_text().len() > 0) { -+ GLib.Signal.emit_by_name(m_entry, "copy-clipboard"); -+ return true; -+ } -+ break; -+ case Gdk.Key.v: -+ GLib.Signal.emit_by_name(m_entry, "paste-clipboard"); -+ return true; - } - return false; - } -diff --git a/ui/gtk3/ibus-emoji.7.in b/ui/gtk3/ibus-emoji.7.in -index a5045f6..4ee8636 100644 ---- a/ui/gtk3/ibus-emoji.7.in -+++ b/ui/gtk3/ibus-emoji.7.in -@@ -83,6 +83,17 @@ Move to the next or previous page in the emoji list. - \fBHead, End, Control-h or Control-e\fR - Select the first or last emoji on the list if an annotation is not typed. - Otherwise move the cursor to the head or end in the typed annotation. -+.TP -+\fBControl-u\fR -+Erase the typed annotation. -+.TP -+\fBControl-x or Control-v or Control-c\fR -+Cut the selected annotation to the clipboard with Control-x. Paste -+the contents of the clipboard into the annotation entry with Control-v. -+Copy the selected annotation to the clipboard with Control-c. -+.TP -+\fBControl-Shift-c\fR -+Copy the selected emoji to the clipboard. - - .SH BUGS - If you find a bug, please report it at https://github.com/ibus/ibus/issues --- -2.9.3 - -From ad80999f5a10faee1a665a2232e1cf60be901cc8 Mon Sep 17 00:00:00 2001 -From: fujiwarat -Date: Mon, 29 May 2017 12:03:41 +0900 -Subject: [PATCH] Make all emoji dicts for fully qualified - -Currently only emoji-en.dict enables fully qualified since it imports -emoji-test.txt and it causes to hardly compare emojis between -emoji-en.dict and emoji-$lang.dict when m_show_emoji_variant -is enabled. E.g. U+1F3CC-FE0F-200D-2642-FE0F -Now emoji-$lang.dict also import emoji-test.txt and enables -fully qualified. - -R=penghuang@google.com - -Review URL: https://codereview.appspot.com/323860043 ---- - src/Makefile.am | 1 + - src/emoji-parser.c | 167 +++++++++++++++++++++++++++++++++++++++++++++------ - src/ibusemoji.c | 2 +- - ui/gtk3/emojier.vala | 34 +++++------ - 4 files changed, 169 insertions(+), 35 deletions(-) - -diff --git a/src/Makefile.am b/src/Makefile.am -index 27cd168..e7bc8be 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -263,6 +263,7 @@ dicts/emoji-en.dict: emoji-parser - --out $@; \ - else \ - $(builddir)/emoji-parser \ -+ --unicode-emoji-dir $(UNICODE_EMOJI_DIR) \ - --xml $(EMOJI_ANNOTATION_DIR)/$$f.xml \ - $$xml_derived_option \ - --out dicts/emoji-$$f.dict; \ -diff --git a/src/emoji-parser.c b/src/emoji-parser.c -index 5e6155b..fe3e4ef 100644 ---- a/src/emoji-parser.c -+++ b/src/emoji-parser.c -@@ -31,12 +31,20 @@ - * ASCII emoji annotations are saved in ../data/annotations/en_ascii.xml - */ - -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ - #include - - #ifdef HAVE_JSON_GLIB1 - #include - #endif - -+#ifdef HAVE_LOCALE_H -+#include -+#endif -+ - #include - - #include "ibusemoji.h" -@@ -65,8 +73,73 @@ struct _EmojiData { - EmojiDataSearchType search_type; - }; - -+typedef struct _NoTransData NoTransData; -+struct _NoTransData { -+ const gchar *xml_file; -+ const gchar *xml_derived_file; -+ GSList *emoji_list; -+}; -+ - static gchar *unicode_emoji_version; - -+ -+static void -+init_annotations (IBusEmojiData *emoji, -+ gpointer user_data) -+{ -+ g_return_if_fail (IBUS_IS_EMOJI_DATA (emoji)); -+ ibus_emoji_data_set_annotations (emoji, NULL); -+ ibus_emoji_data_set_description (emoji, ""); -+} -+ -+static void -+check_no_trans (IBusEmojiData *emoji, -+ NoTransData *no_trans_data) -+{ -+ const gchar *str = NULL; -+ g_return_if_fail (IBUS_IS_EMOJI_DATA (emoji)); -+ if (ibus_emoji_data_get_annotations (emoji) != NULL) -+ return; -+ str = ibus_emoji_data_get_emoji (emoji); -+ if (g_getenv ("IBUS_EMOJI_PARSER_DEBUG") != NULL) { -+ gchar *basename = NULL; -+ if (no_trans_data->xml_file) -+ basename = g_path_get_basename (no_trans_data->xml_file); -+ else if (no_trans_data->xml_derived_file) -+ basename = g_path_get_basename (no_trans_data->xml_derived_file); -+ else -+ basename = g_strdup ("WRONG FILE"); -+ g_warning ("Not found emoji %s in the file %s", str, basename); -+ g_free (basename); -+ } -+ no_trans_data->emoji_list = -+ g_slist_append (no_trans_data->emoji_list, g_strdup (str)); -+} -+ -+int -+strcmp_ibus_emoji_data_str (IBusEmojiData *emoji, -+ const gchar *str) -+{ -+ g_return_val_if_fail (IBUS_IS_EMOJI_DATA (emoji), -1); -+ return g_strcmp0 (ibus_emoji_data_get_emoji (emoji), str); -+} -+ -+static void -+delete_emoji_from_list (const gchar *str, -+ GSList **list) -+{ -+ IBusEmojiData *emoji; -+ -+ g_return_if_fail (list != NULL); -+ GSList *p = g_slist_find_custom (*list, -+ str, -+ (GCompareFunc)strcmp_ibus_emoji_data_str); -+ g_return_if_fail (p != NULL); -+ emoji = p->data; -+ *list = g_slist_remove (*list, emoji); -+ g_object_unref (emoji); -+} -+ - static void - reset_emoji_element (EmojiData *data) - { -@@ -79,6 +152,13 @@ reset_emoji_element (EmojiData *data) - g_clear_pointer (&data->description, g_free); - } - -+/** -+ * strcmp_novariant: -+ * -+ * Return 0 between non-fully-qualified and fully-qualified emojis. -+ * E.g. U+1F3CC-200D-2642 and U+1F3CC-FE0F-200D-2642-FE0F -+ * in case @a_variant or @b_variant == U+FE0F -+ */ - gint - strcmp_novariant (const gchar *a, - const gchar *b, -@@ -86,40 +166,54 @@ strcmp_novariant (const gchar *a, - gunichar b_variant) - { - gint retval; -- gchar *p = NULL; - GString *buff = NULL;; -+ gchar *head = NULL; -+ gchar *p; -+ gchar *variant = NULL; - gchar *substr = NULL; - - if (a_variant > 0) { -- if ((p = g_utf8_strchr (a, -1, a_variant)) != NULL) { -+ if (g_utf8_strchr (a, -1, a_variant) != NULL) { - buff = g_string_new (NULL); -- if (a != p) { -- substr = g_strndup (a, p - a); -- g_string_append (buff, substr); -- g_free (substr); -+ p = head = g_strdup (a); -+ while (*p != '\0') { -+ if ((variant = g_utf8_strchr (p, -1, a_variant)) == NULL) { -+ g_string_append (buff, p); -+ break; -+ } -+ if (p != variant) { -+ substr = g_strndup (p, variant - p); -+ g_string_append (buff, substr); -+ g_free (substr); -+ } -+ p = g_utf8_next_char (variant); - } -- p = g_utf8_next_char (p); -- if (*p != '\0') -- g_string_append (buff, p); - retval = g_strcmp0 (buff->str, b); - g_string_free (buff, TRUE); -+ g_free (head); - return retval; - } else { - return -1; - } - } else if (b_variant > 0) { -- if ((p = g_utf8_strchr (b, -1, b_variant)) != NULL) { -+ if (g_utf8_strchr (b, -1, b_variant) != NULL) { - buff = g_string_new (NULL); -- if (b != p) { -- substr = g_strndup (b, p - b); -- g_string_append (buff, substr); -- g_free (substr); -+ p = head = g_strdup (b); -+ while (*p != '\0') { -+ if ((variant = g_utf8_strchr (p, -1, b_variant)) == NULL) { -+ g_string_append (buff, p); -+ break; -+ } -+ if (p != variant) { -+ substr = g_strndup (p, variant - p); -+ g_string_append (buff, substr); -+ g_free (substr); -+ } -+ p = g_utf8_next_char (variant); - } -- p = g_utf8_next_char (p); -- if (*p != '\0') -- g_string_append (buff, p); - retval = g_strcmp0 (a, buff->str); - g_string_free (buff, TRUE); -+ g_free (head); - return retval; - } else { - return -1; -@@ -1117,6 +1211,12 @@ main (int argc, char *argv[]) - GOptionContext *context; - GError *error = NULL; - GSList *list = NULL; -+ gboolean is_en = TRUE; -+ -+#ifdef HAVE_LOCALE_H -+ /* To output emoji warnings. */ -+ setlocale (LC_ALL, ""); -+#endif - - prgname = g_path_get_basename (argv[0]); - g_set_prgname (prgname); -@@ -1144,12 +1244,45 @@ main (int argc, char *argv[]) - #endif - if (emoji_dir) - unicode_emoji_parse_dir (emoji_dir, &list); -+ if (list) { -+#define CHECK_IS_EN(file) if ((file)) { \ -+ gchar *basename = g_path_get_basename ((file)); \ -+ is_en = (g_ascii_strncasecmp (basename, "en.", 3) == 0) ? \ -+ TRUE : FALSE; \ -+ g_free (basename); \ -+} -+ -+ CHECK_IS_EN(xml_derived_file); -+ CHECK_IS_EN(xml_file); -+#undef CHECK_IS_EN -+ -+ /* Use English emoji-test.txt to get fully-qualified. */ -+ if (!is_en) -+ g_slist_foreach (list, (GFunc)init_annotations, NULL); -+ } - if (xml_file) - unicode_annotations_parse_xml_file (xml_file, &list, FALSE); - if (xml_derived_file) - unicode_annotations_parse_xml_file (xml_derived_file, &list, TRUE); - if (xml_ascii_file) - unicode_annotations_parse_xml_file (xml_ascii_file, &list, FALSE); -+ if (list != NULL && !is_en) { -+ /* If emoji-test.txt has an emoji but $lang.xml does not, clear it -+ * since the language dicts do not want English annotations. -+ */ -+ NoTransData no_trans_data = { -+ xml_file, -+ xml_derived_file, -+ NULL -+ }; -+ g_slist_foreach (list, (GFunc)check_no_trans, &no_trans_data); -+ if (no_trans_data.emoji_list) { -+ g_slist_foreach (no_trans_data.emoji_list, -+ (GFunc)delete_emoji_from_list, -+ &list); -+ g_slist_free_full (no_trans_data.emoji_list, g_free); -+ } -+ } - if (list != NULL && output) - ibus_emoji_data_save (output, list); - if (list != NULL && output_category) -diff --git a/src/ibusemoji.c b/src/ibusemoji.c -index d2e16c5..3d38c2a 100644 ---- a/src/ibusemoji.c -+++ b/src/ibusemoji.c -@@ -29,7 +29,7 @@ - #include "ibusinternal.h" - - #define IBUS_EMOJI_DATA_MAGIC "IBusEmojiData" --#define IBUS_EMOJI_DATA_VERSION (4) -+#define IBUS_EMOJI_DATA_VERSION (5) - - enum { - PROP_0 = 0, -diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala -index 1d105fd..95912bf 100644 ---- a/ui/gtk3/emojier.vala -+++ b/ui/gtk3/emojier.vala -@@ -190,9 +190,6 @@ class IBusEmojier : Gtk.ApplicationWindow { - private const string EMOJI_CATEGORY_OTHERS = N_("Others"); - private const unichar[] EMOJI_VARIANT_LIST = { - 0x1f3fb, 0x1f3fc, 0x1f3fd, 0x1f3fe, 0x1f3ff, 0x200d }; -- private const GLib.ActionEntry[] m_action_entries = { -- { "variant", check_action_variant_cb, null, "false", null } -- }; - - // Set the actual default values in the constructor - // because these fields are used for class_init() and static functions, -@@ -253,7 +250,13 @@ class IBusEmojier : Gtk.ApplicationWindow { - focus_visible : true - ); - -- add_action_entries(m_action_entries, this); -+ // GLib.ActionEntry accepts const variables only. -+ var action = new GLib.SimpleAction.stateful( -+ "variant", -+ null, -+ new GLib.Variant.boolean(m_show_emoji_variant)); -+ action.activate.connect(check_action_variant_cb); -+ add_action(action); - if (m_current_lang_id == null) - m_current_lang_id = "en"; - if (m_emoji_font_family == null) -@@ -521,18 +524,7 @@ class IBusEmojier : Gtk.ApplicationWindow { - m_emoji_to_data_dict.replace(emoji, data); - } else { - unowned IBus.EmojiData? en_data = null; -- // If emoji presentation (+= 0xfe0f) is already saved in dict, -- // update it instead of no presentation. -- // emoji-test.txt has all emoji presentations but $lang.xml has -- // some no emoji presentations. -- if (emoji.chr(-1, 0xfe0f) == null) { -- var buff = new GLib.StringBuilder(); -- buff.append(emoji); -- buff.append_unichar(0xfe0f); -- en_data = m_emoji_to_data_dict.lookup(buff.str); -- } -- if (en_data == null) -- en_data = m_emoji_to_data_dict.lookup(emoji); -+ en_data = m_emoji_to_data_dict.lookup(emoji); - if (en_data == null) { - m_emoji_to_data_dict.insert(emoji, data); - return; -@@ -923,7 +915,12 @@ class IBusEmojier : Gtk.ApplicationWindow { - m_vbox.add(button); - button.show_all(); - button.button_press_event.connect((w, e) => { -- hide_candidate_panel(); -+ // 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) -+ show_emoji_for_category(m_backward); -+ else -+ hide_candidate_panel(); - return true; - }); - } -@@ -1269,6 +1266,9 @@ class IBusEmojier : Gtk.ApplicationWindow { - 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(); - } - - --- -2.9.3 - -From bc0f91342c6f3a6e554493af9430d634d906ee19 Mon Sep 17 00:00:00 2001 -From: fujiwarat -Date: Tue, 25 Jul 2017 12:00:14 +0900 -Subject: [PATCH] ui/gtk3: Fix SEGV of IBusEmojier on de_DE.UTF-8 - -de's decimal_point is ',' instead of '.' and failed to load the -CSS data in Gtk.CssProvider.load_from_data(), launched null -window of emojis and finally caused a SEGV due to the null window. -This also fixes some memory leaks. - -BUG=rhbz#1471079 - -Review URL: https://codereview.appspot.com/323310043 ---- - src/ibusemoji.c | 1 + - ui/gtk3/emojier.vala | 33 ++++++++++++++++++++++++++------- - 2 files changed, 27 insertions(+), 7 deletions(-) - -diff --git a/src/ibusemoji.c b/src/ibusemoji.c -index 3d38c2a..d56c48a 100644 ---- a/src/ibusemoji.c -+++ b/src/ibusemoji.c -@@ -591,6 +591,7 @@ out_load_cache: - g_variant_unref (variant); - if (variant_table) - g_variant_unref (variant_table); -+ g_free (contents); - - return retval; - } -diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala -index 95912bf..9df59ac 100644 ---- a/ui/gtk3/emojier.vala -+++ b/ui/gtk3/emojier.vala -@@ -276,6 +276,17 @@ class IBusEmojier : Gtk.ApplicationWindow { - 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); -@@ -321,6 +332,10 @@ class IBusEmojier : Gtk.ApplicationWindow { - 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, -@@ -424,8 +439,9 @@ class IBusEmojier : Gtk.ApplicationWindow { - unowned GLib.SList annotations = data.get_annotations(); - foreach (string annotation in annotations) { - bool has_emoji = false; -- unowned GLib.SList hits = -- m_annotation_to_emojis_dict.lookup(annotation); -+ GLib.SList hits = -+ m_annotation_to_emojis_dict.lookup(annotation).copy_deep( -+ GLib.strdup); - foreach (string hit_emoji in hits) { - if (hit_emoji == emoji) { - has_emoji = true; -@@ -485,7 +501,8 @@ class IBusEmojier : Gtk.ApplicationWindow { - private static void - update_annotations_with_description (IBus.EmojiData data, - string description) { -- unowned GLib.SList annotations = data.get_annotations(); -+ GLib.SList annotations = -+ data.get_annotations().copy_deep(GLib.strdup); - bool update_annotations = false; - string former = null; - string later = null; -@@ -574,8 +591,9 @@ class IBusEmojier : Gtk.ApplicationWindow { - buff.append_unichar(0xfe0f); - if (m_emoji_to_data_dict.lookup(buff.str) != null) - base_emoji = buff.str; -- unowned GLib.SList? variants = -- m_emoji_to_emoji_variants_dict.lookup(base_emoji); -+ GLib.SList? variants = -+ m_emoji_to_emoji_variants_dict.lookup( -+ base_emoji).copy_deep(GLib.strdup); - if (variants.find_custom(emoji, GLib.strcmp) == null) { - if (variants == null) - variants.append(base_emoji); -@@ -587,8 +605,9 @@ class IBusEmojier : Gtk.ApplicationWindow { - return; - } - bool has_emoji = false; -- unowned GLib.SList hits = -- m_category_to_emojis_dict.lookup(category); -+ GLib.SList hits = -+ m_category_to_emojis_dict.lookup(category).copy_deep( -+ GLib.strdup); - foreach (string hit_emoji in hits) { - if (hit_emoji == emoji) { - has_emoji = true; --- -2.9.3 - -From 4134113a1ae30534367a9ca729c7f36a0a8e3662 Mon Sep 17 00:00:00 2001 -From: fujiwarat -Date: Thu, 27 Jul 2017 14:07:00 +0900 -Subject: [PATCH] ui/gtk3: Fix SEGV of XKeysymToKeycode() on Wayland - -BUG=rhbz#1368593 ---- - ui/gtk3/application.vala | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/ui/gtk3/application.vala b/ui/gtk3/application.vala -index 5ae6e83..fa80272 100644 ---- a/ui/gtk3/application.vala -+++ b/ui/gtk3/application.vala -@@ -3,6 +3,7 @@ - * ibus - The Input Bus - * - * Copyright(c) 2011 Peng Huang -+ * Copyright(c) 2017 Takao Fujiwara - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public -@@ -99,6 +100,9 @@ class Application { - } - - public static void main(string[] argv) { -+ // for Gdk.X11.get_default_xdisplay() -+ Gdk.set_allowed_backends("x11"); -+ - Application app = new Application(argv); - app.run(); - } --- -2.9.3 - -From 6a3301db85e77e0652f7e00894cce493b6a942f6 Mon Sep 17 00:00:00 2001 -From: Xiang Fan -Date: Thu, 10 Aug 2017 11:24:39 +0900 -Subject: [PATCH 01/14] client/gtk2: include the scaling factor - -Scaling factor, which exists for HiDPI displays, needs to be included in -the calculation of cursor location. This does not affect devices without -a HiDPI display. - -Candidate windows would be misplaced to smaller coordinates without this -patch. - -BUG=https://github.com/ibus/ibus/issues/1806 - -Review URL: https://codereview.appspot.com/328250043 - -Patch from Xiang Fan . ---- - client/gtk2/ibusimcontext.c | 21 +++++++++++++++++++++ - 1 file changed, 21 insertions(+) - -diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c -index 0df00620..41c7a3af 100644 ---- a/client/gtk2/ibusimcontext.c -+++ b/client/gtk2/ibusimcontext.c -@@ -999,6 +999,24 @@ ibus_im_context_set_client_window (GtkIMContext *context, GdkWindow *client) - gtk_im_context_set_client_window (ibusimcontext->slave, client); - } - -+static void -+_set_rect_scale_factor_with_window (GdkRectangle *area, -+ GdkWindow *window) -+{ -+#if GTK_CHECK_VERSION (3, 10, 0) -+ int scale_factor; -+ -+ g_assert (area); -+ g_assert (GDK_IS_WINDOW (window)); -+ -+ scale_factor = gdk_window_get_scale_factor (window); -+ area->x *= scale_factor; -+ area->y *= scale_factor; -+ area->width *= scale_factor; -+ area->height *= scale_factor; -+#endif -+} -+ - static gboolean - _set_cursor_location_internal (IBusIMContext *ibusimcontext) - { -@@ -1024,6 +1042,8 @@ _set_cursor_location_internal (IBusIMContext *ibusimcontext) - window = parent; - } - -+ _set_rect_scale_factor_with_window (&area, -+ ibusimcontext->client_window); - ibus_input_context_set_cursor_location_relative ( - ibusimcontext->ibuscontext, - area.x, -@@ -1049,6 +1069,7 @@ _set_cursor_location_internal (IBusIMContext *ibusimcontext) - gdk_window_get_root_coords (ibusimcontext->client_window, - area.x, area.y, - &area.x, &area.y); -+ _set_rect_scale_factor_with_window (&area, ibusimcontext->client_window); - ibus_input_context_set_cursor_location (ibusimcontext->ibuscontext, - area.x, - area.y, --- -2.13.4 - -From c1b93f933f5cbd74f3e06575d26ed7432a5420fd Mon Sep 17 00:00:00 2001 -From: Mario Bodemann -Date: Tue, 15 Aug 2017 12:10:56 +0900 -Subject: [PATCH 02/14] Typo fix - -BUG=https://github.com/ibus/ibus/pull/1939 - -Review URL: https://codereview.appspot.com/327080043 - -Patch from Mario Bodemann . ---- - ui/gtk3/ibus-emoji.7.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ui/gtk3/ibus-emoji.7.in b/ui/gtk3/ibus-emoji.7.in -index 4ee86364..d5eae310 100644 ---- a/ui/gtk3/ibus-emoji.7.in -+++ b/ui/gtk3/ibus-emoji.7.in -@@ -15,7 +15,7 @@ - .SH "DESCRIPTION" - - .PP --IBus Emojier provides a GUI to select an emoji by typing an emoji annotaion -+IBus Emojier provides a GUI to select an emoji by typing an emoji annotation - or choosing a character with mouse click and it's designed to work as - an extended IBus lookup window using Space, Enter, and Arrow keys. - The text entry accepts an emoji annotation or Unicode points. --- -2.13.4 - -From 203a3df5a239d644cf42b7bac03a268eb5babfc7 Mon Sep 17 00:00:00 2001 -From: Alexander Larsson -Date: Wed, 30 Aug 2017 11:38:09 +0900 -Subject: [PATCH 03/14] Initial version of ibus portal - -This adds a dbus service called org.freedesktop.portal.IBus on the -session bus. It is a very limited service that only implements -CreateInputContext and the InputContext interface (and Service.Destroy -for lifetime access). - -It uses gdbus code generation for demarshalling the method calls which -means it will verify that all arguments have the right type. - -Additionally all method calls to the input context object have to be -from the client that created it, so each client is isolated. - -BUG=https://github.com/flatpak/flatpak/issues/675 -R=Shawn.P.Huang@gmail.com - -Review URL: https://codereview.appspot.com/326350043 - -Patch from Alexander Larsson . ---- - Makefile.am | 1 + - configure.ac | 5 +- - portal/Makefile.am | 95 ++++ - portal/org.freedesktop.IBus.Portal.xml | 132 +++++ - portal/org.freedesktop.portal.IBus.service.in | 3 + - portal/portal.c | 698 ++++++++++++++++++++++++++ - src/ibusshare.h | 14 + - 7 files changed, 947 insertions(+), 1 deletion(-) - create mode 100644 portal/Makefile.am - create mode 100644 portal/org.freedesktop.IBus.Portal.xml - create mode 100644 portal/org.freedesktop.portal.IBus.service.in - create mode 100644 portal/portal.c - -diff --git a/Makefile.am b/Makefile.am -index f703d4c6..c8e802da 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -51,6 +51,7 @@ SUBDIRS = \ - util \ - conf \ - client \ -+ portal \ - data \ - m4 \ - po \ -diff --git a/configure.ac b/configure.ac -index cb48ad4c..14556a3a 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -153,7 +153,7 @@ PKG_CHECK_MODULES(GOBJECT2, [ - gobject-2.0 >= glib_required_version - ]) - PKG_CHECK_MODULES(GIO2, [ -- gio-2.0 >= glib_required_version -+ gio-2.0 gio-unix-2.0 >= glib_required_version - ]) - PKG_CHECK_MODULES(GTHREAD2, [ - gthread-2.0 >= glib_required_version -@@ -660,6 +660,8 @@ PKG_CHECK_MODULES(ISOCODES, [ - ISOCODES_PREFIX=`$PKG_CONFIG iso-codes --variable=prefix` - AC_SUBST(ISOCODES_PREFIX) - -+AC_SUBST([GDBUS_CODEGEN], [`$PKG_CONFIG --variable gdbus_codegen gio-2.0`]) -+ - # OUTPUT files - AC_CONFIG_FILES([ po/Makefile.in - Makefile -@@ -674,6 +676,7 @@ src/Makefile - src/ibusversion.h - src/tests/Makefile - bus/Makefile -+portal/Makefile - engine/Makefile - util/Makefile - util/IMdkit/Makefile -diff --git a/portal/Makefile.am b/portal/Makefile.am -new file mode 100644 -index 00000000..954fc591 ---- /dev/null -+++ b/portal/Makefile.am -@@ -0,0 +1,95 @@ -+# vim:set noet ts=4: -+# -+# ibus - The Input Bus -+# -+# Copyright (c) 2007-2013 Peng Huang -+# Copyright (c) 2007-2013 Red Hat, Inc. -+# -+# This library is free software; you can redistribute it and/or -+# modify it under the terms of the GNU Lesser General Public -+# License as published by the Free Software Foundation; either -+# version 2.1 of the License, or (at your option) any later version. -+# -+# This library is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+# Lesser General Public License for more details. -+# -+# You should have received a copy of the GNU Lesser General Public -+# License along with this library; if not, write to the Free Software -+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -+# USA -+ -+NULL = -+ -+libibus = $(top_builddir)/src/libibus-@IBUS_API_VERSION@.la -+ -+AM_CPPFLAGS = \ -+ -I$(top_srcdir)/src \ -+ -I$(top_builddir)/src \ -+ $(NULL) -+ -+AM_CFLAGS = \ -+ @GLIB2_CFLAGS@ \ -+ @GIO2_CFLAGS@ \ -+ @GTHREAD2_CFLAGS@ \ -+ -DG_LOG_DOMAIN=\"IBUS\" \ -+ -DPKGDATADIR=\"$(pkgdatadir)\" \ -+ -DLIBEXECDIR=\"$(libexecdir)\" \ -+ -DBINDIR=\"@bindir@\" \ -+ -DIBUS_DISABLE_DEPRECATED \ -+ $(NULL) -+AM_LDADD = \ -+ @GOBJECT2_LIBS@ \ -+ @GLIB2_LIBS@ \ -+ @GIO2_LIBS@ \ -+ @GTHREAD2_LIBS@ \ -+ $(libibus) \ -+ $(NULL) -+ -+ibus_dbus_built_sources = ibus-portal-dbus.c ibus-portal-dbus.h -+BUILT_SOURCES = $(ibus_dbus_built_sources) -+ -+libexec_PROGRAMS = ibus-portal -+ibus_portal_DEPENDENCIES = \ -+ $(libibus) \ -+ $(NULL) -+ibus_portal_SOURCES = \ -+ portal.c \ -+ $(ibus_dbus_built_sources) \ -+ $(NULL) -+ibus_portal_CFLAGS = \ -+ $(AM_CFLAGS) \ -+ $(NULL) -+ibus_portal_LDADD = \ -+ $(AM_LDADD) \ -+ $(NULL) -+ -+EXTRA_DIST = \ -+ $(NULL) -+ -+CLEANFILES = \ -+ $(NULL) -+ -+$(libibus): -+ $(MAKE) -C $(top_builddir)/src -+ -+dbusservice_in_files = org.freedesktop.portal.IBus.service.in -+dbusservice_DATA = $(dbusservice_in_files:.service.in=.service) -+dbusservicedir=${datadir}/dbus-1/services -+ -+org.freedesktop.portal.IBus.service: org.freedesktop.portal.IBus.service.in -+ $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@.tmp && mv $@.tmp $@ -+ -+$(ibus_dbus_built_sources) : org.freedesktop.IBus.Portal.xml -+ $(AM_V_GEN) $(GDBUS_CODEGEN) \ -+ --interface-prefix org.freedesktop.IBus. \ -+ --c-namespace IBusDbus \ -+ --generate-c-code $(builddir)/ibus-portal-dbus \ -+ $^ \ -+ $(NULL) -+ -+EXTRA_DIST += $(dbusservice_in_files) -+CLEANFILES += $(dbusservice_DATA) -+ -+-include $(top_srcdir)/git.mk -diff --git a/portal/org.freedesktop.IBus.Portal.xml b/portal/org.freedesktop.IBus.Portal.xml -new file mode 100644 -index 00000000..afce4daa ---- /dev/null -+++ b/portal/org.freedesktop.IBus.Portal.xml -@@ -0,0 +1,132 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/portal/org.freedesktop.portal.IBus.service.in b/portal/org.freedesktop.portal.IBus.service.in -new file mode 100644 -index 00000000..47ae9ffc ---- /dev/null -+++ b/portal/org.freedesktop.portal.IBus.service.in -@@ -0,0 +1,3 @@ -+[D-BUS Service] -+Name=org.freedesktop.portal.IBus -+Exec=@libexecdir@/ibus-portal -diff --git a/portal/portal.c b/portal/portal.c -new file mode 100644 -index 00000000..0415f996 ---- /dev/null -+++ b/portal/portal.c -@@ -0,0 +1,698 @@ -+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ -+/* vim:set et sts=4: */ -+/* ibus - The Input Bus -+ * Copyright (C) 2017 Red Hat, Inc. -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -+ * USA -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "ibus-portal-dbus.h" -+ -+typedef struct _IBusPortal IBusPortal; -+typedef struct _IBusPortalClass IBusPortalClass; -+typedef struct _IBusPortalContext IBusPortalContext; -+typedef struct _IBusPortalContextClass IBusPortalContextClass; -+ -+struct _IBusPortalContext -+{ -+ IBusDbusInputContextSkeleton parent_instance; -+ IBusInputContext *context; -+ guint id; -+ char *owner; -+ char *object_path; -+ IBusDbusService *service; -+}; -+ -+struct _IBusPortalContextClass -+{ -+ IBusDbusInputContextSkeletonClass parent_class; -+}; -+ -+struct _IBusPortal -+{ -+ IBusDbusPortalSkeleton parent_instance; -+ -+}; -+ -+struct _IBusPortalClass -+{ -+ IBusDbusPortalSkeletonClass parent_class; -+}; -+ -+enum -+{ -+ PROP_CONTENT_TYPE = 1, -+ N_PROPERTIES -+}; -+ -+static GMainLoop *loop = NULL; -+static IBusBus *ibus_bus; -+static IBusPortal *ibus_portal = NULL; -+static gboolean opt_verbose; -+static gboolean opt_replace; -+ -+static GList *all_contexts = NULL; -+ -+static guint next_context_id; -+ -+GType ibus_portal_context_get_type (void) G_GNUC_CONST; -+static void ibus_portal_context_iface_init (IBusDbusInputContextIface *iface); -+ -+static void portal_context_g_signal (GDBusProxy *proxy, -+ const gchar *sender_name, -+ const gchar *signal_name, -+ GVariant *parameters, -+ IBusPortalContext *portal_context); -+ -+G_DEFINE_TYPE_WITH_CODE (IBusPortalContext, -+ ibus_portal_context, -+ IBUS_DBUS_TYPE_INPUT_CONTEXT_SKELETON, -+ G_IMPLEMENT_INTERFACE (IBUS_DBUS_TYPE_INPUT_CONTEXT, -+ ibus_portal_context_iface_init)); -+ -+static void -+_forward_method_cb (GObject *source_object, -+ GAsyncResult *res, -+ gpointer user_data) -+{ -+ GDBusMethodInvocation *invocation = user_data; -+ IBusPortalContext *portal_context = -+ (IBusPortalContext *) g_dbus_method_invocation_get_user_data ( -+ invocation); -+ IBusEngineDesc *desc; -+ GError *error = NULL; -+ -+ GVariant *variant = g_dbus_proxy_call_finish ((GDBusProxy *) source_object, -+ res, &error); -+ if (variant == NULL) { -+ g_dbus_method_invocation_return_gerror (invocation, error); -+ g_error_free (error); -+ return; -+ } -+ -+ g_dbus_method_invocation_return_value (invocation, variant); -+} -+ -+static gboolean -+_forward_method (IBusDbusInputContext *object, -+ GDBusMethodInvocation *invocation) -+{ -+ IBusPortalContext *portal_context = (IBusPortalContext *)object; -+ GDBusMessage *message = g_dbus_method_invocation_get_message (invocation); -+ -+ g_dbus_proxy_call (G_DBUS_PROXY (portal_context->context), -+ g_dbus_method_invocation_get_method_name (invocation), -+ g_dbus_message_get_body (message), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, -+ NULL, /* cancellable */ -+ _forward_method_cb, invocation); -+ return TRUE; -+} -+ -+static gboolean -+ibus_dbus_context_cancel_hand_writing (IBusDbusInputContext *object, -+ GDBusMethodInvocation *invocation, -+ guint arg_n_strokes) -+{ -+ return _forward_method (object, invocation); -+} -+ -+static gboolean -+ibus_dbus_context_focus_in (IBusDbusInputContext *object, -+ GDBusMethodInvocation *invocation) -+{ -+ return _forward_method (object, invocation); -+} -+ -+static gboolean -+ibus_dbus_context_focus_out (IBusDbusInputContext *object, -+ GDBusMethodInvocation *invocation) -+{ -+ return _forward_method (object, invocation); -+} -+ -+static gboolean -+ibus_dbus_context_get_engine (IBusDbusInputContext *object, -+ GDBusMethodInvocation *invocation) -+{ -+ return _forward_method (object, invocation); -+} -+ -+static gboolean -+ibus_dbus_context_process_hand_writing_event (IBusDbusInputContext *object, -+ GDBusMethodInvocation *invocation, -+ GVariant -+ *arg_coordinates) -+{ -+ return _forward_method (object, invocation); -+} -+ -+static gboolean -+ibus_dbus_context_process_key_event (IBusDbusInputContext *object, -+ GDBusMethodInvocation *invocation, -+ guint arg_keyval, -+ guint arg_keycode, -+ guint arg_state) -+{ -+ return _forward_method (object, invocation); -+} -+ -+static gboolean -+ibus_dbus_context_property_activate (IBusDbusInputContext *object, -+ GDBusMethodInvocation *invocation, -+ const gchar *arg_name, -+ guint arg_state) -+{ -+ return _forward_method (object, invocation); -+} -+ -+static gboolean -+ibus_dbus_context_reset (IBusDbusInputContext *object, -+ GDBusMethodInvocation *invocation) -+{ -+ return _forward_method (object, invocation); -+} -+ -+static gboolean -+ibus_dbus_context_set_capabilities (IBusDbusInputContext *object, -+ GDBusMethodInvocation *invocation, -+ guint arg_caps) -+{ -+ return _forward_method (object, invocation); -+} -+ -+static gboolean -+ibus_dbus_context_set_cursor_location (IBusDbusInputContext *object, -+ GDBusMethodInvocation *invocation, -+ gint arg_x, -+ gint arg_y, -+ gint arg_w, -+ gint arg_h) -+{ -+ return _forward_method (object, invocation); -+} -+ -+static gboolean -+ibus_dbus_context_set_cursor_location_relative (IBusDbusInputContext *object, -+ GDBusMethodInvocation -+ *invocation, -+ gint arg_x, -+ gint arg_y, -+ gint arg_w, -+ gint arg_h) -+{ -+ return _forward_method (object, invocation); -+} -+ -+static gboolean -+ibus_dbus_context_set_engine (IBusDbusInputContext *object, -+ GDBusMethodInvocation *invocation, -+ const gchar *arg_name) -+{ -+ return _forward_method (object, invocation); -+} -+ -+static gboolean -+ibus_dbus_context_set_surrounding_text (IBusDbusInputContext *object, -+ GDBusMethodInvocation *invocation, -+ GVariant *arg_text, -+ guint arg_cursor_pos, -+ guint arg_anchor_pos) -+{ -+ return _forward_method (object, invocation); -+} -+ -+static void -+ibus_portal_context_iface_init (IBusDbusInputContextIface *iface) -+{ -+ iface->handle_cancel_hand_writing = ibus_dbus_context_cancel_hand_writing; -+ iface->handle_focus_in = ibus_dbus_context_focus_in; -+ iface->handle_focus_out = ibus_dbus_context_focus_out; -+ iface->handle_get_engine = ibus_dbus_context_get_engine; -+ iface->handle_process_hand_writing_event = -+ ibus_dbus_context_process_hand_writing_event; -+ iface->handle_process_key_event = ibus_dbus_context_process_key_event; -+ iface->handle_property_activate = ibus_dbus_context_property_activate; -+ iface->handle_reset = ibus_dbus_context_reset; -+ iface->handle_set_capabilities = ibus_dbus_context_set_capabilities; -+ iface->handle_set_cursor_location = ibus_dbus_context_set_cursor_location; -+ iface->handle_set_cursor_location_relative = -+ ibus_dbus_context_set_cursor_location_relative; -+ iface->handle_set_engine = ibus_dbus_context_set_engine; -+ iface->handle_set_surrounding_text = ibus_dbus_context_set_surrounding_text; -+} -+ -+static void -+ibus_portal_context_init (IBusPortalContext *portal_context) -+{ -+} -+ -+static void -+ibus_portal_context_finalize (GObject *object) -+{ -+ IBusPortalContext *portal_context = (IBusPortalContext *)object; -+ -+ all_contexts = g_list_remove (all_contexts, portal_context); -+ -+ g_dbus_interface_skeleton_unexport ( -+ G_DBUS_INTERFACE_SKELETON (portal_context->service)); -+ g_dbus_interface_skeleton_unexport ( -+ G_DBUS_INTERFACE_SKELETON (portal_context)); -+ -+ g_free (portal_context->owner); -+ g_free (portal_context->object_path); -+ g_object_unref (portal_context->service); -+ -+ g_signal_handlers_disconnect_by_func ( -+ portal_context->context, -+ G_CALLBACK(portal_context_g_signal), -+ portal_context); -+ g_object_unref (portal_context->context); -+ -+ G_OBJECT_CLASS (ibus_portal_context_parent_class)->finalize (object); -+} -+ -+static void -+ibus_portal_context_set_property (IBusPortalContext *portal_context, -+ guint prop_id, -+ const GValue *value, -+ GParamSpec *pspec) -+{ -+ switch (prop_id) { -+ case PROP_CONTENT_TYPE: -+ g_dbus_proxy_call (G_DBUS_PROXY (portal_context->context), -+ "org.freedesktop.DBus.Properties.Set", -+ g_variant_new ("(ssv)", -+ IBUS_INTERFACE_INPUT_CONTEXT, -+ "ContentType", -+ g_value_get_variant (value)), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, -+ NULL, /* cancellable */ -+ NULL, /* callback */ -+ NULL /* user_data */ -+ ); -+ break; -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (portal_context, prop_id, pspec); -+ } -+} -+ -+static void -+ibus_portal_context_get_property (IBusPortalContext *portal_context, -+ guint prop_id, -+ GValue *value, -+ GParamSpec *pspec) -+{ -+ switch (prop_id) { -+ case PROP_CONTENT_TYPE: -+ g_warning ("No support for setting content type"); -+ break; -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (portal_context, prop_id, pspec); -+ } -+} -+ -+static gboolean -+ibus_portal_context_g_authorize_method (GDBusInterfaceSkeleton *interface, -+ GDBusMethodInvocation *invocation) -+{ -+ IBusPortalContext *portal_context = (IBusPortalContext *)interface; -+ -+ if (g_strcmp0 (g_dbus_method_invocation_get_sender (invocation), -+ portal_context->owner) == 0) { -+ return TRUE; -+ } -+ -+ g_dbus_method_invocation_return_error (invocation, -+ G_DBUS_ERROR, -+ G_DBUS_ERROR_FAILED, -+ "Access denied"); -+ return FALSE; -+} -+ -+ -+static void -+ibus_portal_context_class_init (IBusPortalContextClass *klass) -+{ -+ GObjectClass *gobject_class; -+ GDBusInterfaceSkeletonClass *skeleton_class; -+ -+ gobject_class = G_OBJECT_CLASS (klass); -+ gobject_class->finalize = ibus_portal_context_finalize; -+ gobject_class->set_property = -+ (GObjectSetPropertyFunc) ibus_portal_context_set_property; -+ gobject_class->get_property = -+ (GObjectGetPropertyFunc) ibus_portal_context_get_property; -+ -+ skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS(klass); -+ skeleton_class->g_authorize_method = ibus_portal_context_g_authorize_method; -+ -+ ibus_dbus_input_context_override_properties (gobject_class, -+ PROP_CONTENT_TYPE); -+} -+ -+static void -+portal_context_g_signal (GDBusProxy *proxy, -+ const gchar *sender_name, -+ const gchar *signal_name, -+ GVariant *parameters, -+ IBusPortalContext *portal_context) -+{ -+ GError *error = NULL; -+ GDBusConnection *connection; -+ -+ if (g_strcmp0 (sender_name, IBUS_SERVICE_IBUS) != 0) -+ return; -+ -+ connection = g_dbus_interface_skeleton_get_connection ( -+ G_DBUS_INTERFACE_SKELETON (portal_context)); -+ if (!g_dbus_connection_emit_signal (connection, -+ portal_context->owner, -+ portal_context->object_path, -+ IBUS_INTERFACE_INPUT_CONTEXT, -+ signal_name, -+ parameters, -+ &error)) { -+ g_warning ("Unable to emit signal %s: %s", signal_name, error->message); -+ g_error_free (error); -+ } -+ -+ g_signal_stop_emission_by_name (proxy, "g-signal"); -+} -+ -+static gboolean -+ibus_portal_context_handle_destroy (IBusDbusService *object, -+ GDBusMethodInvocation *invocation, -+ IBusPortalContext *portal_context) -+{ -+ g_object_unref (portal_context); -+} -+ -+static IBusPortalContext * -+ibus_portal_context_new (IBusInputContext *context, -+ GDBusConnection *connection, -+ const char *owner, -+ GError **error) -+{ -+ IBusPortalContext *portal_context = -+ g_object_new (ibus_portal_context_get_type (), NULL); -+ -+ g_signal_connect (context, -+ "g-signal", -+ G_CALLBACK(portal_context_g_signal), -+ portal_context); -+ -+ portal_context->id = ++next_context_id; -+ portal_context->context = g_object_ref (context); -+ portal_context->owner = g_strdup (owner); -+ portal_context->object_path = -+ g_strdup_printf (IBUS_PATH_INPUT_CONTEXT, portal_context->id); -+ portal_context->service = ibus_dbus_service_skeleton_new (); -+ -+ g_signal_connect (portal_context->service, -+ "handle-destroy", -+ G_CALLBACK (ibus_portal_context_handle_destroy), -+ portal_context); -+ -+ if (!g_dbus_interface_skeleton_export ( -+ G_DBUS_INTERFACE_SKELETON (portal_context->service), -+ connection, portal_context->object_path, -+ error) || -+ !g_dbus_interface_skeleton_export ( -+ G_DBUS_INTERFACE_SKELETON (portal_context), -+ connection, portal_context->object_path, -+ error)) { -+ g_object_unref (portal_context); -+ return NULL; -+ } -+ -+ all_contexts = g_list_prepend (all_contexts, portal_context); -+ -+ return portal_context; -+} -+ -+GType ibus_portal_get_type (void) G_GNUC_CONST; -+static void ibus_portal_iface_init (IBusDbusPortalIface *iface); -+ -+G_DEFINE_TYPE_WITH_CODE (IBusPortal, ibus_portal, -+ IBUS_DBUS_TYPE_PORTAL_SKELETON, -+ G_IMPLEMENT_INTERFACE (IBUS_DBUS_TYPE_PORTAL, -+ ibus_portal_iface_init)); -+ -+ -+static void -+create_input_context_done (IBusBus *bus, -+ GAsyncResult *res, -+ GDBusMethodInvocation *invocation) -+{ -+ GError *error = NULL; -+ IBusInputContext *context; -+ IBusPortalContext *portal_context; -+ char *object_path; -+ -+ context = ibus_bus_create_input_context_async_finish (ibus_bus, -+ res, -+ &error); -+ if (context == NULL) { -+ g_dbus_method_invocation_return_gerror (invocation, error); -+ g_error_free (error); -+ return; -+ } -+ -+ portal_context = ibus_portal_context_new ( -+ context, -+ g_dbus_method_invocation_get_connection (invocation), -+ g_dbus_method_invocation_get_sender (invocation), -+ &error); -+ g_object_unref (context); -+ -+ if (portal_context == NULL) { -+ g_dbus_method_invocation_return_gerror (invocation, error); -+ g_error_free (error); -+ g_object_unref (portal_context); -+ return; -+ } -+ -+ ibus_dbus_portal_complete_create_input_context ( -+ IBUS_DBUS_PORTAL(ibus_portal), -+ invocation, portal_context->object_path); -+} -+ -+static gboolean -+ibus_portal_handle_create_input_context (IBusDbusPortal *object, -+ GDBusMethodInvocation *invocation, -+ const gchar *arg_client_name) -+{ -+ ibus_bus_create_input_context_async ( -+ ibus_bus, -+ arg_client_name, -1, -+ NULL, -+ (GAsyncReadyCallback)create_input_context_done, -+ invocation); -+ return TRUE; -+} -+ -+static void -+ibus_portal_iface_init (IBusDbusPortalIface *iface) -+{ -+ iface->handle_create_input_context = -+ ibus_portal_handle_create_input_context; -+} -+ -+static void -+ibus_portal_init (IBusPortal *portal) -+{ -+} -+ -+static void -+ibus_portal_class_init (IBusPortalClass *klass) -+{ -+} -+ -+ -+static void -+show_version_and_quit (void) -+{ -+ g_print ("%s - Version %s\n", g_get_application_name (), VERSION); -+ exit (EXIT_SUCCESS); -+} -+ -+static const GOptionEntry entries[] = -+{ -+ { "version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, -+ show_version_and_quit, "Show the application's version.", NULL }, -+ { "verbose", 'v', 0, G_OPTION_ARG_NONE, -+ &opt_verbose, "verbose.", NULL }, -+ { "replace", 'r', 0, G_OPTION_ARG_NONE, -+ &opt_replace, "Replace.", NULL }, -+ { NULL }, -+}; -+ -+static void -+on_bus_acquired (GDBusConnection *connection, -+ const gchar *name, -+ gpointer user_data) -+{ -+ GError *error = NULL; -+ -+ ibus_portal = g_object_new (ibus_portal_get_type (), NULL); -+ -+ if (!g_dbus_interface_skeleton_export ( -+ G_DBUS_INTERFACE_SKELETON (ibus_portal), -+ connection, -+ IBUS_PATH_IBUS, -+ &error)) { -+ g_warning ("Error exporting portal: %s", error->message); -+ g_error_free (error); -+ return; -+ } -+} -+ -+static void -+on_name_acquired (GDBusConnection *connection, -+ const gchar *name, -+ gpointer user_data) -+{ -+} -+ -+static void -+on_name_lost (GDBusConnection *connection, -+ const gchar *name, -+ gpointer user_data) -+{ -+ g_main_loop_quit (loop); -+} -+ -+static void -+name_owner_changed (GDBusConnection *connection, -+ const gchar *sender_name, -+ const gchar *object_path, -+ const gchar *interface_name, -+ const gchar *signal_name, -+ GVariant *parameters, -+ gpointer user_data) -+{ -+ const char *name, *from, *to; -+ -+ g_variant_get (parameters, "(sss)", &name, &from, &to); -+ -+ if (name[0] == ':' && -+ g_strcmp0 (name, from) == 0 && -+ g_strcmp0 (to, "") == 0) -+ { -+ GList *l, *next; -+ /* Client disconnected, free any input contexts it may have */ -+ for (l = all_contexts; l != NULL; l = next) { -+ IBusPortalContext *portal_context = l->data; -+ next = l->next; -+ -+ if (g_strcmp0 (portal_context->owner, name) == 0) { -+ g_object_unref (portal_context); -+ } -+ } -+ } -+} -+ -+static void -+_bus_disconnected_cb (IBusBus *ibusbus) -+{ -+ g_main_loop_quit (loop); -+} -+ -+gint -+main (gint argc, gchar **argv) -+{ -+ GDBusConnection *session_bus = NULL; -+ guint owner_id; -+ -+ setlocale (LC_ALL, ""); -+ -+ GOptionContext *context = g_option_context_new ("- ibus daemon"); -+ g_option_context_add_main_entries (context, entries, "ibus-daemon"); -+ -+ GError *error = NULL; -+ if (!g_option_context_parse (context, &argc, &argv, &error)) { -+ g_printerr ("Option parsing failed: %s\n", error->message); -+ g_error_free (error); -+ exit (-1); -+ } -+ -+ /* Avoid even loading gvfs to avoid accidental confusion */ -+ g_setenv ("GIO_USE_VFS", "local", TRUE); -+ -+ ibus_init (); -+ -+ ibus_set_log_handler (opt_verbose); -+ -+ ibus_bus = ibus_bus_new (); -+ if (!ibus_bus_is_connected (ibus_bus)) { -+ g_printerr ("Not connected to the ibus bus\n"); -+ exit (1); -+ } -+ -+ g_signal_connect (ibus_bus, "disconnected", -+ G_CALLBACK (_bus_disconnected_cb), NULL); -+ -+ loop = g_main_loop_new (NULL, FALSE); -+ -+ session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); -+ if (session_bus == NULL) { -+ g_printerr ("No session bus: %s", error->message); -+ exit (-1); -+ } -+ -+ g_dbus_connection_signal_subscribe (session_bus, -+ "org.freedesktop.DBus", -+ "org.freedesktop.DBus", -+ "NameOwnerChanged", -+ "/org/freedesktop/DBus", -+ NULL, -+ G_DBUS_SIGNAL_FLAGS_NONE, -+ name_owner_changed, -+ NULL, NULL); -+ -+ owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, -+ IBUS_SERVICE_PORTAL, -+ G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | -+ (opt_replace ? G_BUS_NAME_OWNER_FLAGS_REPLACE -+ : 0), -+ on_bus_acquired, -+ on_name_acquired, -+ on_name_lost, -+ NULL, -+ NULL); -+ -+ g_main_loop_run (loop); -+ -+ g_bus_unown_name (owner_id); -+ g_main_loop_unref (loop); -+ -+ return 0; -+} -diff --git a/src/ibusshare.h b/src/ibusshare.h -index bca477c0..f3e2011e 100644 ---- a/src/ibusshare.h -+++ b/src/ibusshare.h -@@ -52,6 +52,13 @@ - #define IBUS_SERVICE_IBUS "org.freedesktop.IBus" - - /** -+ * IBUS_SERVICE_PORTAL: -+ * -+ * Address of IBus portalservice. -+ */ -+#define IBUS_SERVICE_PORTAL "org.freedesktop.portal.IBus" -+ -+/** - * IBUS_SERVICE_PANEL: - * - * Address of IBus panel service. -@@ -122,6 +129,13 @@ - #define IBUS_INTERFACE_IBUS "org.freedesktop.IBus" - - /** -+ * IBUS_INTERFACE_PORTAL: -+ * -+ * D-Bus interface for IBus portal. -+ */ -+#define IBUS_INTERFACE_PORTAL "org.freedesktop.IBus.Portal" -+ -+/** - * IBUS_INTERFACE_INPUT_CONTEXT: - * - * D-Bus interface for IBus input context. --- -2.13.4 - -From 35ce62474fa97a5460d72c360943700a413a07ae Mon Sep 17 00:00:00 2001 -From: Alexander Larsson -Date: Thu, 31 Aug 2017 12:03:37 +0900 -Subject: [PATCH 04/14] Support the portal in the gtk im modules - -This adds a new way to create an IbusBus, ibus_bus_new_async_client(). -This returns an object that is not guarantee to handle any calls -that are not needed by a client, meaning CreateInputContext and -handling the input context. - -If you are running in a flatpak, or if IBUS_USE_PORTAL is set, then -instead of talking to the regular ibus bus we connect to -org.freedesktop.portal.IBus on the session bus and use the -limited org.freedesktop.IBus.Portal interface instead of the -org.freedesktop.IBus interface. - -This allows flatpaks (or other sandbox systems) to safely use -dbus clients (apps). - -BUG=https://github.com/flatpak/flatpak/issues/675 - -Review URL: https://codereview.appspot.com/328410043 - -Patch from Alexander Larsson . ---- - client/gtk2/ibusimcontext.c | 4 +- - src/ibusbus.c | 248 +++++++++++++++++++++++++++++++++++++++----- - src/ibusbus.h | 23 ++++ - src/ibusinputcontext.c | 12 ++- - 4 files changed, 256 insertions(+), 31 deletions(-) - -diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c -index 41c7a3af..b4ca8828 100644 ---- a/client/gtk2/ibusimcontext.c -+++ b/client/gtk2/ibusimcontext.c -@@ -583,7 +583,7 @@ ibus_im_context_class_init (IBusIMContextClass *class) - - /* init bus object */ - if (_bus == NULL) { -- _bus = ibus_bus_new_async (); -+ _bus = ibus_bus_new_async_client (); - - /* init the global fake context */ - if (ibus_bus_is_connected (_bus)) { -@@ -603,7 +603,7 @@ ibus_im_context_class_init (IBusIMContextClass *class) - } - - _daemon_name_watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION, -- IBUS_SERVICE_IBUS, -+ ibus_bus_get_service_name (_bus), - G_BUS_NAME_WATCHER_FLAGS_NONE, - daemon_name_appeared, - daemon_name_vanished, -diff --git a/src/ibusbus.c b/src/ibusbus.c -index 75406a37..fc0c9033 100644 ---- a/src/ibusbus.c -+++ b/src/ibusbus.c -@@ -48,12 +48,14 @@ enum { - enum { - PROP_0 = 0, - PROP_CONNECT_ASYNC, -+ PROP_CLIENT_ONLY, - }; - - /* IBusBusPriv */ - struct _IBusBusPrivate { - GFileMonitor *monitor; - GDBusConnection *connection; -+ gboolean connected; - gboolean watch_dbus_signal; - guint watch_dbus_signal_id; - gboolean watch_ibus_signal; -@@ -62,7 +64,10 @@ struct _IBusBusPrivate { - gchar *unique_name; - gboolean connect_async; - gchar *bus_address; -+ gboolean use_portal; -+ gboolean client_only; - GCancellable *cancellable; -+ guint portal_name_watch_id; - }; - - static guint bus_signals[LAST_SIGNAL] = { 0 }; -@@ -74,6 +79,7 @@ static GObject *ibus_bus_constructor (GType type, - guint n_params, - GObjectConstructParam *params); - static void ibus_bus_destroy (IBusObject *object); -+static void ibus_bus_connect_async (IBusBus *bus); - static void ibus_bus_watch_dbus_signal (IBusBus *bus); - static void ibus_bus_unwatch_dbus_signal (IBusBus *bus); - static void ibus_bus_watch_ibus_signal (IBusBus *bus); -@@ -117,8 +123,10 @@ ibus_bus_class_init (IBusBusClass *class) - IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (class); - - gobject_class->constructor = ibus_bus_constructor; -- gobject_class->set_property = (GObjectSetPropertyFunc) ibus_bus_set_property; -- gobject_class->get_property = (GObjectGetPropertyFunc) ibus_bus_get_property; -+ gobject_class->set_property = -+ (GObjectSetPropertyFunc) ibus_bus_set_property; -+ gobject_class->get_property = -+ (GObjectGetPropertyFunc) ibus_bus_get_property; - ibus_object_class->destroy = ibus_bus_destroy; - - /* install properties */ -@@ -128,13 +136,28 @@ ibus_bus_class_init (IBusBusClass *class) - * Whether the #IBusBus object should connect asynchronously to the bus. - * - */ -- g_object_class_install_property (gobject_class, -- PROP_CONNECT_ASYNC, -- g_param_spec_boolean ("connect-async", -- "Connect Async", -- "Connect asynchronously to the bus", -- FALSE, -- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); -+ g_object_class_install_property ( -+ gobject_class, -+ PROP_CONNECT_ASYNC, -+ g_param_spec_boolean ("connect-async", -+ "Connect Async", -+ "Connect asynchronously to the bus", -+ FALSE, -+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); -+ /** -+ * IBusBus:client-only: -+ * -+ * Whether the #IBusBus object is for client use only. -+ * -+ */ -+ g_object_class_install_property ( -+ gobject_class, -+ PROP_CLIENT_ONLY, -+ g_param_spec_boolean ("client-only", -+ "ClientOnly", -+ "Client use only", -+ FALSE, -+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - /* install signals */ - /** -@@ -294,6 +317,8 @@ ibus_bus_close_connection (IBusBus *bus) - g_cancellable_cancel (bus->priv->cancellable); - g_cancellable_reset (bus->priv->cancellable); - -+ bus->priv->connected = FALSE; -+ - /* unref the old connection at first */ - if (bus->priv->connection != NULL) { - g_signal_handlers_disconnect_by_func (bus->priv->connection, -@@ -311,6 +336,8 @@ static void - ibus_bus_connect_completed (IBusBus *bus) - { - g_assert (bus->priv->connection); -+ -+ bus->priv->connected = TRUE; - /* FIXME */ - ibus_bus_hello (bus); - -@@ -329,9 +356,38 @@ ibus_bus_connect_completed (IBusBus *bus) - } - - static void -+_bus_connect_start_portal_cb (GObject *source_object, -+ GAsyncResult *res, -+ gpointer user_data) -+{ -+ IBusBus *bus = IBUS_BUS (user_data); -+ GVariant *result; -+ GError *error = NULL; -+ -+ result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), -+ res, -+ &error); -+ if (result != NULL) { -+ ibus_bus_connect_completed (bus); -+ g_variant_unref (result); -+ } else { -+ g_error_free (error); -+ -+ g_dbus_connection_close (bus->priv->connection, NULL, NULL, NULL); -+ g_object_unref (bus->priv->connection); -+ bus->priv->connection = NULL; -+ -+ g_free (bus->priv->bus_address); -+ bus->priv->bus_address = NULL; -+ } -+ -+ g_object_unref (bus); -+} -+ -+static void - _bus_connect_async_cb (GObject *source_object, -- GAsyncResult *res, -- gpointer user_data) -+ GAsyncResult *res, -+ gpointer user_data) - { - g_return_if_fail (user_data != NULL); - g_return_if_fail (IBUS_IS_BUS (user_data)); -@@ -349,7 +405,26 @@ _bus_connect_async_cb (GObject *source_object, - } - - if (bus->priv->connection != NULL) { -- ibus_bus_connect_completed (bus); -+ if (bus->priv->use_portal) { -+ g_object_set_data (G_OBJECT (bus->priv->connection), -+ "ibus-portal-connection", -+ GINT_TO_POINTER (TRUE)); -+ g_dbus_connection_call ( -+ bus->priv->connection, -+ IBUS_SERVICE_PORTAL, -+ IBUS_PATH_IBUS, -+ "org.freedesktop.DBus.Peer", -+ "Ping", -+ g_variant_new ("()"), -+ G_VARIANT_TYPE ("()"), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, -+ bus->priv->cancellable, -+ (GAsyncReadyCallback) _bus_connect_start_portal_cb, -+ g_object_ref (bus)); -+ } else { -+ ibus_bus_connect_completed (bus); -+ } - } - else { - g_free (bus->priv->bus_address); -@@ -360,21 +435,32 @@ _bus_connect_async_cb (GObject *source_object, - g_object_unref (bus); - } - -+static gchar * -+ibus_bus_get_bus_address (IBusBus *bus) -+{ -+ if (_bus->priv->use_portal) -+ return g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SESSION, NULL, NULL); -+ else -+ return g_strdup (ibus_get_address ()); -+} -+ - static void - ibus_bus_connect_async (IBusBus *bus) - { -- const gchar *bus_address = ibus_get_address (); -+ gchar *bus_address = ibus_bus_get_bus_address (bus); - - if (bus_address == NULL) - return; - -- if (g_strcmp0 (bus->priv->bus_address, bus_address) == 0) -+ if (g_strcmp0 (bus->priv->bus_address, bus_address) == 0) { -+ g_free (bus_address); - return; -+ } - - /* Close current connection and cancel ongoing connect request. */ - ibus_bus_close_connection (bus); - -- bus->priv->bus_address = g_strdup (bus_address); -+ bus->priv->bus_address = bus_address; - g_object_ref (bus); - g_dbus_connection_new_for_address ( - bus_address, -@@ -385,6 +471,28 @@ ibus_bus_connect_async (IBusBus *bus) - _bus_connect_async_cb, bus); - } - -+static gboolean -+is_in_flatpak (void) -+{ -+ static gboolean flatpak_info_read; -+ static gboolean in_flatpak; -+ -+ if (flatpak_info_read) -+ return in_flatpak; -+ -+ flatpak_info_read = TRUE; -+ if (g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS)) -+ in_flatpak = TRUE; -+ return in_flatpak; -+} -+ -+static gboolean -+ibus_bus_should_connect_portal (IBusBus *bus) -+{ -+ return bus->priv->client_only && -+ (is_in_flatpak () || g_getenv ("IBUS_USE_PORTAL") != NULL); -+} -+ - static void - ibus_bus_connect (IBusBus *bus) - { -@@ -431,7 +539,6 @@ ibus_bus_init (IBusBus *bus) - { - struct stat buf; - gchar *path; -- GFile *file; - - bus->priv = IBUS_BUS_GET_PRIVATE (bus); - -@@ -443,6 +550,7 @@ ibus_bus_init (IBusBus *bus) - bus->priv->watch_ibus_signal_id = 0; - bus->priv->unique_name = NULL; - bus->priv->connect_async = FALSE; -+ bus->priv->client_only = FALSE; - bus->priv->bus_address = NULL; - bus->priv->cancellable = g_cancellable_new (); - -@@ -453,17 +561,12 @@ ibus_bus_init (IBusBus *bus) - - if (stat (path, &buf) == 0) { - if (buf.st_uid != getuid ()) { -- g_warning ("The owner of %s is not %s!", path, ibus_get_user_name ()); -+ g_warning ("The owner of %s is not %s!", -+ path, ibus_get_user_name ()); - return; - } - } - -- file = g_file_new_for_path (ibus_get_socket_path ()); -- bus->priv->monitor = g_file_monitor_file (file, 0, NULL, NULL); -- -- g_signal_connect (bus->priv->monitor, "changed", (GCallback) _changed_cb, bus); -- -- g_object_unref (file); - g_free (path); - } - -@@ -477,6 +580,9 @@ ibus_bus_set_property (IBusBus *bus, - case PROP_CONNECT_ASYNC: - bus->priv->connect_async = g_value_get_boolean (value); - break; -+ case PROP_CLIENT_ONLY: -+ bus->priv->client_only = g_value_get_boolean (value); -+ break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (bus, prop_id, pspec); - } -@@ -492,25 +598,73 @@ ibus_bus_get_property (IBusBus *bus, - case PROP_CONNECT_ASYNC: - g_value_set_boolean (value, bus->priv->connect_async); - break; -+ case PROP_CLIENT_ONLY: -+ g_value_set_boolean (value, bus->priv->client_only); -+ break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (bus, prop_id, pspec); - } - } - -+static void -+portal_name_appeared (GDBusConnection *connection, -+ const gchar *name, -+ const gchar *owner, -+ gpointer user_data) -+{ -+ IBusBus *bus = IBUS_BUS (user_data); -+ -+ if (bus->priv->connection == NULL) -+ ibus_bus_connect_async (bus); -+} -+ -+static void -+portal_name_vanished (GDBusConnection *connection, -+ const gchar *name, -+ gpointer user_data) -+{ -+ IBusBus *bus = IBUS_BUS (user_data); -+ -+ if (bus->priv->connection) -+ g_dbus_connection_close (bus->priv->connection, NULL, NULL, NULL); -+} -+ -+ - static GObject* - ibus_bus_constructor (GType type, - guint n_params, - GObjectConstructParam *params) - { - GObject *object; -+ GFile *file; - - /* share one IBusBus instance in whole application */ - if (_bus == NULL) { -- object = G_OBJECT_CLASS (ibus_bus_parent_class)->constructor (type, n_params, params); -+ object = G_OBJECT_CLASS (ibus_bus_parent_class)->constructor ( -+ type, n_params, params); - /* make bus object sink */ - g_object_ref_sink (object); - _bus = IBUS_BUS (object); - -+ _bus->priv->use_portal = ibus_bus_should_connect_portal (_bus); -+ -+ if (!_bus->priv->use_portal) { -+ file = g_file_new_for_path (ibus_get_socket_path ()); -+ _bus->priv->monitor = g_file_monitor_file (file, 0, NULL, NULL); -+ g_signal_connect (_bus->priv->monitor, "changed", -+ (GCallback) _changed_cb, _bus); -+ g_object_unref (file); -+ } else { -+ _bus->priv->portal_name_watch_id = -+ g_bus_watch_name (G_BUS_TYPE_SESSION, -+ IBUS_SERVICE_PORTAL, -+ G_BUS_NAME_WATCHER_FLAGS_NONE, -+ portal_name_appeared, -+ portal_name_vanished, -+ _bus, NULL); -+ } -+ -+ - if (_bus->priv->connect_async) - ibus_bus_connect_async (_bus); - else -@@ -561,6 +715,11 @@ ibus_bus_destroy (IBusObject *object) - g_object_unref (bus->priv->cancellable); - bus->priv->cancellable = NULL; - -+ if (bus->priv->portal_name_watch_id) { -+ g_bus_unwatch_name (bus->priv->portal_name_watch_id); -+ bus->priv->portal_name_watch_id = 0; -+ } -+ - IBUS_OBJECT_CLASS (ibus_bus_parent_class)->destroy (object); - } - -@@ -656,6 +815,7 @@ ibus_bus_new (void) - { - IBusBus *bus = IBUS_BUS (g_object_new (IBUS_TYPE_BUS, - "connect-async", FALSE, -+ "client-only", FALSE, - NULL)); - - return bus; -@@ -666,6 +826,18 @@ ibus_bus_new_async (void) - { - IBusBus *bus = IBUS_BUS (g_object_new (IBUS_TYPE_BUS, - "connect-async", TRUE, -+ "client-only", FALSE, -+ NULL)); -+ -+ return bus; -+} -+ -+IBusBus * -+ibus_bus_new_async_client (void) -+{ -+ IBusBus *bus = IBUS_BUS (g_object_new (IBUS_TYPE_BUS, -+ "connect-async", TRUE, -+ "client-only", TRUE, - NULL)); - - return bus; -@@ -679,7 +851,7 @@ ibus_bus_is_connected (IBusBus *bus) - if (bus->priv->connection == NULL || g_dbus_connection_is_closed (bus->priv->connection)) - return FALSE; - -- return TRUE; -+ return bus->priv->connected; - } - - IBusInputContext * -@@ -795,9 +967,9 @@ ibus_bus_create_input_context_async (IBusBus *bus, - * 2. New local IBusInputContext proxy of the remote IC - */ - g_dbus_connection_call (bus->priv->connection, -- IBUS_SERVICE_IBUS, -+ ibus_bus_get_service_name (bus), - IBUS_PATH_IBUS, -- IBUS_INTERFACE_IBUS, -+ bus->priv->use_portal ? IBUS_INTERFACE_PORTAL : IBUS_INTERFACE_IBUS, - "CreateInputContext", - g_variant_new ("(s)", client_name), - G_VARIANT_TYPE("(o)"), -@@ -1454,6 +1626,14 @@ ibus_bus_get_connection (IBusBus *bus) - return bus->priv->connection; - } - -+const gchar * -+ibus_bus_get_service_name (IBusBus *bus) -+{ -+ if (bus->priv->use_portal) -+ return IBUS_SERVICE_PORTAL; -+ return IBUS_SERVICE_IBUS; -+} -+ - gboolean - ibus_bus_exit (IBusBus *bus, - gboolean restart) -@@ -2369,6 +2549,13 @@ ibus_bus_call_sync (IBusBus *bus, - g_assert (member != NULL); - g_return_val_if_fail (ibus_bus_is_connected (bus), NULL); - -+ if (bus->priv->use_portal && -+ g_strcmp0 (bus_name, IBUS_SERVICE_IBUS) == 0) { -+ bus_name = IBUS_SERVICE_PORTAL; -+ if (g_strcmp0 (interface, IBUS_INTERFACE_IBUS) == 0) -+ interface = IBUS_INTERFACE_PORTAL; -+ } -+ - GError *error = NULL; - GVariant *result; - result = g_dbus_connection_call_sync (bus->priv->connection, -@@ -2436,6 +2623,13 @@ ibus_bus_call_async (IBusBus *bus, - task = g_task_new (bus, cancellable, callback, user_data); - g_task_set_source_tag (task, source_tag); - -+ if (bus->priv->use_portal && -+ g_strcmp0 (bus_name, IBUS_SERVICE_IBUS) == 0) { -+ bus_name = IBUS_SERVICE_PORTAL; -+ if (g_strcmp0 (interface, IBUS_INTERFACE_IBUS) == 0) -+ interface = IBUS_INTERFACE_PORTAL; -+ } -+ - g_dbus_connection_call (bus->priv->connection, - bus_name, - path, -diff --git a/src/ibusbus.h b/src/ibusbus.h -index 9f65d36a..dff3dfb7 100644 ---- a/src/ibusbus.h -+++ b/src/ibusbus.h -@@ -105,6 +105,19 @@ IBusBus *ibus_bus_new (void); - */ - IBusBus *ibus_bus_new_async (void); - -+/** -+ * ibus_bus_new_async_client: -+ * -+ * Creates a new #IBusBus instance for client use only. It will possibly -+ * be limited in what it can do. -+ * -+ * The instance will asynchronously connect to the IBus daemon. -+ * -+ * Returns: A newly allocated #IBusBus instance, and the instance is not -+ * floating. -+ */ -+IBusBus *ibus_bus_new_async_client (void); -+ - - /** - * ibus_bus_is_connected: -@@ -128,6 +141,16 @@ GDBusConnection * - ibus_bus_get_connection (IBusBus *bus); - - /** -+ * ibus_bus_get_service_name: -+ * @bus: An #IBusBus. -+ * -+ * Return the main service name to use for calls on the ibus connection. -+ * -+ * Returns: at dbus name. -+ */ -+const gchar * ibus_bus_get_service_name (IBusBus *bus); -+ -+/** - * ibus_bus_hello: - * @bus: An #IBusBus. - * -diff --git a/src/ibusinputcontext.c b/src/ibusinputcontext.c -index 9a50acc0..ae7048ad 100644 ---- a/src/ibusinputcontext.c -+++ b/src/ibusinputcontext.c -@@ -684,16 +684,20 @@ ibus_input_context_new (const gchar *path, - { - g_assert (path != NULL); - g_assert (G_IS_DBUS_CONNECTION (connection)); -+ const gchar *service_name = IBUS_SERVICE_IBUS; - - GInitable *initable; - - GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START; - -+ if (g_object_get_data (G_OBJECT (connection), "ibus-portal-connection")) -+ service_name = IBUS_SERVICE_PORTAL; -+ - initable = g_initable_new (IBUS_TYPE_INPUT_CONTEXT, - cancellable, - error, - "g-connection", connection, -- "g-name", IBUS_SERVICE_IBUS, -+ "g-name", service_name, - "g-flags", flags, - "g-interface-name", IBUS_INTERFACE_INPUT_CONTEXT, - "g-object-path", path, -@@ -714,16 +718,20 @@ ibus_input_context_new_async (const gchar *path, - g_assert (path != NULL); - g_assert (G_IS_DBUS_CONNECTION (connection)); - g_assert (callback != NULL); -+ const gchar *service_name = IBUS_SERVICE_IBUS; - - GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START; - -+ if (g_object_get_data (G_OBJECT (connection), "ibus-portal-connection")) -+ service_name = IBUS_SERVICE_PORTAL; -+ - g_async_initable_new_async (IBUS_TYPE_INPUT_CONTEXT, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - "g-connection", connection, -- "g-name", IBUS_SERVICE_IBUS, -+ "g-name", service_name, - "g-flags", flags, - "g-interface-name", IBUS_INTERFACE_INPUT_CONTEXT, - "g-object-path", path, --- -2.13.4 - -From 9772e800f3e6937510f2609c5ce9a6860c59cb81 Mon Sep 17 00:00:00 2001 -From: Alexander Larsson -Date: Mon, 4 Sep 2017 12:02:17 +0900 -Subject: [PATCH 05/14] test: Testing in flatpak - -Test with: -flatpak-builder --force-clean app org.test.IBus.json -flatpak-builder --run --nofilesystem=host app org.test.IBus.json zenity --entry - -BUG=https://github.com/flatpak/flatpak/issues/675 -R=Shawn.P.Huang@gmail.com - -Review URL: https://codereview.appspot.com/329090043 - -Patch from Alexander Larsson . ---- - test/org.test.IBus.json | 43 +++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 43 insertions(+) - create mode 100644 test/org.test.IBus.json - -diff --git a/test/org.test.IBus.json b/test/org.test.IBus.json -new file mode 100644 -index 00000000..dc3caa62 ---- /dev/null -+++ b/test/org.test.IBus.json -@@ -0,0 +1,43 @@ -+{ -+ "app-id": "org.test.IBus", -+ "runtime": "org.gnome.Platform", -+ "runtime-version": "3.24", -+ "sdk": "org.gnome.Sdk", -+ "command": "/usr/bin/zenity", -+ "finish-args": [ -+ /* X11 + XShm access */ -+ "--share=ipc", "--socket=x11", -+ /* Wayland access */ -+ "--socket=wayland", -+ /* Needed for dconf to work */ -+ "--filesystem=xdg-run/dconf", "--filesystem=~/.config/dconf:ro", -+ "--talk-name=ca.desrt.dconf", "--env=DCONF_USER_CONFIG_DIR=.config/dconf", -+ "--env=GTK_IM_MODULE_FILE=/app/lib/gtk-3.0/3.0.0/immodules.cache" -+ ], -+ "build-options" : { -+ "cflags": "-O2 -g", -+ "cxxflags": "-O2 -g", -+ "env": { -+ "V": "1" -+ } -+ }, -+ "cleanup": ["/include", "/lib/pkgconfig", -+ "/share/pkgconfig", "/share/aclocal", -+ "/man", "/share/man", "/share/gtk-doc", -+ "/share/vala", -+ "*.la", "*.a"], -+ "modules": [ -+ { -+ "name": "ibus", -+ "sources": [ -+ { -+ "type": "git", -+ "url": "https://github.com/alexlarsson/ibus", -+ "branch": "ibus-portal" -+ } -+ ], -+ "config-opts": ["--disable-emoji-dict", "--disable-dconf"], -+ "post-install": ["gtk-query-immodules-3.0 /app/lib/gtk-3.0/3.0.0/immodules/im-ibus.so > /app/lib/gtk-3.0/3.0.0/immodules.cache"] -+ } -+ ] -+} --- -2.13.4 - -From 9937a0e4501ccf0cfd238ce7c97733c3099db3f7 Mon Sep 17 00:00:00 2001 -From: fujiwarat -Date: Mon, 4 Sep 2017 12:19:07 +0900 -Subject: [PATCH 06/14] bus: ibus-daemon activates ibus-portal - -When ibus-daemon restarts, ibus-portal exits with on_name_lost() and -the clients wait for portal_name_appeared() until ibus-poral restarts. -Now the clients can connect to ibus-daemon with this way and also -they don't have to activate ibus-portal. - -BUG=https://github.com/flatpak/flatpak/issues/675 -R=Shawn.P.Huang@gmail.com - -Review URL: https://codereview.appspot.com/321530043 ---- - bus/server.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- - portal/portal.c | 6 +----- - 2 files changed, 44 insertions(+), 7 deletions(-) - -diff --git a/bus/server.c b/bus/server.c -index ff3ea093..e2898274 100644 ---- a/bus/server.c -+++ b/bus/server.c -@@ -93,6 +93,45 @@ bus_new_connection_cb (GDBusServer *server, - return TRUE; - } - -+static void -+_server_connect_start_portal_cb (GObject *source_object, -+ GAsyncResult *res, -+ gpointer user_data) -+{ -+ GVariant *result; -+ GError *error = NULL; -+ -+ result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), -+ res, -+ &error); -+ if (result != NULL) { -+ g_variant_unref (result); -+ } else { -+ g_print ("portal is not running: %s\n", error->message); -+ g_error_free (error); -+ } -+} -+ -+static void -+bus_acquired_handler (GDBusConnection *connection, -+ const gchar *name, -+ gpointer user_data) -+{ -+ g_dbus_connection_call (connection, -+ IBUS_SERVICE_PORTAL, -+ IBUS_PATH_IBUS, -+ "org.freedesktop.DBus.Peer", -+ "Ping", -+ g_variant_new ("()"), -+ G_VARIANT_TYPE ("()"), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, -+ NULL /* cancellable */, -+ (GAsyncReadyCallback) -+ _server_connect_start_portal_cb, -+ NULL); -+} -+ - void - bus_server_init (void) - { -@@ -134,8 +173,10 @@ bus_server_init (void) - ibus_write_address (address); - - /* own a session bus name so that third parties can easily track our life-cycle */ -- g_bus_own_name (G_BUS_TYPE_SESSION, IBUS_SERVICE_IBUS, G_BUS_NAME_OWNER_FLAGS_NONE, -- NULL, NULL, NULL, NULL, NULL); -+ g_bus_own_name (G_BUS_TYPE_SESSION, IBUS_SERVICE_IBUS, -+ G_BUS_NAME_OWNER_FLAGS_NONE, -+ bus_acquired_handler, -+ NULL, NULL, NULL, NULL); - } - - const gchar * -diff --git a/portal/portal.c b/portal/portal.c -index 0415f996..cb24d257 100644 ---- a/portal/portal.c -+++ b/portal/portal.c -@@ -101,10 +101,6 @@ _forward_method_cb (GObject *source_object, - gpointer user_data) - { - GDBusMethodInvocation *invocation = user_data; -- IBusPortalContext *portal_context = -- (IBusPortalContext *) g_dbus_method_invocation_get_user_data ( -- invocation); -- IBusEngineDesc *desc; - GError *error = NULL; - - GVariant *variant = g_dbus_proxy_call_finish ((GDBusProxy *) source_object, -@@ -413,6 +409,7 @@ ibus_portal_context_handle_destroy (IBusDbusService *object, - IBusPortalContext *portal_context) - { - g_object_unref (portal_context); -+ return FALSE; - } - - static IBusPortalContext * -@@ -475,7 +472,6 @@ create_input_context_done (IBusBus *bus, - GError *error = NULL; - IBusInputContext *context; - IBusPortalContext *portal_context; -- char *object_path; - - context = ibus_bus_create_input_context_async_finish (ibus_bus, - res, --- -2.13.4 - -From 3e01bab972ad12b92c55a9dde554a0359c217290 Mon Sep 17 00:00:00 2001 -From: fujiwarat -Date: Wed, 6 Sep 2017 12:04:52 +0900 -Subject: [PATCH 07/14] portal: Add org.freedesktop.IBus.Portal.xml in - EXTRA_DIST - -Review URL: https://codereview.appspot.com/325370043 ---- - portal/Makefile.am | 17 +++++++++-------- - 1 file changed, 9 insertions(+), 8 deletions(-) - -diff --git a/portal/Makefile.am b/portal/Makefile.am -index 954fc591..d1e2051a 100644 ---- a/portal/Makefile.am -+++ b/portal/Makefile.am -@@ -65,12 +65,6 @@ ibus_portal_LDADD = \ - $(AM_LDADD) \ - $(NULL) - --EXTRA_DIST = \ -- $(NULL) -- --CLEANFILES = \ -- $(NULL) -- - $(libibus): - $(MAKE) -C $(top_builddir)/src - -@@ -89,7 +83,14 @@ $(ibus_dbus_built_sources) : org.freedesktop.IBus.Portal.xml - $^ \ - $(NULL) - --EXTRA_DIST += $(dbusservice_in_files) --CLEANFILES += $(dbusservice_DATA) -+EXTRA_DIST = \ -+ $(dbusservice_in_files) \ -+ org.freedesktop.IBus.Portal.xml \ -+ $(NULL) -+ -+CLEANFILES = \ -+ $(dbusservice_DATA) \ -+ $(NULL) -+ - - -include $(top_srcdir)/git.mk --- -2.13.4 - -From 21bac4733684ca6a74ddb02f457c0fe19eb9180d Mon Sep 17 00:00:00 2001 -From: fujiwarat -Date: Wed, 6 Sep 2017 12:11:01 +0900 -Subject: [PATCH 08/14] ui/gtk3: Move ibus-emoji-dialog.vapi from ui/gtk3 to - bindings/vala - -R=Shawn.P.Huang@gmail.com - -Review URL: https://codereview.appspot.com/322590043 ---- - .../vala}/IBusEmojiDialog-1.0.metadata | 0 - bindings/vala/Makefile.am | 161 +++++++++++++++++++-- - .../vala}/ibus-emoji-dialog-1.0.deps | 0 - po/POTFILES.skip | 5 + - ui/gtk3/Makefile.am | 113 ++++----------- - ui/gtk3/emojier.vala | 19 +-- - ui/gtk3/ibusemojidialog.h | 26 ++++ - 7 files changed, 213 insertions(+), 111 deletions(-) - rename {ui/gtk3 => bindings/vala}/IBusEmojiDialog-1.0.metadata (100%) - rename {ui/gtk3 => bindings/vala}/ibus-emoji-dialog-1.0.deps (100%) - -diff --git a/ui/gtk3/IBusEmojiDialog-1.0.metadata b/bindings/vala/IBusEmojiDialog-1.0.metadata -similarity index 100% -rename from ui/gtk3/IBusEmojiDialog-1.0.metadata -rename to bindings/vala/IBusEmojiDialog-1.0.metadata -diff --git a/bindings/vala/Makefile.am b/bindings/vala/Makefile.am -index 4e34afc7..fc8e2f01 100644 ---- a/bindings/vala/Makefile.am -+++ b/bindings/vala/Makefile.am -@@ -3,7 +3,8 @@ - # ibus - The Input Bus - # - # Copyright (c) 2007-2016 Peng Huang --# Copyright (c) 2007-2016 Red Hat, Inc. -+# Copyright (c) 2017 Takao Fujiwara -+# Copyright (c) 2007-2017 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,15 +23,47 @@ - - -include $(VAPIGEN_MAKEFILE) - -+libibus = $(top_builddir)/src/libibus-@IBUS_API_VERSION@.la -+ -+noinst_LTLIBRARIES = -+noinst_DATA = -+INTROSPECTION_GIRS = -+girdir = $(datadir)/gir-1.0 -+ -+AM_CPPFLAGS = \ -+ -I$(top_srcdir)/src \ -+ -I$(top_builddir)/src \ -+ -include $(CONFIG_HEADER) \ -+ $(NULL) -+AM_CFLAGS = \ -+ -DG_LOG_DOMAIN=\"IBUS\" \ -+ -DPKGDATADIR=\"$(pkgdatadir)\" \ -+ -DIBUS_DISABLE_DEPRECATED \ -+ -Wno-unused-variable \ -+ -Wno-unused-but-set-variable \ -+ -Wno-unused-function \ -+ $(NULL) -+AM_VALAFLAGS = \ -+ --vapidir=$(builddir) \ -+ --vapidir=$(srcdir) \ -+ --pkg=posix \ -+ --pkg=gtk+-3.0 \ -+ --pkg=gdk-x11-3.0 \ -+ --pkg=ibus-1.0 \ -+ --pkg=config \ -+ --pkg=xi \ -+ --target-glib="$(VALA_TARGET_GLIB_VERSION)" \ -+ $(NULL) -+ - vapi_deps = \ - IBus-1.0.metadata \ -- IBus-1.0-custom.vala \ - $(top_builddir)/src/IBus-1.0.gir \ - $(NULL) - - ibus-1.0.vapi: $(vapi_deps) - --VAPIGEN_VAPIS = ibus-1.0.vapi -+ibus_vapi = ibus-1.0.vapi -+VAPIGEN_VAPIS = $(ibus_vapi) - - ibus_1_0_vapi_DEPS = gio-2.0 - ibus_1_0_vapi_METADATADIRS = $(srcdir) -@@ -40,18 +73,118 @@ ibus_1_0_vapi_FILES = \ - $(NULL) - - vapidir = $(datadir)/vala/vapi --vapi_DATA = $(VAPIGEN_VAPIS) $(VAPIGEN_VAPIS:.vapi=.deps) -+vapi_DATA = $(ibus_vapi) $(ibus_vapi:.vapi=.deps) - --MAINTAINERCLEANFILES = $(VAPIGEN_VAPIS) --DISTCLEANFILES = $(VAPIGEN_VAPIS) -+MAINTAINERCLEANFILES = $(ibus_vapi) -+DISTCLEANFILES = $(ibus_vapi) - --EXTRA_DIST = \ -- $(VAPIGEN_VAPIS) \ -- IBus-1.0.metadata \ -- IBus-1.0-custom.vala \ -- ibus-1.0.deps \ -- config.vapi \ -- xi.vapi \ -- $(NULL) -+EXTRA_DIST = \ -+ $(ibus_vapi) \ -+ IBus-1.0.metadata \ -+ IBus-1.0-custom.vala \ -+ IBusEmojiDialog-1.0.metadata \ -+ ibus-1.0.deps \ -+ ibus-emoji-dialog-1.0.deps \ -+ config.vapi \ -+ xi.vapi \ -+ $(NULL) -+ -+if ENABLE_EMOJI_DICT -+AM_VALAFLAGS += --define=EMOJI_DICT -+ -+libibus_emoji_dialog = libibus-emoji-dialog-1.0.la -+noinst_LTLIBRARIES += $(libibus_emoji_dialog) -+ -+libibus_emoji_dialog_1_0_la_SOURCES = \ -+ candidatearea.vala \ -+ emojier.vala \ -+ iconwidget.vala \ -+ pango.vala \ -+ separator.vala \ -+ $(NULL) -+libibus_emoji_dialog_1_0_la_CFLAGS = \ -+ $(AM_CFLAGS) \ -+ @GLIB2_CFLAGS@ \ -+ @GIO2_CFLAGS@ \ -+ @GTHREAD2_CFLAGS@ \ -+ @GTK3_CFLAGS@ \ -+ @X11_CFLAGS@ \ -+ -DBINDIR=\"$(bindir)\" \ -+ $(NULL) -+libibus_emoji_dialog_1_0_la_LIBADD = \ -+ @GLIB2_LIBS@ \ -+ @GIO2_LIBS@ \ -+ @GTHREAD2_LIBS@ \ -+ @GTK3_LIBS@ \ -+ @X11_LIBS@ \ -+ -lXi \ -+ $(libibus) \ -+ $(NULL) -+libibus_emoji_dialog_1_0_la_LDFLAGS = \ -+ -no-undefined \ -+ -export-symbols-regex "ibus_.*" \ -+ $(NULL) -+ -+# per file setting is needed to avoid conflicting LN_S by calling -+# duplicated times in parallel make -+%.vala: $(ibus_vapi) -+ if test ! -f $@ ; then \ -+ $(LN_S) $(top_srcdir)/ui/gtk3/$@ .; \ -+ fi; -+ -+MAINTAINERCLEANFILES += $(libibus_emoji_dialog_1_0_la_SOURCES) -+DISTCLEANFILES += $(libibus_emoji_dialog_1_0_la_SOURCES) -+ -+if HAVE_INTROSPECTION -+-include $(INTROSPECTION_MAKEFILE) -+INTROSPECTION_SCANNER_ARGS = -+INTROSPECTION_COMPILER_ARGS = \ -+ --includedir=$(srcdir) \ -+ --includedir=. \ -+ --includedir=$(top_srcdir)/src \ -+ $(NULL) -+ -+ -+emoji_headers = \ -+ $(top_srcdir)/ui/gtk3/ibusemojidialog.h \ -+ $(NULL) -+ -+IBusEmojiDialog-1.0.gir: $(libibus_emoji_dialog) Makefile -+IBusEmojiDialog_1_0_gir_SCANNERFLAGS = \ -+ --pkg-export=ibus-1.0 \ -+ --pkg=gtk+-3.0 \ -+ $(IBUS_GIR_SCANNERFLAGS) \ -+ $(NULL) -+IBusEmojiDialog_1_0_gir_INCLUDES = Gtk-3.0 GLib-2.0 GObject-2.0 Gio-2.0 -+IBusEmojiDialog_1_0_gir_LIBS = $(libibus_emoji_dialog) $(libibus) -+IBusEmojiDialog_1_0_gir_FILES = $(emoji_headers) -+IBusEmojiDialog_1_0_gir_CFLAGS = \ -+ -I$(srcdir) \ -+ -I$(builddir) \ -+ -I$(top_srcdir)/src \ -+ $(NULL) -+ -+ibus_emoji_dialog_gir = IBusEmojiDialog-1.0.gir -+INTROSPECTION_GIRS += $(ibus_emoji_dialog_gir) -+noinst_DATA += $(ibus_emoji_dialog_gir) -+EXTRA_DIST += $(ibus_emoji_dialog_gir) -+MAINTAINERCLEANFILES += $(ibus_emoji_dialog_gir) -+DISTCLEANFILES += $(ibus_emoji_dialog_gir) -+ -+ibus-emoji-dialog-1.0.vapi: $(ibus_emoji_dialog_gir) IBusEmojiDialog-1.0.metadata -+ibus_emoji_dialog_vapi = ibus-emoji-dialog-1.0.vapi -+ibus_emoji_dialog_1_0_vapi_DEPS = gtk+-3.0 gio-2.0 -+ibus_emoji_dialog_1_0_vapi_METADATADIRS = $(srcdir) -+ibus_emoji_dialog_1_0_vapi_FILES = IBusEmojiDialog-1.0.gir -+VAPIGEN_VAPIS += $(ibus_emoji_dialog_vapi) -+noinst_DATA += $(ibus_emoji_dialog_vapi) -+EXTRA_DIST += $(ibus_emoji_dialog_vapi) -+MAINTAINERCLEANFILES += $(ibus_emoji_dialog_vapi) -+DISTCLEANFILES += $(ibus_emoji_dialog_vapi) -+ -+endif -+#end of HAVE_INTROSPECTION -+endif -+# end of ENABLE_EMOJI_DICT - - -include $(top_srcdir)/git.mk -diff --git a/ui/gtk3/ibus-emoji-dialog-1.0.deps b/bindings/vala/ibus-emoji-dialog-1.0.deps -similarity index 100% -rename from ui/gtk3/ibus-emoji-dialog-1.0.deps -rename to bindings/vala/ibus-emoji-dialog-1.0.deps -diff --git a/po/POTFILES.skip b/po/POTFILES.skip -index 7190221d..10b88298 100644 ---- a/po/POTFILES.skip -+++ b/po/POTFILES.skip -@@ -2,6 +2,11 @@ - # Please keep this file in alphabetical order. - # Files under ui/gtk2/ are not shipped in the distribution, but kept - # in the git repository for reference. -+bindings/vala/candidatearea.c -+bindings/vala/emojier.c -+bindings/vala/iconwidget.c -+bindings/vala/pango.c -+bindings/vala/separator.c - ibus/_config.py - tools/main.c - ui/gtk2/candidatepanel.py -diff --git a/ui/gtk3/Makefile.am b/ui/gtk3/Makefile.am -index c79641a5..786b80e6 100644 ---- a/ui/gtk3/Makefile.am -+++ b/ui/gtk3/Makefile.am -@@ -81,10 +81,6 @@ AM_VALAFLAGS = \ - --target-glib="$(VALA_TARGET_GLIB_VERSION)" \ - $(NULL) - --MAINTAINERCLEANFILES = --DISTCLEANFILES = --noinst_DATA = -- - if ENABLE_LIBNOTIFY - AM_CFLAGS += \ - @LIBNOTIFY_CFLAGS@ \ -@@ -158,9 +154,8 @@ man_seven_in_files = ibus-emoji.7.in - EXTRA_DIST = \ - $(emoji_headers) \ - $(man_seven_in_files) \ -- IBusEmojiDialog-1.0.metadata \ -+ emojierapp.vala \ - gtkpanel.xml.in \ -- ibus-emoji-dialog-1.0.deps \ - notification-item.xml \ - notification-watcher.xml \ - $(NULL) -@@ -168,98 +163,40 @@ EXTRA_DIST = \ - if ENABLE_EMOJI_DICT - AM_VALAFLAGS += --define=EMOJI_DICT - --libibus_emoji_dialog = libibus-emoji-dialog-1.0.la -- --noinst_LTLIBRARIES = $(libibus_emoji_dialog) -- --libibus_emoji_dialog_1_0_la_CFLAGS = $(AM_CFLAGS) --libibus_emoji_dialog_1_0_la_LDFLAGS = \ -- -no-undefined \ -- -export-symbols-regex "ibus_.*" \ -- -version-info @LT_VERSION_INFO@ \ -- $(NULL) --libibus_emoji_dialog_1_0_la_SOURCES = \ -- candidatearea.vala \ -- emojier.vala \ -- iconwidget.vala \ -- pango.vala \ -- separator.vala \ -- $(NULL) -- - libexec_PROGRAMS += ibus-ui-emojier - --ibus_ui_emojier_SOURCES = \ -- $(libibus_emoji_dialog_1_0_la_SOURCES) \ -+ibus_ui_emojier_VALASOURCES = \ - emojierapp.vala \ -+ candidatearea.vala \ -+ emojier.vala \ -+ iconwidget.vala \ -+ pango.vala \ -+ separator.vala \ -+ $(NULL) -+ibus_ui_emojier_SOURCES = \ -+ $(ibus_ui_emojier_VALASOURCES:.vala=.c) \ - $(NULL) - - ibus_ui_emojier_LDADD = \ - $(AM_LDADD) \ - $(NULL) - ---include $(INTROSPECTION_MAKEFILE) --INTROSPECTION_SCANNER_ARGS = --INTROSPECTION_COMPILER_ARGS = \ -- --includedir=$(srcdir) \ -- --includedir=. \ -- --includedir=$(top_srcdir)/src \ -- $(NULL) -- --if HAVE_INTROSPECTION --introspection_sources = \ -- $(emoji_headers) \ -- $(NULL) --IBusEmojiDialog-1.0.gir: $(libibus_emoji_dialog) Makefile --IBusEmojiDialog_1_0_gir_SCANNERFLAGS = \ -- --pkg-export=ibus-1.0 \ -- --pkg=gtk+-3.0 \ -- $(IBUS_GIR_SCANNERFLAGS) \ -+ibus_ui_emojier_VALAFLAGS = \ -+ $(AM_VALAFLAGS) \ - $(NULL) --IBusEmojiDialog-1.0.gir: $(libibus_emoji_dialog) Makefile --IBusEmojiDialog_1_0_gir_INCLUDES = Gtk-3.0 GLib-2.0 GObject-2.0 Gio-2.0 --IBusEmojiDialog_1_0_gir_LIBS = $(libibus_emoji_dialog) $(libibus) --IBusEmojiDialog_1_0_gir_FILES = \ -- $(addprefix $(srcdir)/,$(introspection_sources)) \ -- $(NULL) --IBusEmojiDialog_1_0_gir_CFLAGS = \ -- -DIBUS_COMPILATION \ -- -I$(srcdir) \ -- -I$(builddir) \ -- -I$(top_srcdir)/src \ -- $(NULL) --INTROSPECTION_GIRS = IBusEmojiDialog-1.0.gir -- --girdir = $(datadir)/gir-1.0 --noinst_DATA += $(INTROSPECTION_GIRS) --CLEANFILES += $(INTROSPECTION_GIRS) - --typelibsdir = $(libdir)/girepository-1.0 --noinst_DATA += $(INTROSPECTION_GIRS:.gir=.typelib) --CLEANFILES += $(INTROSPECTION_GIRS:.gir=.typelib) -- -- --if ENABLE_VAPIGEN ---include $(VAPIGEN_MAKEFILE) -- --ibus-emoji-dialog-1.0.vapi: $(INTROSPECTION_GIRS) IBusEmojiDialog-1.0.metadata -- --VAPIGEN_VAPIS = ibus-emoji-dialog-1.0.vapi -- --ibus_emoji_dialog_1_0_vapi_DEPS = gtk+-3.0 gio-2.0 --ibus_emoji_dialog_1_0_vapi_METADATADIRS = $(srcdir) --ibus_emoji_dialog_1_0_vapi_FILES = $(INTROSPECTION_GIRS) -- --vapidir = $(datadir)/vala/vapi --noinst_DATA += $(VAPIGEN_VAPIS) $(VAPIGEN_VAPIS:.vapi=.deps) -- --MAINTAINERCLEANFILES += $(VAPIGEN_VAPIS) --DISTCLEANFILES += $(VAPIGEN_VAPIS) --EXTRA_DIST += $(VAPIGEN_VAPIS) -- --# end of ENABLE_VAPIGEN --endif --# end of HAVE_INTROSPECTION --endif -+# This line and foo_VALASOURCES line can delete the duplicated entries -+# of emojier.c: emojier.vala -+emojierapp.c: $(ibus_ui_emojier_VALASOURCES) -+ $(AM_V_VALAC)$(am__cd) $(srcdir) && $(VALAC) $(AM_VALAFLAGS) \ -+$(VALAFLAGS) -C $(ibus_ui_emojier_VALASOURCES) -+ $(NULL) -+# make dist creates .c files in a different srcdir -+emojierapp.o: $(srcdir)/emojierapp.c -+ $(AM_V_CC)source='$<' object='$@' libtool=no \ -+ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ -+ $(AM_V_CC_no)$(COMPILE) -c -o $@ $< -+ $(NULL) - - man_seven_files = $(man_seven_in_files:.7.in=.7) - man_seven_DATA =$(man_seven_files:.7=.7.gz) -@@ -276,7 +213,7 @@ CLEANFILES += \ - $(man_seven_files) \ - $(NULL) - --# end of ENABLE_EMOJI_DICT - endif -+# end of ENABLE_EMOJI_DICT - - -include $(top_srcdir)/git.mk -diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala -index 9df59ac4..36ab4bab 100644 ---- a/ui/gtk3/emojier.vala -+++ b/ui/gtk3/emojier.vala -@@ -1139,6 +1139,7 @@ class IBusEmojier : Gtk.ApplicationWindow { - m_category_active_index = (int)list.length(); - } - Gtk.Adjustment adjustment = m_list_box.get_adjustment(); -+ m_scrolled_window.set_hadjustment(new Gtk.Adjustment(0, 0, 0, 0, 0, 0)); - m_scrolled_window.set_vadjustment(adjustment); - show_category_list(); - } -@@ -1156,7 +1157,7 @@ class IBusEmojier : Gtk.ApplicationWindow { - else if (keyval == Gdk.Key.Right) - m_lookup_table.cursor_down(); - show_candidate_panel(); -- } else if (m_entry.get_text().len() > 0) { -+ } else if (m_entry.get_text().length > 0) { - int step = 0; - if (keyval == Gdk.Key.Left) - step = -1; -@@ -1211,7 +1212,7 @@ class IBusEmojier : Gtk.ApplicationWindow { - show_candidate_panel(); - return true; - } -- if (m_entry.get_text().len() > 0) { -+ if (m_entry.get_text().length > 0) { - int step = 0; - if (keyval == Gdk.Key.Home) - step = -1; -@@ -1410,7 +1411,7 @@ class IBusEmojier : Gtk.ApplicationWindow { - key_press_enter(); - return true; - case Gdk.Key.BackSpace: -- if (m_entry.get_text().len() > 0) { -+ if (m_entry.get_text().length > 0) { - if ((modifiers & Gdk.ModifierType.CONTROL_MASK) != 0) { - GLib.Signal.emit_by_name(m_entry, "delete-from-cursor", - Gtk.DeleteType.WORD_ENDS, -1); -@@ -1422,7 +1423,7 @@ class IBusEmojier : Gtk.ApplicationWindow { - break; - case Gdk.Key.Delete: - case Gdk.Key.KP_Delete: -- if (m_entry.get_text().len() > 0) { -+ if (m_entry.get_text().length > 0) { - if ((modifiers & Gdk.ModifierType.CONTROL_MASK) != 0) { - GLib.Signal.emit_by_name(m_entry, "delete-from-cursor", - Gtk.DeleteType.WORD_ENDS, 1); -@@ -1436,7 +1437,7 @@ class IBusEmojier : Gtk.ApplicationWindow { - case Gdk.Key.space: - case Gdk.Key.KP_Space: - if ((modifiers & Gdk.ModifierType.SHIFT_MASK) != 0) { -- if (m_entry.get_text().len() > 0) -+ if (m_entry.get_text().length > 0) - entry_enter_keyval(keyval); - } else if (m_candidate_panel_is_visible) { - enter_notify_disable_with_timer(); -@@ -1512,7 +1513,7 @@ class IBusEmojier : Gtk.ApplicationWindow { - return true; - break; - case Gdk.Key.u: -- if (m_entry.get_text().len() > 0) { -+ if (m_entry.get_text().length > 0) { - GLib.Signal.emit_by_name(m_entry, - "delete-from-cursor", - Gtk.DeleteType.PARAGRAPH_ENDS, -@@ -1521,13 +1522,13 @@ class IBusEmojier : Gtk.ApplicationWindow { - } - break; - case Gdk.Key.a: -- if (m_entry.get_text().len() > 0) { -+ if (m_entry.get_text().length > 0) { - m_entry.select_region(0, -1); - return true; - } - break; - case Gdk.Key.x: -- if (m_entry.get_text().len() > 0) { -+ if (m_entry.get_text().length > 0) { - GLib.Signal.emit_by_name(m_entry, "cut-clipboard"); - return true; - } -@@ -1544,7 +1545,7 @@ class IBusEmojier : Gtk.ApplicationWindow { - clipboard.store(); - return true; - } -- } else if (m_entry.get_text().len() > 0) { -+ } else if (m_entry.get_text().length > 0) { - GLib.Signal.emit_by_name(m_entry, "copy-clipboard"); - return true; - } -diff --git a/ui/gtk3/ibusemojidialog.h b/ui/gtk3/ibusemojidialog.h -index 24d195c8..ed8886a8 100644 ---- a/ui/gtk3/ibusemojidialog.h -+++ b/ui/gtk3/ibusemojidialog.h -@@ -170,5 +170,31 @@ void ibus_emojier_set_favorites (gchar** favorites, - favorite_annotations, - int - favorite_annotations_length); -+ -+/** -+ * ibus_emojier_set_partial_match: -+ * @has_partial_match: Enable the partial match if %TRUE. Otherwise if %FALSE. -+ * -+ * Set partial match for emoji annotations. -+ */ -+void ibus_emojier_set_partial_match (gboolean has_partial_match); -+ -+/** -+ * ibus_emojier_set_partial_match_length: -+ * @length: minimum lenght to match partially. -+ * -+ * Set the minimum lenght to match partially. -+ */ -+void ibus_emojier_set_partial_match_length -+ (gint length); -+ -+/** -+ * ibus_emojier_set_partial_match_condition: -+ * @condition: condition id between 0 and 2. -+ * -+ * Set the partial match condition with the integer. -+ */ -+void ibus_emojier_set_partial_match_condition -+ (gint condition); - G_END_DECLS - #endif --- -2.13.4 - -From d788918b635275d0247e68f26f9c840100bca366 Mon Sep 17 00:00:00 2001 -From: fujiwarat -Date: Wed, 6 Sep 2017 12:17:30 +0900 -Subject: [PATCH 09/14] ui/gtk3: Switcher should ignore mouse until it moves - -BUG=https://github.com/ibus/ibus/issues/1929 - -Review URL: https://codereview.appspot.com/329100043 ---- - ui/gtk3/switcher.vala | 28 +++++++++++++++++++++++++++- - 1 file changed, 27 insertions(+), 1 deletion(-) - -diff --git a/ui/gtk3/switcher.vala b/ui/gtk3/switcher.vala -index cf187555..269a68d4 100644 ---- a/ui/gtk3/switcher.vala -+++ b/ui/gtk3/switcher.vala -@@ -91,6 +91,9 @@ class Switcher : Gtk.Window { - private uint m_popup_delay_time_id = 0; - private int m_root_x; - private int m_root_y; -+ private double m_mouse_init_x; -+ private double m_mouse_init_y; -+ private bool m_mouse_moved; - private GLib.HashTable m_xkb_languages = - new GLib.HashTable(GLib.str_hash, - GLib.str_equal); -@@ -221,6 +224,11 @@ class Switcher : Gtk.Window { - Gdk.CURRENT_TIME); - if (status != Gdk.GrabStatus.SUCCESS) - warning("Grab pointer failed! status = %d", status); -+ // Probably we can delete m_popup_delay_time in 1.6 -+ pointer.get_position_double(null, -+ out m_mouse_init_x, -+ out m_mouse_init_y); -+ m_mouse_moved = false; - - - m_loop = new GLib.MainLoop(); -@@ -263,12 +271,30 @@ class Switcher : Gtk.Window { - var button = new IBusEngineButton(engine, this); - var longname = engine.get_longname(); - button.set_relief(Gtk.ReliefStyle.NONE); -+ button.add_events(Gdk.EventMask.POINTER_MOTION_MASK); - button.show(); - - button.enter_notify_event.connect((e) => { -+ // avoid gtk_button_update_state() -+ return true; -+ }); -+ button.motion_notify_event.connect((e) => { -+#if VALA_0_24 -+ Gdk.EventMotion pe = e; -+#else -+ Gdk.EventMotion *pe = &e; -+#endif -+ if (m_selected_engine == index) -+ return false; -+ if (!m_mouse_moved && -+ m_mouse_init_x == pe.x_root && -+ m_mouse_init_y == pe.y_root) { -+ return false; -+ } -+ m_mouse_moved = true; - button.grab_focus(); - m_selected_engine = index; -- return true; -+ return false; - }); - - button.button_press_event.connect((e) => { --- -2.13.4 - -From bbfb3d738b9d61d1eb0658a9ce56e3cd8c111ac4 Mon Sep 17 00:00:00 2001 -From: fujiwarat -Date: Wed, 6 Sep 2017 14:08:40 +0900 -Subject: [PATCH 10/14] client/gtk2: Do not send key events to - GtkIMContextSimple - -GtkIMContextSimple binds Ctrl-Shift-u but IBus clients do not now. - -BUG=https://github.com/ibus/ibus/issues/1889 -R=Shawn.P.Huang@gmail.com - -Review URL: https://codereview.appspot.com/327290043 ---- - client/gtk2/ibusimcontext.c | 41 +++++++++++++++++++++++++++++++++++++++-- - src/ibusenginesimple.c | 23 ++--------------------- - src/ibusenginesimple.h | 24 ++++++++++++++++++++++-- - 3 files changed, 63 insertions(+), 25 deletions(-) - -diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c -index b4ca8828..3ea46951 100644 ---- a/client/gtk2/ibusimcontext.c -+++ b/client/gtk2/ibusimcontext.c -@@ -2,7 +2,8 @@ - /* vim:set et sts=4: */ - /* ibus - The Input Bus - * Copyright (C) 2008-2013 Peng Huang -- * Copyright (C) 2008-2013 Red Hat, Inc. -+ * Copyright (C) 2015-2017 Takao Fujiwara -+ * Copyright (C) 2008-2017 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 -@@ -247,6 +248,39 @@ _focus_out_cb (GtkWidget *widget, - return FALSE; - } - -+static gboolean -+ibus_im_context_commit_event (IBusIMContext *ibusimcontext, -+ GdkEventKey *event) -+{ -+ int i; -+ GdkModifierType no_text_input_mask; -+ gunichar ch; -+ -+ if (event->type == GDK_KEY_RELEASE) -+ return FALSE; -+ /* Ignore modifier key presses */ -+ for (i = 0; i < G_N_ELEMENTS (IBUS_COMPOSE_IGNORE_KEYLIST); i++) -+ if (event->keyval == IBUS_COMPOSE_IGNORE_KEYLIST[i]) -+ return FALSE; -+ no_text_input_mask = gdk_keymap_get_modifier_mask ( -+ gdk_keymap_get_for_display (gdk_display_get_default ()), -+ GDK_MODIFIER_INTENT_NO_TEXT_INPUT); -+ if (event->state & no_text_input_mask || -+ event->keyval == GDK_KEY_Return || -+ event->keyval == GDK_KEY_ISO_Enter || -+ event->keyval == GDK_KEY_KP_Enter) { -+ return FALSE; -+ } -+ ch = ibus_keyval_to_unicode (event->keyval); -+ if (ch != 0 && !g_unichar_iscntrl (ch)) { -+ IBusText *text = ibus_text_new_from_unichar (ch); -+ g_signal_emit (ibusimcontext, _signal_commit_id, 0, text->text); -+ g_object_unref (text); -+ return TRUE; -+ } -+ return FALSE; -+} -+ - static void - _process_key_event_done (GObject *object, - GAsyncResult *res, -@@ -797,8 +831,11 @@ ibus_im_context_filter_keypress (GtkIMContext *context, - if (event->state & IBUS_HANDLED_MASK) - return TRUE; - -+ /* Do not call gtk_im_context_filter_keypress() because -+ * gtk_im_context_simple_filter_keypress() binds Ctrl-Shift-u -+ */ - if (event->state & IBUS_IGNORED_MASK) -- return gtk_im_context_filter_keypress (ibusimcontext->slave, event); -+ return ibus_im_context_commit_event (ibusimcontext, event); - - /* XXX it is a workaround for some applications do not set client - * window. */ -diff --git a/src/ibusenginesimple.c b/src/ibusenginesimple.c -index cddd932c..63785223 100644 ---- a/src/ibusenginesimple.c -+++ b/src/ibusenginesimple.c -@@ -81,25 +81,6 @@ const IBusComposeTableCompact ibus_compose_table_compact = { - - static GSList *global_tables; - --static const guint16 ibus_compose_ignore[] = { -- IBUS_KEY_Shift_L, -- IBUS_KEY_Shift_R, -- IBUS_KEY_Control_L, -- IBUS_KEY_Control_R, -- IBUS_KEY_Caps_Lock, -- IBUS_KEY_Shift_Lock, -- IBUS_KEY_Meta_L, -- IBUS_KEY_Meta_R, -- IBUS_KEY_Alt_L, -- IBUS_KEY_Alt_R, -- IBUS_KEY_Super_L, -- IBUS_KEY_Super_R, -- IBUS_KEY_Hyper_L, -- IBUS_KEY_Hyper_R, -- IBUS_KEY_Mode_switch, -- IBUS_KEY_ISO_Level3_Shift --}; -- - /* functions prototype */ - static void ibus_engine_simple_destroy (IBusEngineSimple *simple); - static void ibus_engine_simple_reset (IBusEngine *engine); -@@ -1045,8 +1026,8 @@ ibus_engine_simple_process_key_event (IBusEngine *engine, - } - - /* Ignore modifier key presses */ -- for (i = 0; i < G_N_ELEMENTS (ibus_compose_ignore); i++) -- if (keyval == ibus_compose_ignore[i]) -+ for (i = 0; i < G_N_ELEMENTS (IBUS_COMPOSE_IGNORE_KEYLIST); i++) -+ if (keyval == IBUS_COMPOSE_IGNORE_KEYLIST[i]) - return FALSE; - - if ((priv->in_hex_sequence || priv->in_emoji_sequence) -diff --git a/src/ibusenginesimple.h b/src/ibusenginesimple.h -index 8712659c..a5ef34fb 100644 ---- a/src/ibusenginesimple.h -+++ b/src/ibusenginesimple.h -@@ -2,8 +2,8 @@ - /* vim:set et sts=4: */ - /* ibus - The Input Bus - * Copyright (C) 2008-2015 Peng Huang -- * Copyright (C) 2015-2016 Takao Fujiwara -- * Copyright (C) 2008-2016 Red Hat, Inc. -+ * Copyright (C) 2015-2017 Takao Fujiwara -+ * Copyright (C) 2008-2017 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 -@@ -40,6 +40,7 @@ - */ - - #include "ibusengine.h" -+#include "ibuskeysyms.h" - - G_BEGIN_DECLS - -@@ -94,6 +95,25 @@ struct _IBusEngineSimpleClass { - gpointer pdummy[8]; - }; - -+static const guint16 IBUS_COMPOSE_IGNORE_KEYLIST[] = { -+ IBUS_KEY_Shift_L, -+ IBUS_KEY_Shift_R, -+ IBUS_KEY_Control_L, -+ IBUS_KEY_Control_R, -+ IBUS_KEY_Caps_Lock, -+ IBUS_KEY_Shift_Lock, -+ IBUS_KEY_Meta_L, -+ IBUS_KEY_Meta_R, -+ IBUS_KEY_Alt_L, -+ IBUS_KEY_Alt_R, -+ IBUS_KEY_Super_L, -+ IBUS_KEY_Super_R, -+ IBUS_KEY_Hyper_L, -+ IBUS_KEY_Hyper_R, -+ IBUS_KEY_Mode_switch, -+ IBUS_KEY_ISO_Level3_Shift -+}; -+ - GType ibus_engine_simple_get_type (void); - - /** --- -2.13.4 - -From d784e04c38eeb069f9a8da8b30743f4463fa34c3 Mon Sep 17 00:00:00 2001 -From: fujiwarat -Date: Thu, 7 Sep 2017 10:57:14 +0900 -Subject: [PATCH 11/14] client/gtk2: Fix a build failure with - GDK_MODIFIER_INTENT_NO_TEXT_INPUT - -BUG=https://github.com/ibus/ibus/issues/1942 - -Review URL: https://codereview.appspot.com/327300043 ---- - client/gtk2/ibusimcontext.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c -index 3ea46951..a806382d 100644 ---- a/client/gtk2/ibusimcontext.c -+++ b/client/gtk2/ibusimcontext.c -@@ -262,9 +262,21 @@ ibus_im_context_commit_event (IBusIMContext *ibusimcontext, - for (i = 0; i < G_N_ELEMENTS (IBUS_COMPOSE_IGNORE_KEYLIST); i++) - if (event->keyval == IBUS_COMPOSE_IGNORE_KEYLIST[i]) - return FALSE; -+#if GTK_CHECK_VERSION (3, 4, 0) - no_text_input_mask = gdk_keymap_get_modifier_mask ( - gdk_keymap_get_for_display (gdk_display_get_default ()), - GDK_MODIFIER_INTENT_NO_TEXT_INPUT); -+#else -+# ifndef GDK_WINDOWING_QUARTZ -+# define _IBUS_NO_TEXT_INPUT_MOD_MASK (GDK_MOD1_MASK | GDK_CONTROL_MASK) -+# else -+# define _IBUS_NO_TEXT_INPUT_MOD_MASK (GDK_MOD2_MASK | GDK_CONTROL_MASK) -+# endif -+ -+ no_text_input_mask = _IBUS_NO_TEXT_INPUT_MOD_MASK; -+ -+# undef _IBUS_NO_TEXT_INPUT_MOD_MASK -+#endif - if (event->state & no_text_input_mask || - event->keyval == GDK_KEY_Return || - event->keyval == GDK_KEY_ISO_Enter || --- -2.13.4 - -From 0632cbbbb573749bbca96a416fde1490810e52d2 Mon Sep 17 00:00:00 2001 -From: fujiwarat -Date: Wed, 13 Sep 2017 18:15:06 +0900 -Subject: [PATCH 13/14] ui/gtk3: Fix PropertyPanel position in workarea - -gdk_screen_get_monitor_workarea() no longer return the correct area -from "_NET_WORKAREA" atom in GTK 3.22 and now use -gdk_monitor_get_workarea() instead. - -Use gdk_seat_grab() instead of deprecated gdk_device_grab(). - -Use gtk_menu_popup_at_rect() instead of deprecated gtk_menu_popup() and -generate a new foreign GdkWindow with mouse cursor for the Qt Window. - -Also fixed some deprecated APIs. - -R=Shawn.P.Huang@gmail.com - -Review URL: https://codereview.appspot.com/330190043 ---- - ui/gtk3/candidatepanel.vala | 40 ++++++++------- - ui/gtk3/emojier.vala | 24 ++++++--- - ui/gtk3/handle.vala | 7 +-- - ui/gtk3/indicator.vala | 68 ++++++++++++++++++++++++-- - ui/gtk3/keybindingmanager.vala | 2 +- - ui/gtk3/panel.vala | 108 +++++++++++++++++++++++++++++++---------- - ui/gtk3/propertypanel.vala | 21 +++++++- - ui/gtk3/switcher.vala | 84 +++++++++++++++++++++++--------- - 8 files changed, 270 insertions(+), 84 deletions(-) - -diff --git a/ui/gtk3/candidatepanel.vala b/ui/gtk3/candidatepanel.vala -index 0e5e3bc2..ec2d3db4 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 -- * Copyright(c) 2015-2016 Takao Fujiwara -+ * Copyright(c) 2015-2017 Takao Fujiwara - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public -@@ -292,6 +292,26 @@ public class CandidatePanel : Gtk.Box{ - adjust_window_position_vertical(); - } - -+ 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_horizontal() { - Gdk.Point cursor_right_bottom = { - m_cursor_location.x + m_cursor_location.width, -@@ -305,14 +325,7 @@ public class CandidatePanel : Gtk.Box{ - cursor_right_bottom.y + allocation.height - }; - -- Gdk.Screen screen = Gdk.Screen.get_default(); -- int monitor_num = screen.get_monitor_at_point(m_cursor_location.x, -- m_cursor_location.y); -- // Use get_monitor_geometry() instead of get_monitor_area(). -- // get_monitor_area() excludes docks, but the lookup window should be -- // shown over them. -- Gdk.Rectangle monitor_area; -- screen.get_monitor_geometry(monitor_num, out monitor_area); -+ 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; - -@@ -358,14 +371,7 @@ public class CandidatePanel : Gtk.Box{ - m_cursor_location.y + allocation.height - }; - -- Gdk.Screen screen = Gdk.Screen.get_default(); -- int monitor_num = screen.get_monitor_at_point(m_cursor_location.x, -- m_cursor_location.y); -- // Use get_monitor_geometry() instead of get_monitor_area(). -- // get_monitor_area() excludes docks, but the lookup window should be -- // shown over them. -- Gdk.Rectangle monitor_area; -- screen.get_monitor_geometry(monitor_num, out monitor_area); -+ 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; - -diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala -index 36ab4bab..9cd98140 100644 ---- a/ui/gtk3/emojier.vala -+++ b/ui/gtk3/emojier.vala -@@ -575,7 +575,7 @@ class IBusEmojier : Gtk.ApplicationWindow { - if (lang == "en") { - bool has_variant = false; - foreach (unichar ch in EMOJI_VARIANT_LIST) { -- if (emoji.chr(-1, ch) != null) { -+ if (emoji.index_of_char(ch) >= 0) { - has_variant = true; - break; - } -@@ -782,15 +782,17 @@ class IBusEmojier : Gtk.ApplicationWindow { - private bool check_unicode_point() { - string annotation = m_entry.get_text(); - m_unicode_point = null; -- var buff = new GLib.StringBuilder(); -+ // Add "0x" because uint64.ascii_strtoull() is not accessible -+ // and need to use uint64.parse() -+ var buff = new GLib.StringBuilder("0x"); - var retval = new GLib.StringBuilder(); - for (int i = 0; i < annotation.char_count(); i++) { - unichar ch = annotation.get_char(i); - if (ch == 0) - return false; - if (ch.isspace()) { -- unichar code = (unichar)buff.str.to_ulong(null, 16); -- buff.erase(); -+ unichar code = (unichar)uint64.parse(buff.str); -+ buff.assign("0x"); - if (!code.validate()) - return false; - retval.append(code.to_string()); -@@ -800,7 +802,7 @@ class IBusEmojier : Gtk.ApplicationWindow { - return false; - buff.append_unichar(ch); - } -- unichar code = (unichar)buff.str.to_ulong(null, 16); -+ unichar code = (unichar)uint64.parse(buff.str); - if (!code.validate()) - return false; - retval.append(code.to_string()); -@@ -834,7 +836,7 @@ class IBusEmojier : Gtk.ApplicationWindow { - matched = true; - break; - case 2: -- if (key.str(annotation) != null) -+ if (key.index_of(annotation) >= 0) - matched = true; - break; - default: -@@ -1586,10 +1588,16 @@ class IBusEmojier : Gtk.ApplicationWindow { - public void present_centralize(Gdk.Event event) { - Gtk.Allocation allocation; - get_allocation(out allocation); -- Gdk.Screen screen = Gdk.Screen.get_default(); -- int monitor_num = screen.get_monitor_at_window(get_window()); - Gdk.Rectangle monitor_area; -+#if VALA_0_34 -+ Gdk.Display display = Gdk.Display.get_default(); -+ Gdk.Monitor monitor = display.get_monitor_at_window(this.get_window()); -+ monitor_area = monitor.get_geometry(); -+#else -+ Gdk.Screen screen = Gdk.Screen.get_default(); -+ int monitor_num = screen.get_monitor_at_window(this.get_window()); - screen.get_monitor_geometry(monitor_num, out monitor_area); -+#endif - int x = (monitor_area.x + monitor_area.width - allocation.width)/2; - int y = (monitor_area.y + monitor_area.height - - allocation.height)/2; -diff --git a/ui/gtk3/handle.vala b/ui/gtk3/handle.vala -index bef5e8ba..fc9164a0 100644 ---- a/ui/gtk3/handle.vala -+++ b/ui/gtk3/handle.vala -@@ -3,7 +3,7 @@ - * ibus - The Input Bus - * - * Copyright(c) 2011-2016 Peng Huang -- * Copyright(c) 2016 Takao Fujiwara -+ * Copyright(c) 2016-2017 Takao Fujiwara - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public -@@ -59,7 +59,6 @@ class Handle : Gtk.EventBox { - - public override void realize() { - base.realize(); -- // get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.FLEUR)); - } - - public override bool button_press_event(Gdk.EventButton event) { -@@ -138,7 +137,9 @@ class Handle : Gtk.EventBox { - m_move_begined = false; - m_press_pos.x = 0; - m_press_pos.y = 0; -- get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.LEFT_PTR)); -+ get_window().set_cursor(new Gdk.Cursor.for_display( -+ Gdk.Display.get_default(), -+ Gdk.CursorType.FLEUR)); - move_end(); - return true; - } -diff --git a/ui/gtk3/indicator.vala b/ui/gtk3/indicator.vala -index dac72b49..4d111a64 100644 ---- a/ui/gtk3/indicator.vala -+++ b/ui/gtk3/indicator.vala -@@ -2,7 +2,7 @@ - * - * ibus - The Input Bus - * -- * Copyright(c) 2015 Takao Fujiwara -+ * Copyright(c) 2015-2017 Takao Fujiwara - * Copyright(c) 2015 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or -@@ -97,6 +97,7 @@ class Indicator : IBus.Service - private int m_context_menu_y; - private int m_activate_menu_x; - private int m_activate_menu_y; -+ private Gdk.Window m_indicator_window; - - public Indicator(string id, - GLib.DBusConnection connection, -@@ -206,7 +207,8 @@ class Indicator : IBus.Service - GLib.Variant var_y = parameters.get_child_value(1); - m_context_menu_x = var_x.get_int32(); - m_context_menu_y = var_y.get_int32(); -- context_menu(2, 0); -+ Gdk.Window window = query_gdk_window(); -+ context_menu(m_context_menu_x, m_context_menu_y, window, 2, 0); - } - - private void _activate_menu_cb(GLib.DBusConnection connection, -@@ -216,7 +218,57 @@ class Indicator : IBus.Service - GLib.Variant var_y = parameters.get_child_value(1); - m_activate_menu_x = var_x.get_int32(); - m_activate_menu_y = var_y.get_int32(); -- activate(); -+ Gdk.Window window = query_gdk_window(); -+ activate(m_activate_menu_x, m_activate_menu_y, window); -+ } -+ -+ private Gdk.Window? query_gdk_window() { -+ if (m_indicator_window != null) -+ return m_indicator_window; -+ -+ Gdk.Display display = Gdk.Display.get_default(); -+ unowned X.Display xdisplay = -+ (display as Gdk.X11.Display).get_xdisplay(); -+ X.Window current = xdisplay.default_root_window(); -+ X.Window parent = 0; -+ X.Window child = 0; -+ int root_x, root_y, win_x, win_y; -+ uint mask = 0; -+ root_x = root_y = win_x = win_y = 0; -+ bool retval; -+ // Need XSetErrorHandler for BadWindow? -+ while ((retval = xdisplay.query_pointer(current, -+ out parent, out child, -+ out root_x, out root_y, -+ out win_x, out win_y, -+ out mask))) { -+ if (child == 0) -+ break; -+ current = child; -+ } -+ if (!retval) { -+ string format = -+ "XQueryPointer is failed: current: %x root: %x " + -+ "child: %x (%d, %d), (%d, %d), %u"; -+ string message = format.printf((uint)current, -+ (uint)xdisplay.default_root_window(), -+ (uint)child, -+ root_x, root_y, win_x, win_y, -+ mask); -+ warning("XQueryPointer is failed: %s", message); -+ return null; -+ } -+ if (current == xdisplay.default_root_window()) -+ warning("The query window is root window"); -+ m_indicator_window = Gdk.X11.Window.lookup_for_display( -+ display as Gdk.X11.Display, -+ current); -+ if (m_indicator_window != null) -+ return m_indicator_window; -+ m_indicator_window = new Gdk.X11.Window.foreign_for_display( -+ display as Gdk.X11.Display, -+ current); -+ return m_indicator_window; - } - - private GLib.Variant? _get_id(GLib.DBusConnection connection) { -@@ -479,7 +531,13 @@ class Indicator : IBus.Service - push_in = false; - } - -- public signal void context_menu(uint button, uint activate_time); -- public signal void activate(); -+ public signal void context_menu(int x, -+ int y, -+ Gdk.Window window, -+ uint button, -+ uint activate_time); -+ public signal void activate(int x, -+ int y, -+ Gdk.Window window); - public signal void registered_status_notifier_item(); - } -diff --git a/ui/gtk3/keybindingmanager.vala b/ui/gtk3/keybindingmanager.vala -index 49013b8d..c8b1e7f6 100644 ---- a/ui/gtk3/keybindingmanager.vala -+++ b/ui/gtk3/keybindingmanager.vala -@@ -18,7 +18,7 @@ public class KeybindingManager : GLib.Object { - - private static KeybindingManager m_instance = null; - -- public static const uint MODIFIER_FILTER = -+ public const uint MODIFIER_FILTER = - Gdk.ModifierType.MODIFIER_MASK & ~( - Gdk.ModifierType.LOCK_MASK | // Caps Lock - // Gdk.ModifierType.MOD1_MASK | // Alt -diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala -index bf43cbf9..629dadce 100644 ---- a/ui/gtk3/panel.vala -+++ b/ui/gtk3/panel.vala -@@ -267,6 +267,27 @@ class Panel : IBus.PanelService { - }); - } - -+ private void popup_menu_at_area_window(Gtk.Menu menu, -+ Gdk.Rectangle area, -+ Gdk.Window? window, -+ Gtk.MenuPositionFunc? func) { -+#if VALA_0_34 -+ Gdk.Gravity rect_anchor = Gdk.Gravity.SOUTH_WEST; -+ Gdk.Gravity menu_anchor = Gdk.Gravity.NORTH_WEST; -+ -+ // Gtk.Menu.popup() is now deprecated but -+ // Gtk.Menu.popup_at_rect() requires a Gdk.Window and -+ // Gtk.Menu.popup_at_rect() outputs a warning of -+ // "no trigger event for menu popup" -+ // for the foreigner QT window which is generated by -+ // Gdk.X11.Window.foreign_for_display. -+ // https://git.gnome.org/browse/gtk+/tree/gtk/gtkmenu.c?h=gtk-3-22#n2251 -+ menu.popup_at_rect(window, area, rect_anchor, menu_anchor, null); -+#else -+ menu.popup(null, null, func, 0, Gtk.get_current_event_time()); -+#endif -+ } -+ - #if INDICATOR - private bool is_kde() { - if (Environment.get_variable("XDG_CURRENT_DESKTOP") == "KDE") -@@ -276,6 +297,19 @@ class Panel : IBus.PanelService { - return false; - } - -+ private void popup_menu_at_pointer_window(Gtk.Menu menu, -+ int x, -+ int y, -+ Gdk.Window? window, -+ Gtk.MenuPositionFunc? func) { -+ int win_x = 0; -+ int win_y = 0; -+ window.get_origin(out win_x, out win_y); -+ Gdk.Rectangle area = { x - win_x, y - win_y, 1, 1 }; -+ // window is a bottom wide panel instead of status icon -+ popup_menu_at_area_window(menu, area, window, func); -+ } -+ - private void init_indicator() { - m_icon_type = IconType.INDICATOR; - GLib.Bus.get.begin(GLib.BusType.SESSION, null, (obj, res) => { -@@ -290,21 +324,17 @@ class Panel : IBus.PanelService { - m_indicator.set_status(Indicator.Status.ACTIVE); - state_changed(); - }); -- m_indicator.context_menu.connect((b, t) => { -- Gtk.Menu menu = create_context_menu(); -- menu.popup(null, -- null, -- m_indicator.position_context_menu, -- 0, -- Gtk.get_current_event_time()); -+ m_indicator.context_menu.connect((x, y, w, b, t) => { -+ popup_menu_at_pointer_window( -+ create_context_menu(), -+ x, y, w, -+ m_indicator.position_context_menu); - }); -- m_indicator.activate.connect(() => { -- Gtk.Menu menu = create_activate_menu(); -- menu.popup(null, -- null, -- m_indicator.position_activate_menu, -- 0, -- Gtk.get_current_event_time()); -+ m_indicator.activate.connect((x, y, w) => { -+ popup_menu_at_pointer_window( -+ create_activate_menu(), -+ x, y, w, -+ m_indicator.position_activate_menu); - }); - } catch (GLib.IOError e) { - warning("Failed to get the session bus: %s", e.message); -@@ -317,21 +347,47 @@ class Panel : IBus.PanelService { - m_status_icon = new Gtk.StatusIcon(); - m_status_icon.set_name("ibus-ui-gtk"); - m_status_icon.set_title(_("IBus Panel")); -+ -+ // Gdk.Window.get_width() is needed for the menu position -+ if (m_status_icon.get_size() > 0) -+ init_status_icon_menu(); -+ else -+ m_status_icon.notify["size"].connect(init_status_icon_menu); -+ } -+ -+ private void init_status_icon_menu() { -+ Gdk.Rectangle area = { 0, 0, 0, 0 }; -+ Gdk.Window? window = null; -+ Gtk.MenuPositionFunc? func = null; -+#if VALA_0_34 -+ window = Gdk.X11.Window.lookup_for_display( -+ Gdk.Display.get_default() as Gdk.X11.Display, -+ m_status_icon.get_x11_window_id()) as Gdk.Window; -+ if (window == null) { -+ warning("StatusIcon does not have GdkWindow"); -+ return; -+ } -+ Gtk.Orientation orient; -+ m_status_icon.get_geometry(null, out area, out orient); -+ int win_x = 0; -+ int win_y = 0; -+ window.get_origin(out win_x, out win_y); -+ // The (x, y) is converted by gdk_window_get_root_coords() -+ // in gdk_window_impl_move_to_rect() -+ area.x -= win_x; -+ area.y -= win_y; -+#else -+ func = m_status_icon.position_menu; -+#endif - m_status_icon.popup_menu.connect((b, t) => { -- Gtk.Menu menu = create_context_menu(); -- menu.popup(null, -- null, -- m_status_icon.position_menu, -- 0, -- Gtk.get_current_event_time()); -+ popup_menu_at_area_window( -+ create_context_menu(), -+ area, window, func); - }); - m_status_icon.activate.connect(() => { -- Gtk.Menu menu = create_activate_menu(); -- menu.popup(null, -- null, -- m_status_icon.position_menu, -- 0, -- Gtk.get_current_event_time()); -+ popup_menu_at_area_window( -+ create_activate_menu(), -+ area, window, func); - }); - m_status_icon.set_from_icon_name("ibus-keyboard"); - } -diff --git a/ui/gtk3/propertypanel.vala b/ui/gtk3/propertypanel.vala -index dd4342ec..857f8e20 100644 ---- a/ui/gtk3/propertypanel.vala -+++ b/ui/gtk3/propertypanel.vala -@@ -4,7 +4,7 @@ - * - * Copyright(c) 2013-2016 Red Hat, Inc. - * Copyright(c) 2013-2015 Peng Huang -- * Copyright(c) 2013-2016 Takao Fujiwara -+ * Copyright(c) 2013-2017 Takao Fujiwara - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public -@@ -330,8 +330,16 @@ public class PropertyPanel : Gtk.Box { - Gtk.Allocation allocation; - m_toplevel.get_allocation(out allocation); - -+ Gdk.Rectangle monitor_area; -+#if VALA_0_34 -+ // gdk_screen_get_monitor_workarea() no longer return the correct -+ // area from "_NET_WORKAREA" atom in GTK 3.22 -+ Gdk.Monitor monitor = Gdk.Display.get_default().get_monitor(0); -+ monitor_area = monitor.get_workarea(); -+#else - Gdk.Screen screen = Gdk.Screen.get_default(); -- Gdk.Rectangle monitor_area = screen.get_monitor_workarea(0); -+ monitor_area = screen.get_monitor_workarea(0); -+#endif - int monitor_right = monitor_area.x + monitor_area.width; - int monitor_bottom = monitor_area.y + monitor_area.height; - int x, y; -@@ -472,8 +480,15 @@ public class PropMenu : Gtk.Menu, IPropToolItem { - public new void popup(uint button, - uint32 activate_time, - Gtk.Widget widget) { -+#if VALA_0_34 -+ base.popup_at_widget(widget, -+ Gdk.Gravity.SOUTH_WEST, -+ Gdk.Gravity.NORTH_WEST, -+ null); -+#else - m_parent_button = widget; - base.popup(null, null, menu_position, button, activate_time); -+#endif - } - - public override void destroy() { -@@ -532,6 +547,7 @@ public class PropMenu : Gtk.Menu, IPropToolItem { - } - } - -+#if !VALA_0_34 - private void menu_position(Gtk.Menu menu, - out int x, - out int y, -@@ -580,6 +596,7 @@ public class PropMenu : Gtk.Menu, IPropToolItem { - - push_in = false; - } -+#endif - } - - public class PropToolButton : Gtk.ToolButton, IPropToolItem { -diff --git a/ui/gtk3/switcher.vala b/ui/gtk3/switcher.vala -index 269a68d4..0ce742a1 100644 ---- a/ui/gtk3/switcher.vala -+++ b/ui/gtk3/switcher.vala -@@ -157,6 +157,55 @@ class Switcher : Gtk.Window { - m_label.set_text(m_buttons[index].longname); - m_buttons[index].grab_focus(); - -+ // Avoid regressions. -+ if (m_popup_delay_time > 0) { -+ get_position(out m_root_x, out m_root_y); -+ // Pull the window from the screen so that the window gets -+ // the key press and release events but mouse does not select -+ // an IME unexpectedly. -+ move(-1000, -1000); -+ } -+ -+ show_all(); -+ -+ if (m_popup_delay_time > 0) { -+ // Restore the window position after m_popup_delay_time -+ m_popup_delay_time_id = GLib.Timeout.add(m_popup_delay_time, -+ () => { -+ restore_window_position("timeout"); -+ return false; -+ }); -+ } -+ -+ Gdk.Device pointer; -+#if VALA_0_34 -+ Gdk.Seat seat = event.get_seat(); -+ if (seat == null) { -+ var display = get_display(); -+ seat = display.get_default_seat(); -+ } -+ //keyboard = seat.get_keyboard(); -+ pointer = seat.get_pointer(); -+ -+ Gdk.GrabStatus status; -+ // Grab all keyboard events -+ status = seat.grab(get_window(), -+ Gdk.SeatCapabilities.KEYBOARD, -+ true, -+ null, -+ event, -+ null); -+ if (status != Gdk.GrabStatus.SUCCESS) -+ warning("Grab keyboard failed! status = %d", status); -+ status = seat.grab(get_window(), -+ Gdk.SeatCapabilities.POINTER, -+ true, -+ null, -+ event, -+ null); -+ if (status != Gdk.GrabStatus.SUCCESS) -+ warning("Grab pointer failed! status = %d", status); -+#else - Gdk.Device device = event.get_device(); - if (device == null) { - var display = get_display(); -@@ -174,7 +223,6 @@ class Switcher : Gtk.Window { - } - - Gdk.Device keyboard; -- Gdk.Device pointer; - if (device.get_source() == Gdk.InputSource.KEYBOARD) { - keyboard = device; - pointer = device.get_associated_device(); -@@ -183,26 +231,6 @@ class Switcher : Gtk.Window { - keyboard = device.get_associated_device(); - } - -- // Avoid regressions. -- if (m_popup_delay_time > 0) { -- get_position(out m_root_x, out m_root_y); -- // Pull the window from the screen so that the window gets -- // the key press and release events but mouse does not select -- // an IME unexpectedly. -- move(-1000, -1000); -- } -- -- show_all(); -- -- if (m_popup_delay_time > 0) { -- // Restore the window position after m_popup_delay_time -- m_popup_delay_time_id = GLib.Timeout.add(m_popup_delay_time, -- () => { -- restore_window_position("timeout"); -- return false; -- }); -- } -- - Gdk.GrabStatus status; - // Grab all keyboard events - status = keyboard.grab(get_window(), -@@ -224,6 +252,8 @@ class Switcher : Gtk.Window { - Gdk.CURRENT_TIME); - if (status != Gdk.GrabStatus.SUCCESS) - warning("Grab pointer failed! status = %d", status); -+#endif -+ - // Probably we can delete m_popup_delay_time in 1.6 - pointer.get_position_double(null, - out m_mouse_init_x, -@@ -235,8 +265,12 @@ class Switcher : Gtk.Window { - m_loop.run(); - m_loop = null; - -+#if VALA_0_34 -+ seat.ungrab(); -+#else - keyboard.ungrab(Gdk.CURRENT_TIME); - pointer.ungrab(Gdk.CURRENT_TIME); -+#endif - - hide(); - // Make sure the switcher is hidden before returning from this function. -@@ -319,13 +353,19 @@ class Switcher : Gtk.Window { - m_label.set_ellipsize(Pango.EllipsizeMode.END); - - Gdk.Display display = Gdk.Display.get_default(); -+ int screen_width = 0; -+#if VALA_0_34 -+ Gdk.Monitor monitor = display.get_monitor_at_window(this.get_window()); -+ Gdk.Rectangle area = monitor.get_geometry(); -+ screen_width = area.width; -+#else - Gdk.Screen screen = (display != null) ? - display.get_default_screen() : null; -- int screen_width = 0; - - if (screen != null) { - screen_width = screen.get_width(); - } -+#endif - - if (screen_width > 0 && max_label_width > (screen_width / 4)) { - max_label_width = screen_width / 4; --- -2.13.4 - -From 4a541639f50f05bf01b1b84792a7f4039b88c296 Mon Sep 17 00:00:00 2001 -From: fujiwarat -Date: Fri, 15 Sep 2017 17:49:57 +0900 -Subject: [PATCH] ui/gtk3: Fix to enable menu button on PropertyPanel - -Review URL: https://codereview.appspot.com/330720043 ---- - ui/gtk3/propertypanel.vala | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/ui/gtk3/propertypanel.vala b/ui/gtk3/propertypanel.vala -index 857f8e20..f5d9cff7 100644 ---- a/ui/gtk3/propertypanel.vala -+++ b/ui/gtk3/propertypanel.vala -@@ -84,6 +84,23 @@ public class PropertyPanel : Gtk.Box { - public void set_properties(IBus.PropList props) { - debug("set_properties()\n"); - -+ // When click PropMenuToolButton, the focus is changed and -+ // set_properties() is called here while the menu button is active. -+ // Ignore that case here not to remove items. -+ bool has_active = false; -+ foreach (var item in m_items) { -+ Type type = item.get_type(); -+ if (type == typeof(PropMenuToolButton) || -+ type == typeof(PropToggleToolButton)) { -+ if ((item as Gtk.ToggleToolButton).get_active()) { -+ has_active = true; -+ break; -+ } -+ } -+ } -+ if (has_active) -+ return; -+ - foreach (var item in m_items) - remove((item as Gtk.Widget)); - m_items = {}; --- -2.13.4 - -From f6a0100fcd123dc287b606d722b4d83a7d6b1ea7 Mon Sep 17 00:00:00 2001 -From: fujiwarat -Date: Thu, 21 Sep 2017 05:27:19 +0900 -Subject: [PATCH] ui/gtk3: Unset GDK_CORE_DEVICE_EVENTS - -Plasma deskop sets this variable and prevents Super+space, -and Ctrl-Shift-e when ibus-ui-gtk3 runs after the -desktop is launched. -Also fixed a SEGV in display.get_monitor_at_window() -Regression from rhbz#226465 ---- - ui/gtk3/application.vala | 6 ++++++ - ui/gtk3/switcher.vala | 3 ++- - 2 files changed, 8 insertions(+), 1 deletion(-) - -diff --git a/ui/gtk3/application.vala b/ui/gtk3/application.vala -index fa802721..770a32f2 100644 ---- a/ui/gtk3/application.vala -+++ b/ui/gtk3/application.vala -@@ -100,6 +100,12 @@ class Application { - } - - public static void main(string[] argv) { -+ // https://bugzilla.redhat.com/show_bug.cgi?id=1226465#c20 -+ // In /etc/xdg/plasma-workspace/env/gtk3_scrolling.sh -+ // Plasma deskop sets this variable and prevents Super+space, -+ // and Ctrl-Shift-e when ibus-ui-gtk3 runs after the -+ // desktop is launched. -+ GLib.Environment.unset_variable("GDK_CORE_DEVICE_EVENTS"); - // for Gdk.X11.get_default_xdisplay() - Gdk.set_allowed_backends("x11"); - -diff --git a/ui/gtk3/switcher.vala b/ui/gtk3/switcher.vala -index 0ce742a1..2a48c1f1 100644 ---- a/ui/gtk3/switcher.vala -+++ b/ui/gtk3/switcher.vala -@@ -355,7 +355,8 @@ class Switcher : Gtk.Window { - Gdk.Display display = Gdk.Display.get_default(); - int screen_width = 0; - #if VALA_0_34 -- Gdk.Monitor monitor = display.get_monitor_at_window(this.get_window()); -+ // display.get_monitor_at_window() is null because of unrealized window -+ Gdk.Monitor monitor = display.get_primary_monitor(); - Gdk.Rectangle area = monitor.get_geometry(); - screen_width = area.width; - #else --- -2.13.4 -