6a3b677013
- Implemented Ctrl-[f|b|n|p|h|e|a|u] for cursor operations on emoji dialog - Added XSetIOErrorHandler() for GNOME3 desktop
1771 lines
67 KiB
Diff
1771 lines
67 KiB
Diff
From 7e477d5e0ffe19b6c52558c5b37fdd9cb82c097a Mon Sep 17 00:00:00 2001
|
|
From: fujiwarat <takao.fujiwara1@gmail.com>
|
|
Date: Thu, 9 Mar 2017 11:31:21 +0900
|
|
Subject: [PATCH] tools: Fix `ibus emoji` SEGV when language is changed.
|
|
|
|
BUG=rhbz#1430290
|
|
|
|
Review URL: https://codereview.appspot.com/317410043
|
|
---
|
|
tools/main.vala | 3 +++
|
|
1 file changed, 3 insertions(+)
|
|
|
|
diff --git a/tools/main.vala b/tools/main.vala
|
|
index 73c6f57..fd9fd0e 100644
|
|
--- a/tools/main.vala
|
|
+++ b/tools/main.vala
|
|
@@ -353,6 +353,9 @@ int emoji_dialog(string[] argv) {
|
|
} else {
|
|
GLib.MainLoop loop = new GLib.MainLoop();
|
|
emojier.loaded_emoji_dict.connect(() => {
|
|
+ // The signal is called when the language is changed.
|
|
+ if (emojier.is_running())
|
|
+ return;
|
|
run_dialog(emojier);
|
|
loop.quit();
|
|
});
|
|
--
|
|
2.7.4
|
|
|
|
From 9dbea347050ae2ad79d1b53f2ad62a7a2cafadc6 Mon Sep 17 00:00:00 2001
|
|
From: fujiwarat <takao.fujiwara1@gmail.com>
|
|
Date: Thu, 9 Mar 2017 12:45:20 +0900
|
|
Subject: [PATCH] ui/gtk3: Get emoji colors from the theme
|
|
|
|
Get selected and normal text color from the theme.
|
|
Implement to activate an emoji with mouse motion.
|
|
Create back button on emoji language chooser dialog.
|
|
Set row_homogeneous on emoji table.
|
|
|
|
R=Shawn.P.Huang@gmail.com
|
|
|
|
Review URL: https://codereview.appspot.com/319470043
|
|
---
|
|
ui/gtk3/Makefile.am | 3 +
|
|
ui/gtk3/candidatearea.vala | 186 +++++++++++++++++++++++++------------------
|
|
ui/gtk3/emojier.vala | 192 ++++++++++++++++++++++++++++++++-------------
|
|
3 files changed, 251 insertions(+), 130 deletions(-)
|
|
|
|
diff --git a/ui/gtk3/Makefile.am b/ui/gtk3/Makefile.am
|
|
index d5ddc42..4e7fd1b 100644
|
|
--- a/ui/gtk3/Makefile.am
|
|
+++ b/ui/gtk3/Makefile.am
|
|
@@ -172,8 +172,11 @@ libibus_emoji_dialog_1_0_la_LDFLAGS = \
|
|
-version-info @LT_VERSION_INFO@ \
|
|
$(NULL)
|
|
libibus_emoji_dialog_1_0_la_SOURCES = \
|
|
+ candidatearea.c \
|
|
emojier.c \
|
|
iconwidget.c \
|
|
+ pango.c \
|
|
+ separator.c \
|
|
$(NULL)
|
|
|
|
-include $(INTROSPECTION_MAKEFILE)
|
|
diff --git a/ui/gtk3/candidatearea.vala b/ui/gtk3/candidatearea.vala
|
|
index a095e76..e162a96 100644
|
|
--- a/ui/gtk3/candidatearea.vala
|
|
+++ b/ui/gtk3/candidatearea.vala
|
|
@@ -21,6 +21,108 @@
|
|
* USA
|
|
*/
|
|
|
|
+class ThemedRGBA {
|
|
+ public Gdk.RGBA *normal_fg { get; set; }
|
|
+ public Gdk.RGBA *normal_bg { get; set; }
|
|
+ public Gdk.RGBA *selected_fg { get; set; }
|
|
+ public Gdk.RGBA *selected_bg { get; set; }
|
|
+
|
|
+ private Gtk.StyleContext m_style_context;
|
|
+
|
|
+ public ThemedRGBA(Gtk.Widget widget) {
|
|
+ this.normal_fg = null;
|
|
+ this.normal_bg = null;
|
|
+ this.selected_fg = null;
|
|
+ this.selected_bg = null;
|
|
+
|
|
+ /* Use the color of Gtk.TextView instead of Gtk.Label
|
|
+ * because the selected label "color" is not configured
|
|
+ * in "Adwaita" theme and the selected label "background-color"
|
|
+ * is not configured in "Maia" theme.
|
|
+ * https://github.com/ibus/ibus/issues/1871
|
|
+ */
|
|
+ Gtk.WidgetPath widget_path = new Gtk.WidgetPath();
|
|
+ widget_path.append_type(typeof(Gtk.TextView));
|
|
+ m_style_context = new Gtk.StyleContext();
|
|
+ m_style_context.set_path(widget_path);
|
|
+ m_style_context.add_class(Gtk.STYLE_CLASS_VIEW);
|
|
+
|
|
+ /* "-gtk-secondary-caret-color" value is different
|
|
+ * if the parent widget is set in "Menta" theme.
|
|
+ */
|
|
+ m_style_context.set_parent(widget.get_style_context());
|
|
+
|
|
+ get_rgba();
|
|
+
|
|
+ m_style_context.changed.connect(() => { get_rgba(); });
|
|
+ }
|
|
+
|
|
+ ~ThemedRGBA() {
|
|
+ reset_rgba();
|
|
+ }
|
|
+
|
|
+ private void reset_rgba() {
|
|
+ if (this.normal_fg != null) {
|
|
+ this.normal_fg.free();
|
|
+ this.normal_fg = null;
|
|
+ }
|
|
+ if (this.normal_bg != null) {
|
|
+ this.normal_bg.free();
|
|
+ this.normal_bg = null;
|
|
+ }
|
|
+ if (this.selected_fg != null) {
|
|
+ this.selected_fg.free();
|
|
+ this.selected_fg = null;
|
|
+ }
|
|
+ if (this.selected_bg != null) {
|
|
+ this.selected_bg.free();
|
|
+ this.selected_bg = null;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void get_rgba() {
|
|
+ reset_rgba();
|
|
+ Gdk.RGBA *normal_fg = null;
|
|
+ Gdk.RGBA *normal_bg = null;
|
|
+ Gdk.RGBA *selected_fg = null;
|
|
+ Gdk.RGBA *selected_bg = null;
|
|
+ m_style_context.get(Gtk.StateFlags.NORMAL,
|
|
+ "color",
|
|
+ out normal_fg);
|
|
+ m_style_context.get(Gtk.StateFlags.SELECTED,
|
|
+ "color",
|
|
+ out selected_fg);
|
|
+
|
|
+ string bg_prop = "background-color";
|
|
+ m_style_context.get(Gtk.StateFlags.NORMAL,
|
|
+ bg_prop,
|
|
+ out normal_bg);
|
|
+ m_style_context.get(Gtk.StateFlags.SELECTED,
|
|
+ bg_prop,
|
|
+ out selected_bg);
|
|
+ if (normal_bg.red == selected_bg.red &&
|
|
+ normal_bg.green == selected_bg.green &&
|
|
+ normal_bg.blue == selected_bg.blue &&
|
|
+ normal_bg.alpha == selected_bg.alpha) {
|
|
+ normal_bg.free();
|
|
+ normal_bg = null;
|
|
+ normal_bg.free();
|
|
+ normal_bg = null;
|
|
+ bg_prop = "-gtk-secondary-caret-color";
|
|
+ m_style_context.get(Gtk.StateFlags.NORMAL,
|
|
+ bg_prop,
|
|
+ out normal_bg);
|
|
+ m_style_context.get(Gtk.StateFlags.SELECTED,
|
|
+ bg_prop,
|
|
+ out selected_bg);
|
|
+ }
|
|
+ this.normal_fg = normal_fg;
|
|
+ this.normal_bg = normal_bg;
|
|
+ this.selected_fg = selected_fg;
|
|
+ this.selected_bg = selected_bg;
|
|
+ }
|
|
+}
|
|
+
|
|
class CandidateArea : Gtk.Box {
|
|
private bool m_vertical;
|
|
private Gtk.Label[] m_labels;
|
|
@@ -30,9 +132,7 @@ class CandidateArea : Gtk.Box {
|
|
private IBus.Text[] m_ibus_candidates;
|
|
private uint m_focus_candidate;
|
|
private bool m_show_cursor;
|
|
- Gtk.StyleContext m_style_context;
|
|
- private Gdk.RGBA *m_selected_fg_color = null;
|
|
- private Gdk.RGBA *m_selected_bg_color = null;
|
|
+ private ThemedRGBA m_rgba;
|
|
|
|
private const string LABELS[] = {
|
|
"1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.",
|
|
@@ -58,38 +158,7 @@ class CandidateArea : Gtk.Box {
|
|
public CandidateArea(bool vertical) {
|
|
GLib.Object();
|
|
set_vertical(vertical, true);
|
|
-
|
|
- /* Use the color of Gtk.TextView instead of Gtk.Label
|
|
- * because the selected label "color" is not configured
|
|
- * in "Adwaita" theme and the selected label "background-color"
|
|
- * is not configured in "Maia" theme.
|
|
- * https://github.com/ibus/ibus/issues/1871
|
|
- */
|
|
- Gtk.WidgetPath widget_path = new Gtk.WidgetPath();
|
|
- widget_path.append_type(typeof(Gtk.TextView));
|
|
- m_style_context = new Gtk.StyleContext();
|
|
- m_style_context.set_path(widget_path);
|
|
- m_style_context.add_class(Gtk.STYLE_CLASS_VIEW);
|
|
-
|
|
- /* "-gtk-secondary-caret-color" value is different
|
|
- * if the parent widget is set in "Menta" theme.
|
|
- */
|
|
- m_style_context.set_parent(get_style_context());
|
|
-
|
|
- get_selected_color();
|
|
-
|
|
- m_style_context.changed.connect(() => { get_selected_color(); });
|
|
- }
|
|
-
|
|
- ~CandidateArea() {
|
|
- if (m_selected_bg_color != null) {
|
|
- m_selected_bg_color.free();
|
|
- m_selected_bg_color = null;
|
|
- }
|
|
- if (m_selected_bg_color != null) {
|
|
- m_selected_bg_color.free();
|
|
- m_selected_bg_color = null;
|
|
- }
|
|
+ m_rgba = new ThemedRGBA(this);
|
|
}
|
|
|
|
public bool candidate_scrolled(Gdk.EventScroll event) {
|
|
@@ -150,17 +219,17 @@ class CandidateArea : Gtk.Box {
|
|
Pango.AttrList attrs = get_pango_attr_list_from_ibus_text(candidates[i]);
|
|
if (i == focus_candidate && show_cursor) {
|
|
Pango.Attribute pango_attr = Pango.attr_foreground_new(
|
|
- (uint16)(m_selected_fg_color.red * uint16.MAX),
|
|
- (uint16)(m_selected_fg_color.green * uint16.MAX),
|
|
- (uint16)(m_selected_fg_color.blue * uint16.MAX));
|
|
+ (uint16)(m_rgba.selected_fg.red * uint16.MAX),
|
|
+ (uint16)(m_rgba.selected_fg.green * uint16.MAX),
|
|
+ (uint16)(m_rgba.selected_fg.blue * uint16.MAX));
|
|
pango_attr.start_index = 0;
|
|
pango_attr.end_index = candidates[i].get_text().length;
|
|
attrs.insert((owned)pango_attr);
|
|
|
|
pango_attr = Pango.attr_background_new(
|
|
- (uint16)(m_selected_bg_color.red * uint16.MAX),
|
|
- (uint16)(m_selected_bg_color.green * uint16.MAX),
|
|
- (uint16)(m_selected_bg_color.blue * uint16.MAX));
|
|
+ (uint16)(m_rgba.selected_bg.red * uint16.MAX),
|
|
+ (uint16)(m_rgba.selected_bg.green * uint16.MAX),
|
|
+ (uint16)(m_rgba.selected_bg.blue * uint16.MAX));
|
|
pango_attr.start_index = 0;
|
|
pango_attr.end_index = candidates[i].get_text().length;
|
|
attrs.insert((owned)pango_attr);
|
|
@@ -181,41 +250,6 @@ class CandidateArea : Gtk.Box {
|
|
}
|
|
}
|
|
|
|
- private void get_selected_color() {
|
|
- if (m_selected_fg_color != null) {
|
|
- m_selected_fg_color.free();
|
|
- m_selected_fg_color = null;
|
|
- }
|
|
- m_style_context.get(Gtk.StateFlags.SELECTED,
|
|
- "color",
|
|
- out m_selected_fg_color);
|
|
-
|
|
- string bg_prop = "background-color";
|
|
- Gdk.RGBA *normal_color = null;
|
|
- if (m_selected_bg_color != null) {
|
|
- m_selected_bg_color.free();
|
|
- m_selected_bg_color = null;
|
|
- }
|
|
- m_style_context.get(Gtk.StateFlags.NORMAL,
|
|
- bg_prop,
|
|
- out normal_color);
|
|
- m_style_context.get(Gtk.StateFlags.SELECTED,
|
|
- bg_prop,
|
|
- out m_selected_bg_color);
|
|
- if (normal_color.red == m_selected_bg_color.red &&
|
|
- normal_color.green == m_selected_bg_color.green &&
|
|
- normal_color.blue == m_selected_bg_color.blue &&
|
|
- normal_color.alpha == m_selected_bg_color.alpha) {
|
|
- m_selected_bg_color.free();
|
|
- m_selected_bg_color = null;
|
|
- bg_prop = "-gtk-secondary-caret-color";
|
|
- m_style_context.get(Gtk.StateFlags.SELECTED,
|
|
- bg_prop,
|
|
- out m_selected_bg_color);
|
|
- }
|
|
- normal_color.free();
|
|
- }
|
|
-
|
|
private void recreate_ui() {
|
|
foreach (Gtk.Widget w in get_children()) {
|
|
w.destroy();
|
|
diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala
|
|
index 5496c4e..bc1eff4 100644
|
|
--- a/ui/gtk3/emojier.vala
|
|
+++ b/ui/gtk3/emojier.vala
|
|
@@ -72,12 +72,31 @@ class IBusEmojier : Gtk.Window {
|
|
private class EGrid : Gtk.Grid {
|
|
public EGrid() {
|
|
GLib.Object(
|
|
+ row_homogeneous : false,
|
|
vexpand : true,
|
|
halign : Gtk.Align.FILL,
|
|
valign : Gtk.Align.FILL
|
|
);
|
|
}
|
|
}
|
|
+ private class EWhiteLabel : Gtk.Label {
|
|
+ public EWhiteLabel(string text) {
|
|
+ GLib.Object(
|
|
+ name : "IBusEmojierWhiteLabel"
|
|
+ );
|
|
+ if (text != "")
|
|
+ set_label(text);
|
|
+ }
|
|
+ }
|
|
+ private class ESelectedLabel : Gtk.Label {
|
|
+ public ESelectedLabel(string text) {
|
|
+ GLib.Object(
|
|
+ name : "IBusEmojierSelectedLabel"
|
|
+ );
|
|
+ if (text != "")
|
|
+ set_label(text);
|
|
+ }
|
|
+ }
|
|
private class EPaddedLabel : Gtk.Box {
|
|
public EPaddedLabel(string text,
|
|
Gtk.Align align,
|
|
@@ -161,6 +180,7 @@ class IBusEmojier : Gtk.Window {
|
|
}
|
|
|
|
private const uint EMOJI_GRID_PAGE = 10;
|
|
+ private ThemedRGBA m_rgba;
|
|
private Gtk.Box m_vbox;
|
|
private ETitleLabel m_title;
|
|
private EEntry m_entry;
|
|
@@ -174,7 +194,8 @@ class IBusEmojier : Gtk.Window {
|
|
private GLib.MainLoop? m_loop;
|
|
private string? m_result;
|
|
private GLib.SList<string> m_lang_list;
|
|
- private string m_current_lang = "en";
|
|
+ private string m_current_lang_id = "en";
|
|
+ private string m_current_language = "English";
|
|
private string? m_unicode_point = null;
|
|
private bool m_candidate_panel_is_visible;
|
|
private GLib.HashTable<string, GLib.SList>?
|
|
@@ -189,11 +210,8 @@ class IBusEmojier : Gtk.Window {
|
|
private Gtk.Label[] m_candidates;
|
|
private string m_emoji_font = "Monospace 16";
|
|
private string[] m_favorites = {};
|
|
- // TODO: Get the selected color from CandidateArea
|
|
- private Gdk.RGBA m_selected_fg_color = Gdk.RGBA(){
|
|
- red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0 };
|
|
- private Gdk.RGBA m_selected_bg_color = Gdk.RGBA(){
|
|
- red = 0.300, green = 0.565, blue = 0.851, alpha = 1.0 };
|
|
+ private bool m_enter_notify_enable = true;
|
|
+ private uint m_entry_notify_show_id;
|
|
|
|
public signal void candidate_clicked(uint index, uint button, uint state);
|
|
public signal void loaded_emoji_dict();
|
|
@@ -220,7 +238,33 @@ class IBusEmojier : Gtk.Window {
|
|
warning("Could not open display.");
|
|
return;
|
|
}
|
|
- string data = "grid { background-color: #ffffff; }";
|
|
+ m_rgba = new ThemedRGBA(this);
|
|
+ uint bg_red = (uint)(m_rgba.normal_bg.red * 255);
|
|
+ uint bg_green = (uint)(m_rgba.normal_bg.green * 255);
|
|
+ uint bg_blue = (uint)(m_rgba.normal_bg.blue * 255);
|
|
+ double bg_alpha = m_rgba.normal_bg.alpha;
|
|
+ string data =
|
|
+ "#IBusEmojierWhiteLabel { background-color: " +
|
|
+ "rgba(%u, %u, %u, %lf); ".printf(
|
|
+ bg_red, bg_green, bg_blue, bg_alpha) +
|
|
+ "border-width: 4px; border-radius: 3px; } ";
|
|
+
|
|
+ uint fg_red = (uint)(m_rgba.selected_fg.red * 255);
|
|
+ uint fg_green = (uint)(m_rgba.selected_fg.green * 255);
|
|
+ uint fg_blue = (uint)(m_rgba.selected_fg.blue * 255);
|
|
+ double fg_alpha = m_rgba.selected_fg.alpha;
|
|
+ bg_red = (uint)(m_rgba.selected_bg.red * 255);
|
|
+ bg_green = (uint)(m_rgba.selected_bg.green * 255);
|
|
+ bg_blue = (uint)(m_rgba.selected_bg.blue * 255);
|
|
+ bg_alpha = m_rgba.selected_bg.alpha;
|
|
+ data += "#IBusEmojierSelectedLabel { color: " +
|
|
+ "rgba(%u, %u, %u, %lf); ".printf(
|
|
+ fg_red, fg_green, fg_blue, fg_alpha) +
|
|
+ "background-color: " +
|
|
+ "rgba(%u, %u, %u, %lf); ".printf(
|
|
+ bg_red, bg_green, bg_blue, bg_alpha) +
|
|
+ "border-width: 4px; border-radius: 3px; }";
|
|
+
|
|
Gtk.CssProvider css_provider = new Gtk.CssProvider();
|
|
try {
|
|
css_provider.load_from_data(data, -1);
|
|
@@ -317,6 +361,8 @@ class IBusEmojier : Gtk.Window {
|
|
lang_list.sort((a, b) => {
|
|
string a_lang = IBus.get_language_name(a);
|
|
string b_lang = IBus.get_language_name(b);
|
|
+ a_lang = "%s (%s)".printf(a_lang, a);
|
|
+ b_lang = "%s (%s)".printf(b_lang, b);
|
|
return GLib.strcmp(a_lang, b_lang);
|
|
});
|
|
return lang_list;
|
|
@@ -325,8 +371,8 @@ class IBusEmojier : Gtk.Window {
|
|
private void reload_emoji_dict() {
|
|
init_emoji_dict();
|
|
make_emoji_dict("en");
|
|
- if (m_current_lang != "en")
|
|
- make_emoji_dict(m_current_lang);
|
|
+ if (m_current_lang_id != "en")
|
|
+ make_emoji_dict(m_current_lang_id);
|
|
loaded_emoji_dict();
|
|
}
|
|
|
|
@@ -458,22 +504,50 @@ class IBusEmojier : Gtk.Window {
|
|
}
|
|
}
|
|
|
|
+ private void activated_language(EBoxRow row) {
|
|
+ m_category_active_index = 0;
|
|
+ if (m_current_lang_id != row.id) {
|
|
+ m_current_lang_id = row.id;
|
|
+ m_current_language = row.text;
|
|
+ reload_emoji_dict();
|
|
+ }
|
|
+ m_current_category_type = CategoryType.EMOJI;
|
|
+ show_category_list();
|
|
+ }
|
|
+
|
|
private void show_category_list() {
|
|
remove_all_children();
|
|
m_scrolled_window = new EScrolledWindow();
|
|
set_fixed_size();
|
|
- string language = IBus.get_language_name(m_current_lang);
|
|
- EPaddedLabel label = new EPaddedLabel(language, Gtk.Align.CENTER);
|
|
+ EPaddedLabel label;
|
|
+ if (m_current_category_type == CategoryType.EMOJI) {
|
|
+ label = new EPaddedLabel(m_current_language, Gtk.Align.CENTER);
|
|
+ } else if (m_current_category_type == CategoryType.LANG) {
|
|
+ label = new EPaddedLabel(m_current_language,
|
|
+ Gtk.Align.CENTER,
|
|
+ TravelDirection.BACKWARD);
|
|
+ } else {
|
|
+ label = new EPaddedLabel("", Gtk.Align.CENTER);
|
|
+ }
|
|
Gtk.Button button = new Gtk.Button();
|
|
button.add(label);
|
|
m_vbox.add(button);
|
|
button.show_all();
|
|
- button.button_press_event.connect((e) => {
|
|
- m_category_active_index = 0;
|
|
- m_current_category_type = CategoryType.LANG;
|
|
- show_category_list();
|
|
- return true;
|
|
- });
|
|
+ if (m_current_category_type == CategoryType.EMOJI) {
|
|
+ button.button_press_event.connect((e) => {
|
|
+ m_category_active_index = 0;
|
|
+ m_current_category_type = CategoryType.LANG;
|
|
+ show_category_list();
|
|
+ return true;
|
|
+ });
|
|
+ } else if (m_current_category_type == CategoryType.LANG) {
|
|
+ button.button_press_event.connect((e) => {
|
|
+ m_category_active_index = 0;
|
|
+ m_current_category_type = CategoryType.EMOJI;
|
|
+ show_category_list();
|
|
+ return true;
|
|
+ });
|
|
+ }
|
|
|
|
m_vbox.add(m_scrolled_window);
|
|
Gtk.Viewport viewport = new Gtk.Viewport(null, null);
|
|
@@ -523,21 +597,19 @@ class IBusEmojier : Gtk.Window {
|
|
}
|
|
} else if (m_current_category_type == CategoryType.LANG) {
|
|
m_list_box.row_activated.connect((box, gtkrow) => {
|
|
- m_category_active_index = 0;
|
|
- EBoxRow row = gtkrow as EBoxRow;
|
|
- if (m_current_lang != row.id) {
|
|
- m_current_lang = row.id;
|
|
- reload_emoji_dict();
|
|
- }
|
|
- m_current_category_type = CategoryType.EMOJI;
|
|
- show_category_list();
|
|
+ activated_language(gtkrow as EBoxRow);
|
|
});
|
|
uint n = 1;
|
|
+ string prev_language = null;
|
|
foreach (unowned string id in m_lang_list) {
|
|
- string selected_language = IBus.get_language_name(id);
|
|
- EBoxRow row = new EBoxRow("", id);
|
|
+ string language = IBus.get_language_name(id);
|
|
+ if (prev_language == language)
|
|
+ language = "%s (%s)".printf(language, id);
|
|
+ else
|
|
+ prev_language = language;
|
|
+ EBoxRow row = new EBoxRow(language, id);
|
|
EPaddedLabel widget =
|
|
- new EPaddedLabel(selected_language, Gtk.Align.CENTER);
|
|
+ new EPaddedLabel(language, Gtk.Align.CENTER);
|
|
row.add(widget);
|
|
m_list_box.add(row);
|
|
if (n++ == m_category_active_index)
|
|
@@ -573,27 +645,6 @@ class IBusEmojier : Gtk.Window {
|
|
show_candidate_panel();
|
|
}
|
|
|
|
- private void label_set_active_color(Gtk.Label label) {
|
|
- unowned string text = label.get_text();
|
|
- Pango.AttrList attrs = new Pango.AttrList();
|
|
- Pango.Attribute pango_attr = Pango.attr_foreground_new(
|
|
- (uint16)(m_selected_fg_color.red * uint16.MAX),
|
|
- (uint16)(m_selected_fg_color.green * uint16.MAX),
|
|
- (uint16)(m_selected_fg_color.blue * uint16.MAX));
|
|
- pango_attr.start_index = 0;
|
|
- pango_attr.end_index = text.char_count();
|
|
- attrs.insert((owned)pango_attr);
|
|
-
|
|
- pango_attr = Pango.attr_background_new(
|
|
- (uint16)(m_selected_bg_color.red * uint16.MAX),
|
|
- (uint16)(m_selected_bg_color.green * uint16.MAX),
|
|
- (uint16)(m_selected_bg_color.blue * uint16.MAX));
|
|
- pango_attr.start_index = 0;
|
|
- pango_attr.end_index = text.char_count();
|
|
- attrs.insert((owned)pango_attr);
|
|
- label.set_attributes(attrs);
|
|
- }
|
|
-
|
|
private void show_arrow_buttons() {
|
|
Gtk.Button next_button = new Gtk.Button();
|
|
next_button.clicked.connect(() => {
|
|
@@ -709,10 +760,17 @@ class IBusEmojier : Gtk.Window {
|
|
});
|
|
}
|
|
EGrid grid = new EGrid();
|
|
+ grid.set_row_spacing(5);
|
|
+ grid.set_column_spacing(5);
|
|
+ grid.set_border_width(2);
|
|
int n = 0;
|
|
for (uint i = page_start_pos; i < page_end_pos; i++) {
|
|
IBus.Text candidate = m_lookup_table.get_candidate(i);
|
|
- Gtk.Label label = new Gtk.Label(candidate.text);
|
|
+ Gtk.Label label;
|
|
+ if (i == cursor)
|
|
+ label = new ESelectedLabel(candidate.text) as Gtk.Label;
|
|
+ else
|
|
+ label = new EWhiteLabel(candidate.text) as Gtk.Label;
|
|
string emoji_font = m_emoji_font;
|
|
if (candidate.text.char_count() > 2) {
|
|
Pango.FontDescription font_desc =
|
|
@@ -726,9 +784,6 @@ class IBusEmojier : Gtk.Window {
|
|
label.set_markup(markup);
|
|
label.set_halign(Gtk.Align.FILL);
|
|
label.set_valign(Gtk.Align.FILL);
|
|
- if (i == cursor) {
|
|
- label_set_active_color(label);
|
|
- }
|
|
Gtk.EventBox candidate_ebox = new Gtk.EventBox();
|
|
candidate_ebox.add(label);
|
|
// Make a copy of i to workaround a bug in vala.
|
|
@@ -738,6 +793,23 @@ class IBusEmojier : Gtk.Window {
|
|
candidate_clicked(index, e.button, e.state);
|
|
return true;
|
|
});
|
|
+ // m_enter_notify_enable is added because
|
|
+ // enter_notify_event conflicts with keyboard operations.
|
|
+ if (m_enter_notify_enable) {
|
|
+ candidate_ebox.enter_notify_event.connect((e) => {
|
|
+ m_lookup_table.set_cursor_pos(index);
|
|
+ if (m_entry_notify_show_id > 0) {
|
|
+ GLib.Source.remove(m_entry_notify_show_id);
|
|
+ }
|
|
+ // If timeout is not added, memory leak happens and
|
|
+ // button_press_event signal does not work above.
|
|
+ m_entry_notify_show_id = GLib.Timeout.add(100, () => {
|
|
+ show_candidate_panel();
|
|
+ return false;
|
|
+ });
|
|
+ return true;
|
|
+ });
|
|
+ }
|
|
grid.attach(candidate_ebox,
|
|
n % (int)EMOJI_GRID_PAGE, n / (int)EMOJI_GRID_PAGE,
|
|
1, 1);
|
|
@@ -797,6 +869,7 @@ class IBusEmojier : Gtk.Window {
|
|
}
|
|
|
|
private void hide_candidate_panel() {
|
|
+ m_enter_notify_enable = true;
|
|
m_candidate_panel_is_visible = false;
|
|
if (m_loop.is_running())
|
|
show_category_list();
|
|
@@ -841,6 +914,7 @@ class IBusEmojier : Gtk.Window {
|
|
}
|
|
|
|
private void candidate_panel_cursor_down() {
|
|
+ m_enter_notify_enable = false;
|
|
uint ncandidates = m_lookup_table.get_number_of_candidates();
|
|
uint cursor = m_lookup_table.get_cursor_pos();
|
|
if ((cursor + EMOJI_GRID_PAGE) < ncandidates) {
|
|
@@ -854,6 +928,7 @@ class IBusEmojier : Gtk.Window {
|
|
}
|
|
|
|
private void candidate_panel_cursor_up() {
|
|
+ m_enter_notify_enable = false;
|
|
int ncandidates = (int)m_lookup_table.get_number_of_candidates();
|
|
int cursor = (int)m_lookup_table.get_cursor_pos();
|
|
int highest_pos =
|
|
@@ -891,6 +966,7 @@ class IBusEmojier : Gtk.Window {
|
|
m_input_context_path = input_context_path;
|
|
m_candidate_panel_is_visible = false;
|
|
m_result = null;
|
|
+ m_enter_notify_enable = true;
|
|
|
|
/* Let gtk recalculate the window size. */
|
|
resize(1, 1);
|
|
@@ -1011,7 +1087,10 @@ class IBusEmojier : Gtk.Window {
|
|
} else if (m_category_active_index > 0) {
|
|
Gtk.ListBoxRow gtkrow = m_list_box.get_selected_row();
|
|
EBoxRow row = gtkrow as EBoxRow;
|
|
- show_emoji_for_category(row);
|
|
+ if (m_current_category_type == CategoryType.EMOJI)
|
|
+ show_emoji_for_category(row);
|
|
+ else if (m_current_category_type == CategoryType.LANG)
|
|
+ activated_language(row);
|
|
}
|
|
return true;
|
|
case Gdk.Key.BackSpace:
|
|
@@ -1026,6 +1105,7 @@ class IBusEmojier : Gtk.Window {
|
|
break;
|
|
}
|
|
if (m_candidate_panel_is_visible) {
|
|
+ m_enter_notify_enable = false;
|
|
m_lookup_table.cursor_down();
|
|
show_candidate_panel();
|
|
}
|
|
@@ -1035,6 +1115,7 @@ class IBusEmojier : Gtk.Window {
|
|
return true;
|
|
case Gdk.Key.Right:
|
|
if (m_candidate_panel_is_visible) {
|
|
+ m_enter_notify_enable = false;
|
|
m_lookup_table.cursor_down();
|
|
show_candidate_panel();
|
|
return true;
|
|
@@ -1042,6 +1123,7 @@ class IBusEmojier : Gtk.Window {
|
|
break;
|
|
case Gdk.Key.Left:
|
|
if (m_candidate_panel_is_visible) {
|
|
+ m_enter_notify_enable = false;
|
|
m_lookup_table.cursor_up();
|
|
show_candidate_panel();
|
|
return true;
|
|
@@ -1061,6 +1143,7 @@ class IBusEmojier : Gtk.Window {
|
|
return true;
|
|
case Gdk.Key.Page_Down:
|
|
if (m_candidate_panel_is_visible) {
|
|
+ m_enter_notify_enable = false;
|
|
m_lookup_table.page_down();
|
|
show_candidate_panel();
|
|
return true;
|
|
@@ -1068,6 +1151,7 @@ class IBusEmojier : Gtk.Window {
|
|
break;
|
|
case Gdk.Key.Page_Up:
|
|
if (m_candidate_panel_is_visible) {
|
|
+ m_enter_notify_enable = false;
|
|
m_lookup_table.page_up();
|
|
show_candidate_panel();
|
|
return true;
|
|
--
|
|
2.7.4
|
|
|
|
From 31ed31e5303c3946f53b035a63d76f5c1e3cd84a Mon Sep 17 00:00:00 2001
|
|
From: fujiwarat <takao.fujiwara1@gmail.com>
|
|
Date: Mon, 13 Mar 2017 11:43:09 +0900
|
|
Subject: [PATCH] src: Fix ibus_emoji_dict_load()
|
|
|
|
R=Shawn.P.Huang@gmail.com
|
|
|
|
Review URL: https://codereview.appspot.com/320350043
|
|
---
|
|
configure.ac | 3 ++-
|
|
src/emoji-parser.c | 6 ++++--
|
|
src/ibusemoji.c | 6 +++---
|
|
3 files changed, 9 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/configure.ac b/configure.ac
|
|
index 027c027..369485c 100644
|
|
--- a/configure.ac
|
|
+++ b/configure.ac
|
|
@@ -620,7 +620,8 @@ fi
|
|
|
|
AC_ARG_WITH(emoji-json-file,
|
|
AS_HELP_STRING([--with-emoji-json-file[=DIR/emoji.json]],
|
|
- [Set emoji.json. (default: "/usr/lib/node_modules/emojione/emoji.json")]),
|
|
+ [Set emoji.json. (default: "/usr/lib/node_modules/emojione/emoji.json")
|
|
+ You can get emoji.json with "npm install -g emojione".]),
|
|
EMOJI_JSON_FILE=$with_emoji_json_file,
|
|
EMOJI_JSON_FILE="/usr/lib/node_modules/emojione/emoji.json"
|
|
)
|
|
diff --git a/src/emoji-parser.c b/src/emoji-parser.c
|
|
index c5af42c..5965309 100644
|
|
--- a/src/emoji-parser.c
|
|
+++ b/src/emoji-parser.c
|
|
@@ -1,7 +1,7 @@
|
|
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
|
|
/* vim:set et sts=4: */
|
|
/* ibus - The Input Bus
|
|
- * Copyright (C) 2016 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
+ * Copyright (C) 2016-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
* Copyright (C) 2016 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
@@ -20,9 +20,11 @@
|
|
* USA
|
|
*/
|
|
|
|
-/* Convert ../data/annotations/en.xml and
|
|
+/* Convert /usr/share/unicode/cldr/common/annotations/*.xml and
|
|
* /usr/lib/node_modules/emojione/emoji.json
|
|
* to the dictionary file which look up the Emoji from the annotation.
|
|
+ * Get *.xml from https://github.com/fujiwarat/cldr-emoji-annotation
|
|
+ * or http://www.unicode.org/repos/cldr/trunk/common/annotations .
|
|
* Get emoji.json with 'npm install -g emojione'.
|
|
* en.xml is used for the Unicode annotations and emoji.json is used
|
|
* for the aliases_ascii, e.g. ":)", and category, e.g. "people".
|
|
diff --git a/src/ibusemoji.c b/src/ibusemoji.c
|
|
index 8d88704..996d136 100644
|
|
--- a/src/ibusemoji.c
|
|
+++ b/src/ibusemoji.c
|
|
@@ -431,10 +431,10 @@ ibus_emoji_dict_load (const gchar *path)
|
|
GHashTable *dict = g_hash_table_new_full (g_str_hash,
|
|
g_str_equal,
|
|
g_free,
|
|
- free_dict_words);
|
|
+ g_object_unref);
|
|
|
|
for (l = list; l; l = l->next) {
|
|
- IBusEmojiData *data = list->data;
|
|
+ IBusEmojiData *data = l->data;
|
|
if (!IBUS_IS_EMOJI_DATA (data)) {
|
|
g_warning ("Your dict format is no longer supported.\n"
|
|
"Need to create the dictionaries again.");
|
|
@@ -442,7 +442,7 @@ ibus_emoji_dict_load (const gchar *path)
|
|
}
|
|
g_hash_table_insert (dict,
|
|
g_strdup (ibus_emoji_data_get_emoji (data)),
|
|
- data);
|
|
+ g_object_ref_sink (data));
|
|
}
|
|
|
|
g_slist_free (list);
|
|
--
|
|
2.9.3
|
|
|
|
From c580845167b54ccab76d8b72bdc797ef8d64d554 Mon Sep 17 00:00:00 2001
|
|
From: fujiwarat <takao.fujiwara1@gmail.com>
|
|
Date: Mon, 13 Mar 2017 11:58:06 +0900
|
|
Subject: [PATCH] ui/gtk3: Fix emoji text entry cusor position
|
|
|
|
Focus on emoji text entry by default
|
|
Remove internal text buffer and use Gtk.Entry buffer instead.
|
|
Implement cusor left, right, home, end on emoji annotation preedit.
|
|
|
|
Review URL: https://codereview.appspot.com/313710043
|
|
---
|
|
ui/gtk3/emojier.vala | 104 +++++++++++++++++++++++++++++++++------------------
|
|
1 file changed, 68 insertions(+), 36 deletions(-)
|
|
|
|
diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala
|
|
index bc1eff4..8cecea8 100644
|
|
--- a/ui/gtk3/emojier.vala
|
|
+++ b/ui/gtk3/emojier.vala
|
|
@@ -75,7 +75,10 @@ class IBusEmojier : Gtk.Window {
|
|
row_homogeneous : false,
|
|
vexpand : true,
|
|
halign : Gtk.Align.FILL,
|
|
- valign : Gtk.Align.FILL
|
|
+ valign : Gtk.Align.FILL,
|
|
+ row_spacing : 5,
|
|
+ column_spacing : 5,
|
|
+ border_width : 2
|
|
);
|
|
}
|
|
}
|
|
@@ -190,7 +193,6 @@ class IBusEmojier : Gtk.Window {
|
|
private CategoryType m_current_category_type = CategoryType.EMOJI;
|
|
private bool m_is_running = false;
|
|
private string m_input_context_path = "";
|
|
- private GLib.StringBuilder m_buffer_string;
|
|
private GLib.MainLoop? m_loop;
|
|
private string? m_result;
|
|
private GLib.SList<string> m_lang_list;
|
|
@@ -288,11 +290,9 @@ class IBusEmojier : Gtk.Window {
|
|
m_entry.set_placeholder_text(_("Type annotation or choose emoji"));
|
|
m_vbox.add(m_entry);
|
|
m_entry.changed.connect(() => {
|
|
- m_buffer_string.assign(m_entry.get_text());
|
|
- update_cadidate_window();
|
|
+ update_candidate_window();
|
|
});
|
|
m_entry.icon_release.connect((icon_pos, event) => {
|
|
- m_buffer_string.erase();
|
|
hide_candidate_panel();
|
|
});
|
|
|
|
@@ -303,7 +303,6 @@ class IBusEmojier : Gtk.Window {
|
|
Atk.Object obj = m_entry.get_accessible();
|
|
obj.set_role (Atk.Role.STATUSBAR);
|
|
|
|
- m_buffer_string = new StringBuilder();
|
|
grab_focus();
|
|
|
|
// The constructor of IBus.LookupTable does not support more than
|
|
@@ -680,11 +679,16 @@ class IBusEmojier : Gtk.Window {
|
|
buttons_hbox.show_all();
|
|
}
|
|
|
|
- private bool check_unicode_point(bool check_xdigit_only) {
|
|
- m_unicode_point = null;
|
|
+ private bool check_unicode_point(string? annotation=null) {
|
|
+ bool check_xdigit_only = true;
|
|
+ if (annotation == null) {
|
|
+ annotation = m_entry.get_text();
|
|
+ m_unicode_point = null;
|
|
+ check_xdigit_only = false;
|
|
+ }
|
|
GLib.StringBuilder buff = new GLib.StringBuilder();
|
|
- for (int i = 0; i < m_buffer_string.str.char_count(); i++) {
|
|
- unichar ch = m_buffer_string.str.get_char(i);
|
|
+ for (int i = 0; i < annotation.char_count(); i++) {
|
|
+ unichar ch = annotation.get_char(i);
|
|
if (ch == 0)
|
|
return false;
|
|
if (!ch.isxdigit())
|
|
@@ -704,7 +708,7 @@ class IBusEmojier : Gtk.Window {
|
|
return true;
|
|
}
|
|
|
|
- public void update_cadidate_window() {
|
|
+ public void update_candidate_window() {
|
|
string annotation = m_entry.get_text();
|
|
if (annotation.length == 0) {
|
|
hide_candidate_panel();
|
|
@@ -716,7 +720,7 @@ class IBusEmojier : Gtk.Window {
|
|
return;
|
|
}
|
|
// Call check_unicode_point() to get m_unicode_point
|
|
- check_unicode_point(false);
|
|
+ check_unicode_point();
|
|
unowned GLib.SList<string>? emojis =
|
|
m_annotation_to_emojis_dict.lookup(annotation);
|
|
if (emojis == null && m_unicode_point == null) {
|
|
@@ -725,7 +729,7 @@ class IBusEmojier : Gtk.Window {
|
|
}
|
|
m_lookup_table.clear();
|
|
// Call check_unicode_point() to update m_lookup_table
|
|
- check_unicode_point(false);
|
|
+ check_unicode_point();
|
|
foreach (unowned string emoji in emojis) {
|
|
IBus.Text text = new IBus.Text.from_string(emoji);
|
|
m_lookup_table.append_candidate(text);
|
|
@@ -760,9 +764,6 @@ class IBusEmojier : Gtk.Window {
|
|
});
|
|
}
|
|
EGrid grid = new EGrid();
|
|
- grid.set_row_spacing(5);
|
|
- grid.set_column_spacing(5);
|
|
- grid.set_border_width(2);
|
|
int n = 0;
|
|
for (uint i = page_start_pos; i < page_end_pos; i++) {
|
|
IBus.Text candidate = m_lookup_table.get_candidate(i);
|
|
@@ -878,14 +879,11 @@ class IBusEmojier : Gtk.Window {
|
|
private bool if_in_range_of_lookup(uint keyval) {
|
|
if (!m_candidate_panel_is_visible)
|
|
return false;
|
|
- string backup_annotation = m_buffer_string.str.dup();
|
|
+ StringBuilder buffer_string = new StringBuilder(m_entry.get_text());
|
|
unichar ch = IBus.keyval_to_unicode (keyval);
|
|
- m_buffer_string.append_unichar(ch);
|
|
- if (check_unicode_point(true)) {
|
|
- m_buffer_string.assign(backup_annotation);
|
|
+ buffer_string.append_unichar(ch);
|
|
+ if (check_unicode_point(buffer_string.str))
|
|
return false;
|
|
- }
|
|
- m_buffer_string.assign(backup_annotation);
|
|
if (keyval < Gdk.Key.@0 || keyval > Gdk.Key.@9)
|
|
return false;
|
|
if (keyval == Gdk.Key.@0)
|
|
@@ -958,6 +956,18 @@ class IBusEmojier : Gtk.Window {
|
|
show_category_list();
|
|
}
|
|
|
|
+ private void entry_enter_keyval(uint keyval) {
|
|
+ unichar ch = IBus.keyval_to_unicode(keyval);
|
|
+ if (!ch.isgraph())
|
|
+ return;
|
|
+ string str = ch.to_string();
|
|
+
|
|
+ // what gtk_entry_commit_cb() do
|
|
+ int pos = m_entry.get_position();
|
|
+ m_entry.insert_text(str, -1, ref pos);
|
|
+ m_entry.set_position(pos);
|
|
+ }
|
|
+
|
|
public string run(Gdk.Event event,
|
|
string input_context_path) {
|
|
assert (m_loop == null);
|
|
@@ -972,7 +982,7 @@ class IBusEmojier : Gtk.Window {
|
|
resize(1, 1);
|
|
|
|
m_entry.set_text("");
|
|
- m_buffer_string.erase();
|
|
+ m_entry.grab_focus();
|
|
|
|
Gdk.Device device = event.get_device();
|
|
if (device == null) {
|
|
@@ -1070,12 +1080,12 @@ class IBusEmojier : Gtk.Window {
|
|
m_current_category_type = CategoryType.EMOJI;
|
|
show_candidate_panel();
|
|
return true;
|
|
- } else if (m_buffer_string.str.length == 0) {
|
|
+ } else if (m_entry.get_text().length == 0) {
|
|
m_loop.quit();
|
|
hide_candidate_panel();
|
|
return true;
|
|
}
|
|
- m_buffer_string.erase();
|
|
+ m_entry.delete_text(0, -1);
|
|
break;
|
|
case Gdk.Key.Return:
|
|
if (m_candidate_panel_is_visible) {
|
|
@@ -1094,14 +1104,14 @@ class IBusEmojier : Gtk.Window {
|
|
}
|
|
return true;
|
|
case Gdk.Key.BackSpace:
|
|
- if (m_buffer_string.len > 0)
|
|
- m_buffer_string.erase(m_buffer_string.len - 1);
|
|
+ if (m_entry.get_text().len() > 0) {
|
|
+ GLib.Signal.emit_by_name(m_entry, "backspace");
|
|
+ }
|
|
break;
|
|
case Gdk.Key.space:
|
|
case Gdk.Key.KP_Space:
|
|
if ((modifiers & Gdk.ModifierType.SHIFT_MASK) != 0) {
|
|
- unichar ch = IBus.keyval_to_unicode (keyval);
|
|
- m_buffer_string.append_unichar(ch);
|
|
+ entry_enter_keyval(keyval);
|
|
break;
|
|
}
|
|
if (m_candidate_panel_is_visible) {
|
|
@@ -1120,6 +1130,12 @@ class IBusEmojier : Gtk.Window {
|
|
show_candidate_panel();
|
|
return true;
|
|
}
|
|
+ if (m_entry.get_text().len() > 0) {
|
|
+ GLib.Signal.emit_by_name(m_entry, "move-cursor",
|
|
+ Gtk.MovementStep.VISUAL_POSITIONS,
|
|
+ 1, false);
|
|
+ return true;
|
|
+ }
|
|
break;
|
|
case Gdk.Key.Left:
|
|
if (m_candidate_panel_is_visible) {
|
|
@@ -1128,6 +1144,12 @@ class IBusEmojier : Gtk.Window {
|
|
show_candidate_panel();
|
|
return true;
|
|
}
|
|
+ if (m_entry.get_text().len() > 0) {
|
|
+ GLib.Signal.emit_by_name(m_entry, "move-cursor",
|
|
+ Gtk.MovementStep.VISUAL_POSITIONS,
|
|
+ -1, false);
|
|
+ return true;
|
|
+ }
|
|
break;
|
|
case Gdk.Key.Down:
|
|
if (m_candidate_panel_is_visible)
|
|
@@ -1157,17 +1179,27 @@ class IBusEmojier : Gtk.Window {
|
|
return true;
|
|
}
|
|
break;
|
|
- default:
|
|
- unichar ch = IBus.keyval_to_unicode(keyval);
|
|
- if (!ch.isgraph())
|
|
+ case Gdk.Key.Home:
|
|
+ if (m_entry.get_text().len() > 0) {
|
|
+ GLib.Signal.emit_by_name(m_entry, "move-cursor",
|
|
+ Gtk.MovementStep.DISPLAY_LINE_ENDS,
|
|
+ -1, false);
|
|
+ return true;
|
|
+ }
|
|
+ break;
|
|
+ case Gdk.Key.End:
|
|
+ if (m_entry.get_text().len() > 0) {
|
|
+ GLib.Signal.emit_by_name(m_entry, "move-cursor",
|
|
+ Gtk.MovementStep.DISPLAY_LINE_ENDS,
|
|
+ 1, false);
|
|
return true;
|
|
- m_buffer_string.append_unichar(ch);
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ entry_enter_keyval(keyval);
|
|
break;
|
|
}
|
|
|
|
- string annotation = m_buffer_string.str;
|
|
- m_entry.set_text(annotation);
|
|
-
|
|
return true;
|
|
}
|
|
|
|
--
|
|
2.9.3
|
|
|
|
From fbe3de1789c73a8a175a451b2a6b967f5d3c6514 Mon Sep 17 00:00:00 2001
|
|
From: fujiwarat <takao.fujiwara1@gmail.com>
|
|
Date: Mon, 13 Mar 2017 12:08:21 +0900
|
|
Subject: [PATCH] src: Update emoji-parser to treat tts as emoji
|
|
description
|
|
|
|
unicode annotation xml files have a 'tts' attribute and seem
|
|
it is used as the emoji descriptions instead of emoji annotations.
|
|
This can show the translated descriptions.
|
|
|
|
R=Shawn.P.Huang@gmail.com
|
|
|
|
Review URL: https://codereview.appspot.com/319480043
|
|
---
|
|
src/emoji-parser.c | 26 +++++++++++++++++++-------
|
|
src/ibusemoji.c | 16 +++++++++++++---
|
|
src/ibusemoji.h | 11 +++++++++++
|
|
ui/gtk3/emojier.vala | 17 ++++++++++++++---
|
|
4 files changed, 57 insertions(+), 13 deletions(-)
|
|
|
|
diff --git a/src/emoji-parser.c b/src/emoji-parser.c
|
|
index 5965309..8ff04f1 100644
|
|
--- a/src/emoji-parser.c
|
|
+++ b/src/emoji-parser.c
|
|
@@ -43,6 +43,7 @@ struct _EmojiData {
|
|
GSList *annotations;
|
|
gboolean is_annotation;
|
|
gchar *description;
|
|
+ gboolean is_tts;
|
|
gchar *category;
|
|
GSList *list;
|
|
};
|
|
@@ -97,6 +98,8 @@ update_emoji_list (EmojiData *data)
|
|
(GCopyFunc) g_strdup,
|
|
NULL));
|
|
}
|
|
+ if (data->description)
|
|
+ ibus_emoji_data_set_description (emoji, data->description);
|
|
} else {
|
|
IBusEmojiData *emoji =
|
|
ibus_emoji_data_new ("emoji",
|
|
@@ -149,13 +152,12 @@ unicode_annotations_start_element_cb (GMarkupParseContext *context,
|
|
data->emoji = g_strdup (value);
|
|
}
|
|
}
|
|
- else if (g_strcmp0 (attribute, "tts") == 0) {
|
|
- GSList *duplicated = g_slist_find_custom (data->annotations,
|
|
- value,
|
|
- (GCompareFunc) g_strcmp0);
|
|
- if (duplicated == NULL) {
|
|
- data->annotations = g_slist_prepend (data->annotations,
|
|
- g_strdup (value));
|
|
+ /* tts seems 'text to speach' and it would be a description
|
|
+ * instead of annotation.
|
|
+ */
|
|
+ else if (g_strcmp0 (attribute, "type") == 0) {
|
|
+ if (g_strcmp0 (value, "tts") == 0) {
|
|
+ data->is_tts = TRUE;
|
|
}
|
|
}
|
|
}
|
|
@@ -177,6 +179,7 @@ unicode_annotations_end_element_cb (GMarkupParseContext *context,
|
|
|
|
update_emoji_list (data);
|
|
data->is_annotation = FALSE;
|
|
+ data->is_tts = FALSE;
|
|
}
|
|
|
|
void
|
|
@@ -194,6 +197,15 @@ unicode_annotations_text_cb (GMarkupParseContext *context,
|
|
g_assert (data != NULL);
|
|
if (!data->is_annotation)
|
|
return;
|
|
+ if (data->is_tts) {
|
|
+ if (data->description) {
|
|
+ g_warning ("Duplicated 'tts' is found: %s: %s",
|
|
+ data->description, text);
|
|
+ g_clear_pointer (&data->description, g_free);
|
|
+ }
|
|
+ data->description = g_strdup (text);
|
|
+ return;
|
|
+ }
|
|
annotations = g_strsplit (text, " | ", -1);
|
|
for (i = 0; (annotation = annotations[i]) != NULL; i++) {
|
|
GSList *duplicated = g_slist_find_custom (data->annotations,
|
|
diff --git a/src/ibusemoji.c b/src/ibusemoji.c
|
|
index 996d136..c61cd70 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 (1)
|
|
+#define IBUS_EMOJI_DATA_VERSION (2)
|
|
|
|
enum {
|
|
PROP_0 = 0,
|
|
@@ -128,7 +128,7 @@ ibus_emoji_data_class_init (IBusEmojiDataClass *class)
|
|
"emoji description",
|
|
"The emoji description",
|
|
"",
|
|
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
|
+ G_PARAM_READWRITE));
|
|
|
|
/**
|
|
* IBusEmojiData:category:
|
|
@@ -352,6 +352,16 @@ ibus_emoji_data_get_description (IBusEmojiData *emoji)
|
|
return emoji->priv->description;
|
|
}
|
|
|
|
+void
|
|
+ibus_emoji_data_set_description (IBusEmojiData *emoji,
|
|
+ const gchar *description)
|
|
+{
|
|
+ g_return_if_fail (IBUS_IS_EMOJI_DATA (emoji));
|
|
+
|
|
+ g_free (emoji->priv->description);
|
|
+ emoji->priv->description = g_strdup (description);
|
|
+}
|
|
+
|
|
const gchar *
|
|
ibus_emoji_data_get_category (IBusEmojiData *emoji)
|
|
{
|
|
@@ -541,7 +551,7 @@ ibus_emoji_data_load (const gchar *path)
|
|
goto out_load_cache;
|
|
}
|
|
|
|
- if (version != IBUS_EMOJI_DATA_VERSION) {
|
|
+ if (version > IBUS_EMOJI_DATA_VERSION) {
|
|
g_warning ("cache version is different: %u != %u",
|
|
version, IBUS_EMOJI_DATA_VERSION);
|
|
goto out_load_cache;
|
|
diff --git a/src/ibusemoji.h b/src/ibusemoji.h
|
|
index 3fd09a9..eb24fdd 100644
|
|
--- a/src/ibusemoji.h
|
|
+++ b/src/ibusemoji.h
|
|
@@ -134,6 +134,17 @@ void ibus_emoji_data_set_annotations (IBusEmojiData *emoji,
|
|
const gchar * ibus_emoji_data_get_description (IBusEmojiData *emoji);
|
|
|
|
/**
|
|
+ * ibus_emoji_data_set_description:
|
|
+ * @emoji : An #IBusEmojiData
|
|
+ * @description: An emoji description
|
|
+ *
|
|
+ * Sets the description in #IBusEmojiData.
|
|
+ */
|
|
+void ibus_emoji_data_set_description (IBusEmojiData *emoji,
|
|
+ const gchar *description);
|
|
+
|
|
+
|
|
+/**
|
|
* ibus_emoji_data_get_category:
|
|
* @emoji : An #IBusEmojiData
|
|
*
|
|
diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala
|
|
index 8cecea8..5e126e9 100644
|
|
--- a/ui/gtk3/emojier.vala
|
|
+++ b/ui/gtk3/emojier.vala
|
|
@@ -370,8 +370,14 @@ class IBusEmojier : Gtk.Window {
|
|
private void reload_emoji_dict() {
|
|
init_emoji_dict();
|
|
make_emoji_dict("en");
|
|
- if (m_current_lang_id != "en")
|
|
+ if (m_current_lang_id != "en") {
|
|
+ var lang_ids = m_current_lang_id.split("_");
|
|
+ if (lang_ids.length > 1) {
|
|
+ string sub_id = lang_ids[0];
|
|
+ make_emoji_dict(sub_id);
|
|
+ }
|
|
make_emoji_dict(m_current_lang_id);
|
|
+ }
|
|
loaded_emoji_dict();
|
|
}
|
|
|
|
@@ -393,8 +399,8 @@ class IBusEmojier : Gtk.Window {
|
|
if (emoji_list == null)
|
|
return;
|
|
foreach (IBus.EmojiData data in emoji_list) {
|
|
- update_annotation_to_emojis_dict(data);
|
|
update_emoji_to_data_dict(data, lang);
|
|
+ update_annotation_to_emojis_dict(data);
|
|
update_category_to_emojis_dict(data, lang);
|
|
}
|
|
GLib.List<unowned string> annotations =
|
|
@@ -434,11 +440,16 @@ class IBusEmojier : Gtk.Window {
|
|
unowned IBus.EmojiData? en_data =
|
|
m_emoji_to_data_dict.lookup(emoji);
|
|
if (en_data == null) {
|
|
- warning("No IBusEmojiData for English: %s".printf(emoji));
|
|
m_emoji_to_data_dict.insert(emoji, data);
|
|
return;
|
|
}
|
|
+ string trans_description = data.get_description();
|
|
+ en_data.set_description(trans_description);
|
|
unowned GLib.SList<string> annotations = data.get_annotations();
|
|
+ var words = trans_description.split(" ");
|
|
+ // If the description has less than 3 words, add it to annotations
|
|
+ if (words.length < 3)
|
|
+ annotations.append(trans_description);
|
|
unowned GLib.SList<string> en_annotations
|
|
= en_data.get_annotations();
|
|
foreach (string annotation in en_annotations) {
|
|
--
|
|
2.9.3
|
|
|
|
From ab6c38c192cdf22356cbf254b98fb5b3d9d9a680 Mon Sep 17 00:00:00 2001
|
|
From: fujiwarat <takao.fujiwara1@gmail.com>
|
|
Date: Wed, 15 Mar 2017 11:48:24 +0900
|
|
Subject: [PATCH] client/x11: Add XSetIOErrorHandler() for GNOME3 desktop
|
|
|
|
When log into GNOME3 desktop immediately after the system is booted,
|
|
ibus-daemon is sometimes alive but ibus-x11 is dead after log out
|
|
the session. Because gdk_x_io_error() is called as the callback of
|
|
XSetIOErrorHandler() in gtk/gdk/x11/gdkmain-x11.c in ibus-x11.
|
|
Now I assume the callback is called in logout.
|
|
|
|
BUG=https://github.com/ibus/ibus/issues/1907
|
|
|
|
Review URL: https://codereview.appspot.com/319490043
|
|
---
|
|
client/x11/main.c | 16 ++++++++++++++++
|
|
1 file changed, 16 insertions(+)
|
|
|
|
diff --git a/client/x11/main.c b/client/x11/main.c
|
|
index a717a2c..159f430 100644
|
|
--- a/client/x11/main.c
|
|
+++ b/client/x11/main.c
|
|
@@ -2,6 +2,7 @@
|
|
/* vim:set et sts=4: */
|
|
/* ibus
|
|
* Copyright (C) 2007-2015 Peng Huang <shawn.p.huang@gmail.com>
|
|
+ * Copyright (C) 2015-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
* Copyright (C) 2007-2015 Red Hat, Inc.
|
|
*
|
|
* main.c:
|
|
@@ -1131,6 +1132,20 @@ _xerror_handler (Display *dpy, XErrorEvent *e)
|
|
return 1;
|
|
}
|
|
|
|
+/* When log into GNOME3 desktop immediately after the system is booted,
|
|
+ * ibus-daemon is sometimes alive but ibus-x11 is dead after log out
|
|
+ * the session. Because gdk_x_io_error() is called as the callback of
|
|
+ * XSetIOErrorHandler() in gtk/gdk/x11/gdkmain-x11.c in ibus-x11.
|
|
+ * Now I assume the callback is called in logout.
|
|
+ */
|
|
+static int
|
|
+_xerror_io_handler (Display *dpy)
|
|
+{
|
|
+ if (_kill_daemon)
|
|
+ _atexit_cb ();
|
|
+ return 0;
|
|
+}
|
|
+
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
@@ -1146,6 +1161,7 @@ main (int argc, char **argv)
|
|
|
|
gtk_init (&argc, &argv);
|
|
XSetErrorHandler (_xerror_handler);
|
|
+ XSetIOErrorHandler (_xerror_io_handler);
|
|
|
|
while (1) {
|
|
static struct option long_options [] = {
|
|
--
|
|
2.9.3
|
|
|
|
From 58f6140f427815adc947a5bb5c7dea4f3e315ae8 Mon Sep 17 00:00:00 2001
|
|
From: fujiwarat <takao.fujiwara1@gmail.com>
|
|
Date: Wed, 15 Mar 2017 11:52:39 +0900
|
|
Subject: [PATCH] ui/gtk3: Implement shortcut keys on emoji dialog
|
|
|
|
- Implement Ctrl-f, Ctrl-b, Ctrl-n, Ctrl-p, Ctrl-h, Ctrh-e for
|
|
cursor movements; forward, back, next, previous, head, end
|
|
on emoji grid.
|
|
- Implement Ctrl-a and Shift+arrow for text selection on emoji annotation.
|
|
- Implement Ctrl-u to delete text on emoji annotation.
|
|
- Implement to delete a selected text on emoji annotation.
|
|
- Change to show page indices to candidate indices on emoji.
|
|
- Sorted emoji categories.
|
|
- Added timeout of m_enter_notify_enable = false to bring back mouse.
|
|
|
|
R=Shawn.P.Huang@gmail.com
|
|
|
|
Review URL: https://codereview.appspot.com/315700043
|
|
---
|
|
ui/gtk3/emojier.vala | 311 +++++++++++++++++++++++++++++++++++----------------
|
|
1 file changed, 215 insertions(+), 96 deletions(-)
|
|
|
|
diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala
|
|
index 5e126e9..7da96c7 100644
|
|
--- a/ui/gtk3/emojier.vala
|
|
+++ b/ui/gtk3/emojier.vala
|
|
@@ -214,6 +214,7 @@ class IBusEmojier : Gtk.Window {
|
|
private string[] m_favorites = {};
|
|
private bool m_enter_notify_enable = true;
|
|
private uint m_entry_notify_show_id;
|
|
+ private uint m_entry_notify_disable_id;
|
|
|
|
public signal void candidate_clicked(uint index, uint button, uint state);
|
|
public signal void loaded_emoji_dict();
|
|
@@ -525,6 +526,18 @@ class IBusEmojier : Gtk.Window {
|
|
show_category_list();
|
|
}
|
|
|
|
+ private string get_title_string(string orig) {
|
|
+ StringBuilder buff = new StringBuilder();
|
|
+ for (int i = 0; i < orig.char_count(); i++) {
|
|
+ unichar ch = orig.get_char(i);
|
|
+ if (i == 0)
|
|
+ buff.append_unichar(ch.toupper());
|
|
+ else
|
|
+ buff.append_unichar(ch);
|
|
+ }
|
|
+ return buff.str;
|
|
+ }
|
|
+
|
|
private void show_category_list() {
|
|
remove_all_children();
|
|
m_scrolled_window = new EScrolledWindow();
|
|
@@ -586,19 +599,14 @@ class IBusEmojier : Gtk.Window {
|
|
}
|
|
GLib.List<unowned string> categories =
|
|
m_category_to_emojis_dict.get_keys();
|
|
+ categories.sort((a, b) => {
|
|
+ return GLib.strcmp(_(a), _(b));
|
|
+ });
|
|
foreach (unowned string category in categories) {
|
|
EBoxRow row = new EBoxRow(category);
|
|
string locale_category = _(category);
|
|
- StringBuilder capital_category = new StringBuilder();
|
|
- for (int i = 0; i < locale_category.char_count(); i++) {
|
|
- unichar ch = locale_category.get_char(i);
|
|
- if (i == 0)
|
|
- capital_category.append_unichar(ch.toupper());
|
|
- else
|
|
- capital_category.append_unichar(ch);
|
|
- }
|
|
EPaddedLabel widget =
|
|
- new EPaddedLabel(capital_category.str,
|
|
+ new EPaddedLabel(get_title_string(locale_category),
|
|
Gtk.Align.CENTER);
|
|
row.add(widget);
|
|
m_list_box.add(row);
|
|
@@ -650,7 +658,7 @@ class IBusEmojier : Gtk.Window {
|
|
IBus.Text text = new IBus.Text.from_string(emoji);
|
|
m_lookup_table.append_candidate(text);
|
|
}
|
|
- m_backward = row.text;
|
|
+ m_backward = get_title_string(row.text);
|
|
}
|
|
show_candidate_panel();
|
|
}
|
|
@@ -759,9 +767,7 @@ class IBusEmojier : Gtk.Window {
|
|
uint page_end_pos = uint.min(page_start_pos + page_size, ncandidates);
|
|
if (m_backward != null) {
|
|
string backward_desc =
|
|
- "%s (%u / %u)".printf(m_backward,
|
|
- cursor / page_size + 1,
|
|
- ncandidates / page_size + 1);
|
|
+ "%s (%u / %u)".printf(m_backward, cursor, ncandidates - 1);
|
|
EPaddedLabel label = new EPaddedLabel(backward_desc,
|
|
Gtk.Align.CENTER,
|
|
TravelDirection.BACKWARD);
|
|
@@ -805,23 +811,23 @@ class IBusEmojier : Gtk.Window {
|
|
candidate_clicked(index, e.button, e.state);
|
|
return true;
|
|
});
|
|
- // m_enter_notify_enable is added because
|
|
- // enter_notify_event conflicts with keyboard operations.
|
|
- if (m_enter_notify_enable) {
|
|
- candidate_ebox.enter_notify_event.connect((e) => {
|
|
- m_lookup_table.set_cursor_pos(index);
|
|
- if (m_entry_notify_show_id > 0) {
|
|
+ candidate_ebox.enter_notify_event.connect((e) => {
|
|
+ // m_enter_notify_enable is added because
|
|
+ // enter_notify_event conflicts with keyboard operations.
|
|
+ if (!m_enter_notify_enable)
|
|
+ return true;
|
|
+ m_lookup_table.set_cursor_pos(index);
|
|
+ if (m_entry_notify_show_id > 0) {
|
|
GLib.Source.remove(m_entry_notify_show_id);
|
|
- }
|
|
- // If timeout is not added, memory leak happens and
|
|
- // button_press_event signal does not work above.
|
|
- m_entry_notify_show_id = GLib.Timeout.add(100, () => {
|
|
+ }
|
|
+ // If timeout is not added, memory leak happens and
|
|
+ // button_press_event signal does not work above.
|
|
+ m_entry_notify_show_id = GLib.Timeout.add(100, () => {
|
|
show_candidate_panel();
|
|
return false;
|
|
- });
|
|
- return true;
|
|
});
|
|
- }
|
|
+ return true;
|
|
+ });
|
|
grid.attach(candidate_ebox,
|
|
n % (int)EMOJI_GRID_PAGE, n / (int)EMOJI_GRID_PAGE,
|
|
1, 1);
|
|
@@ -844,16 +850,23 @@ class IBusEmojier : Gtk.Window {
|
|
widget.show_all();
|
|
return;
|
|
}
|
|
- unowned IBus.EmojiData data =
|
|
+ unowned IBus.EmojiData? data =
|
|
m_emoji_to_data_dict.lookup(candidate.text);
|
|
- unowned string description = data.get_description();
|
|
- if (description != "") {
|
|
+ if (data == null) {
|
|
+ // TODO: Provide a description for the favorite emojis.
|
|
EPaddedLabel widget = new EPaddedLabel(
|
|
- _("Description: %s").printf(description),
|
|
+ _("Description: %s").printf(_("None")),
|
|
Gtk.Align.START);
|
|
m_vbox.add(widget);
|
|
widget.show_all();
|
|
+ return;
|
|
}
|
|
+ unowned string description = data.get_description();
|
|
+ EPaddedLabel desc_widget = new EPaddedLabel(
|
|
+ _("Description: %s").printf(description),
|
|
+ Gtk.Align.START);
|
|
+ m_vbox.add(desc_widget);
|
|
+ desc_widget.show_all();
|
|
unowned GLib.SList<unowned string>? annotations =
|
|
data.get_annotations();
|
|
GLib.StringBuilder buff = new GLib.StringBuilder();
|
|
@@ -922,8 +935,21 @@ class IBusEmojier : Gtk.Window {
|
|
m_result = text.text;
|
|
}
|
|
|
|
- private void candidate_panel_cursor_down() {
|
|
+ private void enter_notify_disable_with_timer() {
|
|
+ // Enable keyboard operation and disable mouse operation.
|
|
m_enter_notify_enable = false;
|
|
+ if (m_entry_notify_disable_id > 0) {
|
|
+ GLib.Source.remove(m_entry_notify_disable_id);
|
|
+ }
|
|
+ // Bring back the mouse operation after a timeout.
|
|
+ m_entry_notify_show_id = GLib.Timeout.add(100, () => {
|
|
+ m_enter_notify_enable = true;
|
|
+ return false;
|
|
+ });
|
|
+ }
|
|
+
|
|
+ private void candidate_panel_cursor_down() {
|
|
+ enter_notify_disable_with_timer();
|
|
uint ncandidates = m_lookup_table.get_number_of_candidates();
|
|
uint cursor = m_lookup_table.get_cursor_pos();
|
|
if ((cursor + EMOJI_GRID_PAGE) < ncandidates) {
|
|
@@ -937,11 +963,11 @@ class IBusEmojier : Gtk.Window {
|
|
}
|
|
|
|
private void candidate_panel_cursor_up() {
|
|
- m_enter_notify_enable = false;
|
|
+ enter_notify_disable_with_timer();
|
|
int ncandidates = (int)m_lookup_table.get_number_of_candidates();
|
|
int cursor = (int)m_lookup_table.get_cursor_pos();
|
|
int highest_pos =
|
|
- (ncandidates / (int)EMOJI_GRID_PAGE * (int)EMOJI_GRID_PAGE)
|
|
+ ((ncandidates - 1)/ (int)EMOJI_GRID_PAGE * (int)EMOJI_GRID_PAGE)
|
|
+ (cursor % (int)EMOJI_GRID_PAGE);
|
|
if ((cursor - (int)EMOJI_GRID_PAGE) >= 0) {
|
|
m_lookup_table.set_cursor_pos(cursor - (int)EMOJI_GRID_PAGE);
|
|
@@ -967,13 +993,119 @@ class IBusEmojier : Gtk.Window {
|
|
show_category_list();
|
|
}
|
|
|
|
+ private bool key_press_cursor_horizontal(uint keyval,
|
|
+ uint modifiers) {
|
|
+ assert (keyval == Gdk.Key.Left || keyval == Gdk.Key.Right);
|
|
+
|
|
+ if (m_candidate_panel_is_visible) {
|
|
+ enter_notify_disable_with_timer();
|
|
+ if (keyval == Gdk.Key.Left)
|
|
+ m_lookup_table.cursor_up();
|
|
+ else if (keyval == Gdk.Key.Right)
|
|
+ m_lookup_table.cursor_down();
|
|
+ show_candidate_panel();
|
|
+ } else if (m_entry.get_text().len() > 0) {
|
|
+ int step = 0;
|
|
+ if (keyval == Gdk.Key.Left)
|
|
+ step = -1;
|
|
+ else if (keyval == Gdk.Key.Right)
|
|
+ step = 1;
|
|
+ GLib.Signal.emit_by_name(
|
|
+ m_entry, "move-cursor",
|
|
+ Gtk.MovementStep.VISUAL_POSITIONS,
|
|
+ step,
|
|
+ (modifiers & Gdk.ModifierType.SHIFT_MASK) != 0
|
|
+ ? true : false);
|
|
+ } else {
|
|
+ // For Gdk.Key.f and Gdk.Key.b
|
|
+ if (keyval == Gdk.Key.Left)
|
|
+ keyval = Gdk.Key.Up;
|
|
+ else if (keyval == Gdk.Key.Right)
|
|
+ keyval = Gdk.Key.Down;
|
|
+ category_list_cursor_move(keyval);
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ private bool key_press_cursor_vertical(uint keyval) {
|
|
+ assert (keyval == Gdk.Key.Down || keyval == Gdk.Key.Up);
|
|
+
|
|
+ if (m_candidate_panel_is_visible) {
|
|
+ if (keyval == Gdk.Key.Down)
|
|
+ candidate_panel_cursor_down();
|
|
+ else if (keyval == Gdk.Key.Up)
|
|
+ candidate_panel_cursor_up();
|
|
+ } else {
|
|
+ category_list_cursor_move(keyval);
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ private bool key_press_cursor_home_end(uint keyval,
|
|
+ uint modifiers) {
|
|
+ assert (keyval == Gdk.Key.Home || keyval == Gdk.Key.End);
|
|
+
|
|
+ if (m_candidate_panel_is_visible) {
|
|
+ enter_notify_disable_with_timer();
|
|
+ if (keyval == Gdk.Key.Home) {
|
|
+ m_lookup_table.set_cursor_pos(0);
|
|
+ } else if (keyval == Gdk.Key.End) {
|
|
+ uint ncandidates = m_lookup_table.get_number_of_candidates();
|
|
+ m_lookup_table.set_cursor_pos(ncandidates - 1);
|
|
+ }
|
|
+ show_candidate_panel();
|
|
+ return true;
|
|
+ }
|
|
+ if (m_entry.get_text().len() > 0) {
|
|
+ int step = 0;
|
|
+ if (keyval == Gdk.Key.Home)
|
|
+ step = -1;
|
|
+ else if (keyval == Gdk.Key.End)
|
|
+ step = 1;
|
|
+ GLib.Signal.emit_by_name(
|
|
+ m_entry, "move-cursor",
|
|
+ Gtk.MovementStep.DISPLAY_LINE_ENDS,
|
|
+ step,
|
|
+ (modifiers & Gdk.ModifierType.SHIFT_MASK) != 0
|
|
+ ? true : false);
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ private bool key_press_cursor_escape() {
|
|
+ if (m_candidate_panel_is_visible) {
|
|
+ hide_candidate_panel();
|
|
+ return true;
|
|
+ } else if (m_current_category_type == CategoryType.LANG) {
|
|
+ m_current_category_type = CategoryType.EMOJI;
|
|
+ show_candidate_panel();
|
|
+ return true;
|
|
+ } else if (m_entry.get_text().length == 0) {
|
|
+ m_loop.quit();
|
|
+ hide_candidate_panel();
|
|
+ return true;
|
|
+ }
|
|
+ m_entry.delete_text(0, -1);
|
|
+ return true;
|
|
+ }
|
|
+
|
|
private void entry_enter_keyval(uint keyval) {
|
|
unichar ch = IBus.keyval_to_unicode(keyval);
|
|
- if (!ch.isgraph())
|
|
+ if (ch.iscntrl())
|
|
return;
|
|
string str = ch.to_string();
|
|
|
|
// what gtk_entry_commit_cb() do
|
|
+ if (m_entry.get_selection_bounds(null, null)) {
|
|
+ m_entry.delete_selection();
|
|
+ } else {
|
|
+ if (m_entry.get_overwrite_mode()) {
|
|
+ uint text_length = m_entry.get_buffer().get_length();
|
|
+ if (m_entry.cursor_position < text_length)
|
|
+ m_entry.delete_from_cursor(Gtk.DeleteType.CHARS, 1);
|
|
+ }
|
|
+ }
|
|
int pos = m_entry.get_position();
|
|
m_entry.insert_text(str, -1, ref pos);
|
|
m_entry.set_position(pos);
|
|
@@ -1084,19 +1216,8 @@ class IBusEmojier : Gtk.Window {
|
|
}
|
|
switch (keyval) {
|
|
case Gdk.Key.Escape:
|
|
- if (m_candidate_panel_is_visible) {
|
|
- hide_candidate_panel();
|
|
- return true;
|
|
- } else if (m_current_category_type == CategoryType.LANG) {
|
|
- m_current_category_type = CategoryType.EMOJI;
|
|
- show_candidate_panel();
|
|
+ if (key_press_cursor_escape())
|
|
return true;
|
|
- } else if (m_entry.get_text().length == 0) {
|
|
- m_loop.quit();
|
|
- hide_candidate_panel();
|
|
- return true;
|
|
- }
|
|
- m_entry.delete_text(0, -1);
|
|
break;
|
|
case Gdk.Key.Return:
|
|
if (m_candidate_panel_is_visible) {
|
|
@@ -1126,7 +1247,7 @@ class IBusEmojier : Gtk.Window {
|
|
break;
|
|
}
|
|
if (m_candidate_panel_is_visible) {
|
|
- m_enter_notify_enable = false;
|
|
+ enter_notify_disable_with_timer();
|
|
m_lookup_table.cursor_down();
|
|
show_candidate_panel();
|
|
}
|
|
@@ -1135,48 +1256,20 @@ class IBusEmojier : Gtk.Window {
|
|
}
|
|
return true;
|
|
case Gdk.Key.Right:
|
|
- if (m_candidate_panel_is_visible) {
|
|
- m_enter_notify_enable = false;
|
|
- m_lookup_table.cursor_down();
|
|
- show_candidate_panel();
|
|
- return true;
|
|
- }
|
|
- if (m_entry.get_text().len() > 0) {
|
|
- GLib.Signal.emit_by_name(m_entry, "move-cursor",
|
|
- Gtk.MovementStep.VISUAL_POSITIONS,
|
|
- 1, false);
|
|
- return true;
|
|
- }
|
|
- break;
|
|
+ key_press_cursor_horizontal(keyval, modifiers);
|
|
+ return true;
|
|
case Gdk.Key.Left:
|
|
- if (m_candidate_panel_is_visible) {
|
|
- m_enter_notify_enable = false;
|
|
- m_lookup_table.cursor_up();
|
|
- show_candidate_panel();
|
|
- return true;
|
|
- }
|
|
- if (m_entry.get_text().len() > 0) {
|
|
- GLib.Signal.emit_by_name(m_entry, "move-cursor",
|
|
- Gtk.MovementStep.VISUAL_POSITIONS,
|
|
- -1, false);
|
|
- return true;
|
|
- }
|
|
- break;
|
|
+ key_press_cursor_horizontal(keyval, modifiers);
|
|
+ return true;
|
|
case Gdk.Key.Down:
|
|
- if (m_candidate_panel_is_visible)
|
|
- candidate_panel_cursor_down();
|
|
- else
|
|
- category_list_cursor_move(Gdk.Key.Down);
|
|
+ key_press_cursor_vertical(keyval);
|
|
return true;
|
|
case Gdk.Key.Up:
|
|
- if (m_candidate_panel_is_visible)
|
|
- candidate_panel_cursor_up();
|
|
- else
|
|
- category_list_cursor_move(Gdk.Key.Up);
|
|
+ key_press_cursor_vertical(keyval);
|
|
return true;
|
|
case Gdk.Key.Page_Down:
|
|
if (m_candidate_panel_is_visible) {
|
|
- m_enter_notify_enable = false;
|
|
+ enter_notify_disable_with_timer();
|
|
m_lookup_table.page_down();
|
|
show_candidate_panel();
|
|
return true;
|
|
@@ -1184,33 +1277,59 @@ class IBusEmojier : Gtk.Window {
|
|
break;
|
|
case Gdk.Key.Page_Up:
|
|
if (m_candidate_panel_is_visible) {
|
|
- m_enter_notify_enable = false;
|
|
+ enter_notify_disable_with_timer();
|
|
m_lookup_table.page_up();
|
|
show_candidate_panel();
|
|
return true;
|
|
}
|
|
break;
|
|
case Gdk.Key.Home:
|
|
- if (m_entry.get_text().len() > 0) {
|
|
- GLib.Signal.emit_by_name(m_entry, "move-cursor",
|
|
- Gtk.MovementStep.DISPLAY_LINE_ENDS,
|
|
- -1, false);
|
|
+ if (key_press_cursor_home_end(keyval, modifiers))
|
|
return true;
|
|
- }
|
|
break;
|
|
case Gdk.Key.End:
|
|
- if (m_entry.get_text().len() > 0) {
|
|
- GLib.Signal.emit_by_name(m_entry, "move-cursor",
|
|
- Gtk.MovementStep.DISPLAY_LINE_ENDS,
|
|
- 1, false);
|
|
+ if (key_press_cursor_home_end(keyval, modifiers))
|
|
return true;
|
|
- }
|
|
- break;
|
|
- default:
|
|
- entry_enter_keyval(keyval);
|
|
break;
|
|
}
|
|
|
|
+ if ((modifiers & Gdk.ModifierType.CONTROL_MASK) != 0) {
|
|
+ switch (keyval) {
|
|
+ case Gdk.Key.f:
|
|
+ key_press_cursor_horizontal(Gdk.Key.Right, modifiers);
|
|
+ return true;
|
|
+ case Gdk.Key.b:
|
|
+ key_press_cursor_horizontal(Gdk.Key.Left, modifiers);
|
|
+ return true;
|
|
+ case Gdk.Key.n:
|
|
+ key_press_cursor_vertical(Gdk.Key.Down);
|
|
+ return true;
|
|
+ case Gdk.Key.p:
|
|
+ key_press_cursor_vertical(Gdk.Key.Up);
|
|
+ return true;
|
|
+ case Gdk.Key.h:
|
|
+ if (key_press_cursor_home_end(Gdk.Key.Home, modifiers))
|
|
+ return true;
|
|
+ break;
|
|
+ case Gdk.Key.e:
|
|
+ if (key_press_cursor_home_end(Gdk.Key.End, modifiers))
|
|
+ return true;
|
|
+ break;
|
|
+ case Gdk.Key.u:
|
|
+ if (key_press_cursor_escape())
|
|
+ return true;
|
|
+ break;
|
|
+ case Gdk.Key.a:
|
|
+ if (m_entry.get_text().len() > 0) {
|
|
+ m_entry.select_region(0, -1);
|
|
+ return true;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ entry_enter_keyval(keyval);
|
|
return true;
|
|
}
|
|
|
|
--
|
|
2.9.3
|
|
|