3818b86c29
- Fix scaling factor, mouse events on switcher, c-s-u on im-ibus, propertypanel position and menu - Add ibus-portal - Move ibus-emoji-dialog.vapi in the build - Fixed some SEGVs #1406699 #1432252
4309 lines
151 KiB
Diff
4309 lines
151 KiB
Diff
From e6bab7ab78c69d238a70a64e60963dd5a6711ffe Mon Sep 17 00:00:00 2001
|
|
From: Felix Yan <felixonmars@archlinux.org>
|
|
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 <felixonmars@archlinux.org>.
|
|
---
|
|
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 <takao.fujiwara1@gmail.com>
|
|
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 <takao.fujiwara1@gmail.com>
|
|
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 @@
|
|
<icon>ibus-keyboard</icon>
|
|
<rank>1</rank>
|
|
</engine>
|
|
+ <engine>
|
|
+ <name>xkb:my::msa</name>
|
|
+ <language>ms</language>
|
|
+ <license>GPL</license>
|
|
+ <author>Peng Huang <shawn.p.huang@gmail.com></author>
|
|
+ <layout>my</layout>
|
|
+ <longname>Malay (Jawi)</longname>
|
|
+ <description>Malay (Jawi)</description>
|
|
+ <icon>ibus-keyboard</icon>
|
|
+ <rank>1</rank>
|
|
+ </engine>
|
|
+ <engine>
|
|
+ <name>xkb:mn::mon</name>
|
|
+ <language>mn</language>
|
|
+ <license>GPL</license>
|
|
+ <author>Peng Huang <shawn.p.huang@gmail.com></author>
|
|
+ <layout>mn</layout>
|
|
+ <longname>Mongolian</longname>
|
|
+ <description>Mongolian</description>
|
|
+ <icon>ibus-keyboard</icon>
|
|
+ <rank>1</rank>
|
|
+ </engine>
|
|
</engines>
|
|
</component>
|
|
--
|
|
2.9.3
|
|
|
|
From 081d09f1a927f459dacda3bcc59a1678ca2f9a95 Mon Sep 17 00:00:00 2001
|
|
From: fujiwarat <takao.fujiwara1@gmail.com>
|
|
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 <takao.fujiwara1@gmail.com>
|
|
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 <config.h>
|
|
+#endif
|
|
+
|
|
#include <glib.h>
|
|
|
|
#ifdef HAVE_JSON_GLIB1
|
|
#include <json-glib/json-glib.h>
|
|
#endif
|
|
|
|
+#ifdef HAVE_LOCALE_H
|
|
+#include <locale.h>
|
|
+#endif
|
|
+
|
|
#include <string.h>
|
|
|
|
#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 <takao.fujiwara1@gmail.com>
|
|
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<string> annotations = data.get_annotations();
|
|
foreach (string annotation in annotations) {
|
|
bool has_emoji = false;
|
|
- unowned GLib.SList<string> hits =
|
|
- m_annotation_to_emojis_dict.lookup(annotation);
|
|
+ GLib.SList<string> 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<string> annotations = data.get_annotations();
|
|
+ GLib.SList<string> 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<string>? variants =
|
|
- m_emoji_to_emoji_variants_dict.lookup(base_emoji);
|
|
+ GLib.SList<string>? 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<string> hits =
|
|
- m_category_to_emojis_dict.lookup(category);
|
|
+ GLib.SList<string> 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 <takao.fujiwara1@gmail.com>
|
|
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 <shawn.p.huang@gmail.com>
|
|
+ * Copyright(c) 2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
@@ -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 <sfanxiang@gmail.com>
|
|
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 <sfanxiang@gmail.com>.
|
|
---
|
|
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 <mario.bodemann@gmail.com>
|
|
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 <mario.bodemann@gmail.com>.
|
|
---
|
|
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 <alexl@redhat.com>
|
|
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 <alexl@redhat.com>.
|
|
---
|
|
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 <shawn.p.huang@gmail.com>
|
|
+# Copyright (c) 2007-2013 Red Hat, Inc.
|
|
+#
|
|
+# This library is free software; you can redistribute it and/or
|
|
+# modify it under the terms of the GNU Lesser General Public
|
|
+# License as published by the Free Software Foundation; either
|
|
+# version 2.1 of the License, or (at your option) any later version.
|
|
+#
|
|
+# This library is distributed in the hope that it will be useful,
|
|
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+# Lesser General Public License for more details.
|
|
+#
|
|
+# You should have received a copy of the GNU Lesser General Public
|
|
+# License along with this library; if not, write to the Free Software
|
|
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
+# USA
|
|
+
|
|
+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 @@
|
|
+<?xml version="1.0"?>
|
|
+<!--
|
|
+ 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 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, see <http://www.gnu.org/licenses/>.
|
|
+
|
|
+ Author: Alexander Larsson <alexl@redhat.com>
|
|
+-->
|
|
+
|
|
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
|
|
+ <!--
|
|
+ org.freedesktop.IBus.Portal:
|
|
+ @short_description: Portal for ibus client access
|
|
+
|
|
+ This interface is a minimal interface to IBus that is safe to expose to
|
|
+ clients.
|
|
+ -->
|
|
+ <interface name="org.freedesktop.IBus.Portal">
|
|
+ <method name='CreateInputContext'>
|
|
+ <arg direction='in' type='s' name='client_name' />
|
|
+ <arg direction='out' type='o' name='object_path' />
|
|
+ </method>
|
|
+ </interface>
|
|
+
|
|
+ <!-- This is a copy of the interface in inputcontext.c, they should be shared.
|
|
+ We want this for the code generator so that we can be sure we verify all
|
|
+ caller types, etc.
|
|
+ -->
|
|
+ <interface name='org.freedesktop.IBus.InputContext'>
|
|
+ <method name='ProcessKeyEvent'>
|
|
+ <arg direction='in' type='u' name='keyval' />
|
|
+ <arg direction='in' type='u' name='keycode' />
|
|
+ <arg direction='in' type='u' name='state' />
|
|
+ <arg direction='out' type='b' name='handled' />
|
|
+ </method>
|
|
+ <method name='SetCursorLocation'>
|
|
+ <arg direction='in' type='i' name='x' />
|
|
+ <arg direction='in' type='i' name='y' />
|
|
+ <arg direction='in' type='i' name='w' />
|
|
+ <arg direction='in' type='i' name='h' />
|
|
+ </method>
|
|
+ <method name='SetCursorLocationRelative'>
|
|
+ <arg direction='in' type='i' name='x' />
|
|
+ <arg direction='in' type='i' name='y' />
|
|
+ <arg direction='in' type='i' name='w' />
|
|
+ <arg direction='in' type='i' name='h' />
|
|
+ </method>
|
|
+ <method name='ProcessHandWritingEvent'>
|
|
+ <arg direction='in' type='ad' name='coordinates' />
|
|
+ </method>
|
|
+ <method name='CancelHandWriting'>
|
|
+ <arg direction='in' type='u' name='n_strokes' />
|
|
+ </method>
|
|
+ <method name='FocusIn' />
|
|
+ <method name='FocusOut' />
|
|
+ <method name='Reset' />
|
|
+ <method name='SetCapabilities'>
|
|
+ <arg direction='in' type='u' name='caps' />
|
|
+ </method>
|
|
+ <method name='PropertyActivate'>
|
|
+ <arg direction='in' type='s' name='name' />
|
|
+ <arg direction='in' type='u' name='state' />
|
|
+ </method>
|
|
+ <method name='SetEngine'>
|
|
+ <arg direction='in' type='s' name='name' />
|
|
+ </method>
|
|
+ <method name='GetEngine'>
|
|
+ <arg direction='out' type='v' name='desc' />
|
|
+ </method>
|
|
+ <method name='SetSurroundingText'>
|
|
+ <arg direction='in' type='v' name='text' />
|
|
+ <arg direction='in' type='u' name='cursor_pos' />
|
|
+ <arg direction='in' type='u' name='anchor_pos' />
|
|
+ </method>
|
|
+
|
|
+ <signal name='CommitText'>
|
|
+ <arg type='v' name='text' />
|
|
+ </signal>
|
|
+ <signal name='ForwardKeyEvent'>
|
|
+ <arg type='u' name='keyval' />
|
|
+ <arg type='u' name='keycode' />
|
|
+ <arg type='u' name='state' />
|
|
+ </signal>
|
|
+ <signal name='UpdatePreeditText'>
|
|
+ <arg type='v' name='text' />
|
|
+ <arg type='u' name='cursor_pos' />
|
|
+ <arg type='b' name='visible' />
|
|
+ </signal>
|
|
+ <signal name='ShowPreeditText'/>
|
|
+ <signal name='HidePreeditText'/>
|
|
+ <signal name='UpdateAuxiliaryText'>
|
|
+ <arg type='v' name='text' />
|
|
+ <arg type='b' name='visible' />
|
|
+ </signal>
|
|
+ <signal name='ShowAuxiliaryText'/>
|
|
+ <signal name='HideAuxiliaryText'/>
|
|
+ <signal name='UpdateLookupTable'>
|
|
+ <arg type='v' name='table' />
|
|
+ <arg type='b' name='visible' />
|
|
+ </signal>
|
|
+ <signal name='ShowLookupTable'/>
|
|
+ <signal name='HideLookupTable'/>
|
|
+ <signal name='PageUpLookupTable'/>
|
|
+ <signal name='PageDownLookupTable'/>
|
|
+ <signal name='CursorUpLookupTable'/>
|
|
+ <signal name='CursorDownLookupTable'/>
|
|
+ <signal name='RegisterProperties'>
|
|
+ <arg type='v' name='props' />
|
|
+ </signal>
|
|
+ <signal name='UpdateProperty'>
|
|
+ <arg type='v' name='prop' />
|
|
+ </signal>
|
|
+
|
|
+ <property name='ContentType' type='(uu)' access='write' />
|
|
+ </interface>
|
|
+
|
|
+ <interface name='org.freedesktop.IBus.Service'>
|
|
+ <method name='Destroy' />
|
|
+ </interface>
|
|
+
|
|
+</node>
|
|
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 <config.h>
|
|
+#include <fcntl.h>
|
|
+#include <glib.h>
|
|
+#include <gio/gio.h>
|
|
+#include <ibus.h>
|
|
+#include <locale.h>
|
|
+#include <pwd.h>
|
|
+#include <signal.h>
|
|
+#include <stdlib.h>
|
|
+#include <sys/types.h>
|
|
+#include <sys/stat.h>
|
|
+#include <unistd.h>
|
|
+
|
|
+#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 <alexl@redhat.com>
|
|
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 <alexl@redhat.com>.
|
|
---
|
|
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 <alexl@redhat.com>
|
|
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 <alexl@redhat.com>.
|
|
---
|
|
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 <takao.fujiwara1@gmail.com>
|
|
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 <takao.fujiwara1@gmail.com>
|
|
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 <takao.fujiwara1@gmail.com>
|
|
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 <shawn.p.huang@gmail.com>
|
|
-# Copyright (c) 2007-2016 Red Hat, Inc.
|
|
+# Copyright (c) 2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
+# 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 <takao.fujiwara1@gmail.com>
|
|
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<string, string> m_xkb_languages =
|
|
new GLib.HashTable<string, string>(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 <takao.fujiwara1@gmail.com>
|
|
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 <shawn.p.huang@gmail.com>
|
|
- * Copyright (C) 2008-2013 Red Hat, Inc.
|
|
+ * Copyright (C) 2015-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
+ * 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 <shawn.p.huang@gmail.com>
|
|
- * Copyright (C) 2015-2016 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
- * Copyright (C) 2008-2016 Red Hat, Inc.
|
|
+ * Copyright (C) 2015-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
+ * 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 <takao.fujiwara1@gmail.com>
|
|
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 <takao.fujiwara1@gmail.com>
|
|
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 <shawn.p.huang@gmail.com>
|
|
- * Copyright(c) 2015-2016 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
+ * Copyright(c) 2015-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
@@ -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 <shawn.p.huang@gmail.com>
|
|
- * Copyright(c) 2016 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
+ * Copyright(c) 2016-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
@@ -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 <takao.fujiwara1@gmail.com>
|
|
+ * Copyright(c) 2015-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
* 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 <shawn.p.huang@gmail.com>
|
|
- * Copyright(c) 2013-2016 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
+ * Copyright(c) 2013-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
@@ -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 a7e78022b95329ca5782512872398a365503c410 Mon Sep 17 00:00:00 2001
|
|
From: fujiwarat <takao.fujiwara1@gmail.com>
|
|
Date: Thu, 14 Sep 2017 18:07:42 +0900
|
|
Subject: [PATCH 14/14] ui/gtk3: Fix to enable menu button on PropertyPanel
|
|
|
|
---
|
|
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
|
|
|