public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Takao Fujiwara <tfujiwar@redhat.com>
To: git-commits@fedoraproject.org
Subject: [rpms/ibus] autotool: Implement shortcut keys on emoji dialog
Date: Sun, 31 May 2026 02:06:30 GMT [thread overview]
Message-ID: <178019319064.1.16712814926975530344.rpms-ibus-6a3b67701391@fedoraproject.org> (raw)
A new commit has been pushed.
Repo : rpms/ibus
Branch : autotool
Commit : 6a3b6770139172a4fad44e499971f9d2a52066d6
Author : Takao Fujiwara <tfujiwar@redhat.com>
Date : 2017-03-15T12:41:29+09:00
Stats : +550/-1 in 2 file(s)
URL : https://src.fedoraproject.org/rpms/ibus/c/6a3b6770139172a4fad44e499971f9d2a52066d6?branch=autotool
Log:
Implement shortcut keys on emoji dialog
- Implemented Ctrl-[f|b|n|p|h|e|a|u] for cursor operations on emoji dialog
- Added XSetIOErrorHandler() for GNOME3 desktop
---
diff --git a/ibus-HEAD.patch b/ibus-HEAD.patch
index 45d0eef..56a760c 100644
--- a/ibus-HEAD.patch
+++ b/ibus-HEAD.patch
@@ -1223,3 +1223,548 @@ index 8cecea8..5e126e9 100644
--
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
+
diff --git a/ibus.spec b/ibus.spec
index 3166733..ca0f66b 100644
--- a/ibus.spec
+++ b/ibus.spec
@@ -28,7 +28,7 @@
Name: ibus
Version: 1.5.15
-Release: 3%{?dist}
+Release: 4%{?dist}
Summary: Intelligent Input Bus for Linux OS
License: LGPLv2+
Group: System Environment/Libraries
@@ -426,6 +426,10 @@ gtk-query-immodules-3.0-%{__isa_bits} --update-cache &> /dev/null || :
%{_datadir}/gtk-doc/html/*
%changelog
+* Wed Mar 15 2017 Takao Fujiwara <tfujiwar@redhat.com> - 1.5.15-4
+- Implemented Ctrl-[f|b|n|p|h|e|a|u] for cursor operations on emoji dialog
+- Added XSetIOErrorHandler() for GNOME3 desktop
+
* Mon Mar 13 2017 Takao Fujiwara <tfujiwar@redhat.com> - 1.5.15-3
- Emoji dialog enhancements and bug fixes
Fixed ibus_emoji_dict_load() API.
reply other threads:[~2026-05-31 2:06 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=178019319064.1.16712814926975530344.rpms-ibus-6a3b67701391@fedoraproject.org \
--to=tfujiwar@redhat.com \
--cc=git-commits@fedoraproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox