Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1215)

Delta Between Two Patch Sets: ui/gtk3/emojier.vala

Issue 320700043: ui/gtk3: Integrate custom rendering to use HarfBuzz glyph info Base URL: git@github.com:ibus/ibus.git@master
Left Patch Set: Fix a build failure in ibusfontset.h dependency Created 6 years, 6 months ago
Right Patch Set: Fix a typo Created 6 years, 5 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « ui/gtk3/Makefile.am ('k') | ui/gtk3/ibusfontset.h » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 /* vim:set et sts=4 sw=4: 1 /* vim:set et sts=4 sw=4:
2 * 2 *
3 * ibus - The Input Bus 3 * ibus - The Input Bus
4 * 4 *
5 * Copyright (c) 2017 Takao Fujiwara <takao.fujiwara1@gmail.com> 5 * Copyright (c) 2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
6 * 6 *
7 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public 8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version. 10 * version 2.1 of the License, or (at your option) any later version.
(...skipping 21 matching lines...) Expand all
32 ); 32 );
33 } 33 }
34 } 34 }
35 private class EListBox : Gtk.ListBox { 35 private class EListBox : Gtk.ListBox {
36 public EListBox() { 36 public EListBox() {
37 GLib.Object( 37 GLib.Object(
38 vexpand : true, 38 vexpand : true,
39 halign : Gtk.Align.FILL, 39 halign : Gtk.Align.FILL,
40 valign : Gtk.Align.FILL 40 valign : Gtk.Align.FILL
41 ); 41 );
42 this.motion_notify_event.connect((e) => {
43 #if VALA_0_24
44 Gdk.EventMotion pe = e;
45 #else
46 Gdk.EventMotion *pe = &e;
47 #endif
48 if (m_mouse_x == pe.x_root && m_mouse_y == pe.y_root)
49 return false;
50 m_mouse_x = pe.x_root;
51 m_mouse_y = pe.y_root;
52 var row = this.get_row_at_y((int)e.y);
53 if (row != null)
54 this.select_row(row);
55 return false;
56 });
57 this.enter_notify_event.connect((e) => {
58 // avoid gtk_button_update_state()
59 return true;
60 });
42 } 61 }
43 } 62 }
44 private class EBoxRow : Gtk.ListBoxRow { 63 private class EBoxRow : Gtk.ListBoxRow {
45 public EBoxRow(string text) { 64 public EBoxRow(string text) {
46 this.text = text; 65 this.text = text;
47 } 66 }
48 67
49 public string text { get; set; } 68 public string text { get; set; }
50 } 69 }
51 private class EScrolledWindow : Gtk.ScrolledWindow { 70 private class EScrolledWindow : Gtk.ScrolledWindow {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 public override void get_preferred_height(out int minimum_height, 140 public override void get_preferred_height(out int minimum_height,
122 out int natural_height) { 141 out int natural_height) {
123 get_preferred_size_with_hb(null, null, 142 get_preferred_size_with_hb(null, null,
124 out minimum_height, 143 out minimum_height,
125 out natural_height); 144 out natural_height);
126 } 145 }
127 public override bool draw(Cairo.Context cr) { 146 public override bool draw(Cairo.Context cr) {
128 if (m_fontset == null) 147 if (m_fontset == null)
129 return true; 148 return true;
130 if (m_requisition == null) 149 if (m_requisition == null)
131 return true; 150 return true;
132 if (m_requisition.cairo_lines == null) 151 if (m_requisition.cairo_lines == null)
133 return true; 152 return true;
134 var style_context = get_style_context(); 153 var style_context = get_style_context();
135 Gtk.Allocation allocation; 154 Gtk.Allocation allocation;
136 get_allocation(out allocation); 155 get_allocation(out allocation);
137 style_context.render_background(cr, 156 style_context.render_background(cr,
138 0, 0, 157 0, 0,
139 allocation.width, 158 allocation.width,
140 allocation.height); 159 allocation.height);
141 Gdk.RGBA *normal_fg = null; 160 Gdk.RGBA *normal_fg = null;
142 style_context.get(Gtk.StateFlags.NORMAL, 161 style_context.get(Gtk.StateFlags.NORMAL,
143 "color", 162 "color",
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 private GLib.MainLoop? m_loop; 321 private GLib.MainLoop? m_loop;
303 private string? m_result; 322 private string? m_result;
304 private string? m_unicode_point = null; 323 private string? m_unicode_point = null;
305 private bool m_candidate_panel_is_visible; 324 private bool m_candidate_panel_is_visible;
306 private int m_category_active_index; 325 private int m_category_active_index;
307 private IBus.LookupTable m_lookup_table; 326 private IBus.LookupTable m_lookup_table;
308 private Gtk.Label[] m_candidates; 327 private Gtk.Label[] m_candidates;
309 private bool m_enter_notify_enable = true; 328 private bool m_enter_notify_enable = true;
310 private uint m_entry_notify_show_id; 329 private uint m_entry_notify_show_id;
311 private uint m_entry_notify_disable_id; 330 private uint m_entry_notify_disable_id;
331 protected static double m_mouse_x;
332 protected static double m_mouse_y;
312 333
313 public signal void candidate_clicked(uint index, uint button, uint state); 334 public signal void candidate_clicked(uint index, uint button, uint state);
314 335
315 public IBusEmojier() { 336 public IBusEmojier() {
316 GLib.Object( 337 GLib.Object(
317 type : Gtk.WindowType.TOPLEVEL, 338 type : Gtk.WindowType.TOPLEVEL,
318 events : Gdk.EventMask.KEY_PRESS_MASK | 339 events : Gdk.EventMask.KEY_PRESS_MASK |
319 Gdk.EventMask.KEY_RELEASE_MASK | 340 Gdk.EventMask.KEY_RELEASE_MASK |
320 Gdk.EventMask.BUTTON_PRESS_MASK | 341 Gdk.EventMask.BUTTON_PRESS_MASK |
321 Gdk.EventMask.BUTTON_RELEASE_MASK, 342 Gdk.EventMask.BUTTON_RELEASE_MASK,
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 665
645 private static void update_category_to_emojis_dict(IBus.EmojiData data, 666 private static void update_category_to_emojis_dict(IBus.EmojiData data,
646 string lang) { 667 string lang) {
647 string emoji = data.get_emoji(); 668 string emoji = data.get_emoji();
648 string category = data.get_category(); 669 string category = data.get_category();
649 if (category == "") 670 if (category == "")
650 category = EMOJI_CATEGORY_OTHERS; 671 category = EMOJI_CATEGORY_OTHERS;
651 if (lang == "en") { 672 if (lang == "en") {
652 bool has_variant = false; 673 bool has_variant = false;
653 foreach (unichar ch in EMOJI_VARIANT_LIST) { 674 foreach (unichar ch in EMOJI_VARIANT_LIST) {
654 if (emoji.chr(-1, ch) != null) { 675 if (emoji.index_of_char(ch) >= 0) {
655 has_variant = true; 676 has_variant = true;
656 break; 677 break;
657 } 678 }
658 } 679 }
659 // If emoji includes variants (skin colors and items), 680 // If emoji includes variants (skin colors and items),
660 // it's escaped in m_emoji_to_emoji_variants_dict and 681 // it's escaped in m_emoji_to_emoji_variants_dict and
661 // not shown by default. 682 // not shown by default.
662 if (has_variant) { 683 if (has_variant) {
663 unichar base_ch = emoji.get_char(); 684 unichar base_ch = emoji.get_char();
664 string base_emoji = base_ch.to_string(); 685 string base_emoji = base_ch.to_string();
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 buttons_hbox.pack_start(prev_button, false, false, 0); 872 buttons_hbox.pack_start(prev_button, false, false, 0);
852 buttons_hbox.pack_start(next_button, false, false, 0); 873 buttons_hbox.pack_start(next_button, false, false, 0);
853 m_vbox.pack_start(buttons_hbox, false, false, 0); 874 m_vbox.pack_start(buttons_hbox, false, false, 0);
854 buttons_hbox.show_all(); 875 buttons_hbox.show_all();
855 } 876 }
856 877
857 878
858 private bool check_unicode_point() { 879 private bool check_unicode_point() {
859 string annotation = m_entry.get_text(); 880 string annotation = m_entry.get_text();
860 m_unicode_point = null; 881 m_unicode_point = null;
861 var buff = new GLib.StringBuilder(); 882 // Add "0x" because uint64.ascii_strtoull() is not accessible
883 // and need to use uint64.parse()
884 var buff = new GLib.StringBuilder("0x");
862 var retval = new GLib.StringBuilder(); 885 var retval = new GLib.StringBuilder();
863 for (int i = 0; i < annotation.char_count(); i++) { 886 for (int i = 0; i < annotation.char_count(); i++) {
864 unichar ch = annotation.get_char(i); 887 unichar ch = annotation.get_char(i);
865 if (ch == 0) 888 if (ch == 0)
866 return false; 889 return false;
867 if (ch.isspace()) { 890 if (ch.isspace()) {
868 unichar code = (unichar)buff.str.to_ulong(null, 16); 891 unichar code = (unichar)uint64.parse(buff.str);
869 buff.erase(); 892 buff.assign("0x");
870 if (!code.validate()) 893 if (!code.validate())
871 return false; 894 return false;
872 retval.append(code.to_string()); 895 retval.append(code.to_string());
873 continue; 896 continue;
874 } 897 }
875 if (!ch.isxdigit()) 898 if (!ch.isxdigit())
876 return false; 899 return false;
877 buff.append_unichar(ch); 900 buff.append_unichar(ch);
878 } 901 }
879 unichar code = (unichar)buff.str.to_ulong(null, 16); 902 unichar code = (unichar)uint64.parse(buff.str);
880 if (!code.validate()) 903 if (!code.validate())
881 return false; 904 return false;
882 retval.append(code.to_string()); 905 retval.append(code.to_string());
883 m_unicode_point = retval.str; 906 m_unicode_point = retval.str;
884 if (m_unicode_point == null) 907 if (m_unicode_point == null)
885 return true; 908 return true;
886 IBus.Text text = new IBus.Text.from_string(m_unicode_point); 909 IBus.Text text = new IBus.Text.from_string(m_unicode_point);
887 m_lookup_table.append_candidate(text); 910 m_lookup_table.append_candidate(text);
888 return true; 911 return true;
889 } 912 }
(...skipping 13 matching lines...) Expand all
903 switch(m_partial_match_condition) { 926 switch(m_partial_match_condition) {
904 case 0: 927 case 0:
905 if (key.has_prefix(annotation)) 928 if (key.has_prefix(annotation))
906 matched = true; 929 matched = true;
907 break; 930 break;
908 case 1: 931 case 1:
909 if (key.has_suffix(annotation)) 932 if (key.has_suffix(annotation))
910 matched = true; 933 matched = true;
911 break; 934 break;
912 case 2: 935 case 2:
913 if (key.str(annotation) != null) 936 if (key.index_of(annotation) >= 0)
914 matched = true; 937 matched = true;
915 break; 938 break;
916 default: 939 default:
917 break; 940 break;
918 } 941 }
919 if (!matched) 942 if (!matched)
920 continue; 943 continue;
921 sub_emojis = m_annotation_to_emojis_dict.lookup(key); 944 sub_emojis = m_annotation_to_emojis_dict.lookup(key);
922 foreach (unowned string emoji in sub_emojis) { 945 foreach (unowned string emoji in sub_emojis) {
923 if (total_emojis.find_custom(emoji, GLib.strcmp) == null) { 946 if (total_emojis.find_custom(emoji, GLib.strcmp) == null) {
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1041 string font_family = m_emoji_font_family; 1064 string font_family = m_emoji_font_family;
1042 int font_size = m_emoji_font_size - 2; 1065 int font_size = m_emoji_font_size - 2;
1043 string emoji_font = "%s %d".printf(font_family, font_size); 1066 string emoji_font = "%s %d".printf(font_family, font_size);
1044 string markup = "<span font=\"%s\">%s</span>". 1067 string markup = "<span font=\"%s\">%s</span>".
1045 printf(emoji_font, utf8_entity(text)); 1068 printf(emoji_font, utf8_entity(text));
1046 label.set_markup(markup); 1069 label.set_markup(markup);
1047 } 1070 }
1048 label.set_halign(Gtk.Align.FILL); 1071 label.set_halign(Gtk.Align.FILL);
1049 label.set_valign(Gtk.Align.FILL); 1072 label.set_valign(Gtk.Align.FILL);
1050 Gtk.EventBox candidate_ebox = new Gtk.EventBox(); 1073 Gtk.EventBox candidate_ebox = new Gtk.EventBox();
1074 candidate_ebox.add_events(Gdk.EventMask.POINTER_MOTION_MASK);
1051 candidate_ebox.add(label); 1075 candidate_ebox.add(label);
1052 // Make a copy of i to workaround a bug in vala. 1076 // Make a copy of i to workaround a bug in vala.
1053 // https://bugzilla.gnome.org/show_bug.cgi?id=628336 1077 // https://bugzilla.gnome.org/show_bug.cgi?id=628336
1054 uint index = i; 1078 uint index = i;
1055 candidate_ebox.button_press_event.connect((w, e) => { 1079 candidate_ebox.button_press_event.connect((w, e) => {
1056 candidate_clicked(index, e.button, e.state); 1080 candidate_clicked(index, e.button, e.state);
1057 return true; 1081 return true;
1058 }); 1082 });
1059 candidate_ebox.enter_notify_event.connect((e) => { 1083 candidate_ebox.motion_notify_event.connect((e) => {
1060 // m_enter_notify_enable is added because 1084 // m_enter_notify_enable is added because
1061 // enter_notify_event conflicts with keyboard operations. 1085 // enter_notify_event conflicts with keyboard operations.
1062 if (!m_enter_notify_enable) 1086 if (!m_enter_notify_enable)
1063 return true; 1087 return false;
1064 if (m_lookup_table.get_cursor_pos() == index) 1088 if (m_lookup_table.get_cursor_pos() == index)
1065 return true; 1089 return false;
1090 #if VALA_0_24
1091 Gdk.EventMotion pe = e;
1092 #else
1093 Gdk.EventMotion *pe = &e;
1094 #endif
1095 if (m_mouse_x == pe.x_root && m_mouse_y == pe.y_root)
1096 return false;
1097 m_mouse_x = pe.x_root;
1098 m_mouse_y = pe.y_root;
1099
1066 m_lookup_table.set_cursor_pos(index); 1100 m_lookup_table.set_cursor_pos(index);
1067 if (m_entry_notify_show_id > 0) { 1101 if (m_entry_notify_show_id > 0 &&
1102 GLib.MainContext.default().find_source_by_id(
1103 m_entry_notify_show_id) != null) {
1068 GLib.Source.remove(m_entry_notify_show_id); 1104 GLib.Source.remove(m_entry_notify_show_id);
1069 } 1105 }
1070 // If timeout is not added, memory leak happens and 1106 // If timeout is not added, memory leak happens and
1071 // button_press_event signal does not work above. 1107 // button_press_event signal does not work above.
1072 m_entry_notify_show_id = GLib.Timeout.add(100, () => { 1108 m_entry_notify_show_id = GLib.Timeout.add(100, () => {
1073 show_candidate_panel(); 1109 show_candidate_panel();
1074 return false; 1110 return false;
1075 }); 1111 });
1076 return true; 1112 return false;
1077 }); 1113 });
1078 grid.attach(candidate_ebox, 1114 grid.attach(candidate_ebox,
1079 n % (int)EMOJI_GRID_PAGE, n / (int)EMOJI_GRID_PAGE, 1115 n % (int)EMOJI_GRID_PAGE, n / (int)EMOJI_GRID_PAGE,
1080 1, 1); 1116 1, 1);
1081 n++; 1117 n++;
1082 1118
1083 m_candidates += label; 1119 m_candidates += label;
1084 } 1120 }
1085 if (n > 0) { 1121 if (n > 0) {
1086 m_candidate_panel_is_visible = true; 1122 m_candidate_panel_is_visible = true;
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
1434 * does not give the keyboard focus when Emojier is lauched 1470 * does not give the keyboard focus when Emojier is lauched
1435 * twice with Ctrl-Shift-e via XIEvent, if present_with_time() 1471 * twice with Ctrl-Shift-e via XIEvent, if present_with_time()
1436 * is not applied. 1472 * is not applied.
1437 * But XFCE4 desktop does not effect this bug. 1473 * But XFCE4 desktop does not effect this bug.
1438 * Seems this is caused by the window manager's focus stealing 1474 * Seems this is caused by the window manager's focus stealing
1439 * prevention logic: 1475 * prevention logic:
1440 * https://mail.gnome.org/archives/gtk-devel-list/2017-May/msg00026.html 1476 * https://mail.gnome.org/archives/gtk-devel-list/2017-May/msg00026.html
1441 */ 1477 */
1442 uint32 timestamp = event.get_time(); 1478 uint32 timestamp = event.get_time();
1443 present_with_time(timestamp); 1479 present_with_time(timestamp);
1480
1481 Gdk.Device pointer;
1482 #if VALA_0_34
1483 Gdk.Seat seat = event.get_seat();
1484 if (seat == null) {
1485 var display = get_display();
1486 seat = display.get_default_seat();
1487 }
1488 pointer = seat.get_pointer();
1489 #else
1490 Gdk.Device device = event.get_device();
1491 if (device == null) {
1492 var display = get_display();
1493 device = display.list_devices().data;
1494 }
1495 if (device.get_source() == Gdk.InputSource.KEYBOARD)
1496 pointer = device.get_associated_device();
1497 else
1498 pointer = device;
1499 #endif
1500 pointer.get_position_double(null,
1501 out m_mouse_x,
1502 out m_mouse_y);
1444 1503
1445 m_loop = new GLib.MainLoop(); 1504 m_loop = new GLib.MainLoop();
1446 m_loop.run(); 1505 m_loop.run();
1447 m_loop = null; 1506 m_loop = null;
1448 1507
1449 // Need focus-out on Gtk.Entry to send the emoji to applications. 1508 // Need focus-out on Gtk.Entry to send the emoji to applications.
1450 Gdk.Event fevent = new Gdk.Event(Gdk.EventType.FOCUS_CHANGE); 1509 Gdk.Event fevent = new Gdk.Event(Gdk.EventType.FOCUS_CHANGE);
1451 fevent.focus_change.in = 0; 1510 fevent.focus_change.in = 0;
1452 fevent.focus_change.window = get_window(); 1511 fevent.focus_change.window = get_window();
1453 m_entry.send_focus_change(fevent); 1512 m_entry.send_focus_change(fevent);
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
1655 1714
1656 public void reset() { 1715 public void reset() {
1657 m_input_context_path = ""; 1716 m_input_context_path = "";
1658 m_result = null; 1717 m_result = null;
1659 } 1718 }
1660 1719
1661 1720
1662 public void present_centralize(Gdk.Event event) { 1721 public void present_centralize(Gdk.Event event) {
1663 Gtk.Allocation allocation; 1722 Gtk.Allocation allocation;
1664 get_allocation(out allocation); 1723 get_allocation(out allocation);
1724 Gdk.Rectangle monitor_area;
1725 #if VALA_0_34
1726 Gdk.Display display = Gdk.Display.get_default();
1727 Gdk.Monitor monitor = display.get_monitor_at_window(this.get_window());
1728 monitor_area = monitor.get_geometry();
1729 #else
1665 Gdk.Screen screen = Gdk.Screen.get_default(); 1730 Gdk.Screen screen = Gdk.Screen.get_default();
1666 int monitor_num = screen.get_monitor_at_window(get_window()); 1731 int monitor_num = screen.get_monitor_at_window(this.get_window());
1667 Gdk.Rectangle monitor_area;
1668 screen.get_monitor_geometry(monitor_num, out monitor_area); 1732 screen.get_monitor_geometry(monitor_num, out monitor_area);
1733 #endif
1669 int x = (monitor_area.x + monitor_area.width - allocation.width)/2; 1734 int x = (monitor_area.x + monitor_area.width - allocation.width)/2;
1670 int y = (monitor_area.y + monitor_area.height 1735 int y = (monitor_area.y + monitor_area.height
1671 - allocation.height)/2; 1736 - allocation.height)/2;
1672 move(x, y); 1737 move(x, y);
1673 1738
1674 uint32 timestamp = event.get_time(); 1739 uint32 timestamp = event.get_time();
1675 present_with_time(timestamp); 1740 present_with_time(timestamp);
1676 m_entry.set_activates_default(true); 1741 m_entry.set_activates_default(true);
1677 } 1742 }
1678 1743
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1758 m_favorites += favorite; 1823 m_favorites += favorite;
1759 } 1824 }
1760 for(int i = 0; i < unowned_favorite_annotations.length; i++) { 1825 for(int i = 0; i < unowned_favorite_annotations.length; i++) {
1761 string? favorite_annotation = unowned_favorite_annotations[i]; 1826 string? favorite_annotation = unowned_favorite_annotations[i];
1762 GLib.return_if_fail(favorite_annotation != null); 1827 GLib.return_if_fail(favorite_annotation != null);
1763 m_favorite_annotations += favorite_annotation; 1828 m_favorite_annotations += favorite_annotation;
1764 } 1829 }
1765 update_favorite_emoji_dict(); 1830 update_favorite_emoji_dict();
1766 } 1831 }
1767 } 1832 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b