Philipp Hörist pushed to branch master at gajim / gajim

Commits:

2 changed files:

Changes:

  • gajim/common/helpers.py
    ... ... @@ -1478,11 +1478,7 @@ def version_condition(current_version, required_version):
    1478 1478
         return True
    
    1479 1479
     
    
    1480 1480
     def get_available_emoticon_themes():
    
    1481
    -    emoticons_themes = []
    
    1482
    -    if sys.platform not in ('win32', 'darwin'):
    
    1483
    -        # Colored emoji fonts only supported on Linux
    
    1484
    -        emoticons_themes.append('font')
    
    1485
    -
    
    1481
    +    emoticons_themes = ['font']
    
    1486 1482
         files = []
    
    1487 1483
         dir_iterator = os.scandir(configpaths.get('EMOTICONS'))
    
    1488 1484
         for folder in dir_iterator:
    

  • gajim/gtk/emoji_chooser.py
    ... ... @@ -21,6 +21,7 @@ from collections import OrderedDict
    21 21
     from gi.repository import Gtk
    
    22 22
     from gi.repository import GLib
    
    23 23
     from gi.repository import GdkPixbuf
    
    24
    +from gi.repository import Pango
    
    24 25
     
    
    25 26
     from gajim.common import app
    
    26 27
     from gajim.common import helpers
    
    ... ... @@ -38,8 +39,9 @@ log = logging.getLogger('gajim.emoji')
    38 39
     
    
    39 40
     
    
    40 41
     class Section(Gtk.Box):
    
    41
    -    def __init__(self, name, search_entry, press_cb):
    
    42
    +    def __init__(self, name, search_entry, press_cb, chooser):
    
    42 43
             Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL)
    
    44
    +        self._chooser = chooser
    
    43 45
             self._press_cb = press_cb
    
    44 46
             self.pixbuf_generator = None
    
    45 47
             self.heading = Gtk.Label(label=name)
    
    ... ... @@ -83,22 +85,44 @@ class Section(Gtk.Box):
    83 85
                     emoji_pixbufs[codepoint] = pixbuf
    
    84 86
             else:
    
    85 87
                 if pixbuf is not None:
    
    86
    -                chooser = self._get_emoji_modifier(
    
    87
    -                    codepoint, pixbuf, attrs)
    
    88
    -                chooser.flowbox.connect(
    
    89
    -                    'child-activated', self._press_cb)
    
    88
    +                chooser = ModifierChooser()
    
    89
    +
    
    90
    +                # Iterate over the variations and add the codepoints
    
    91
    +                for codepoint_ in variations.keys():
    
    92
    +                    pixbuf_ = self._get_next_pixbuf()
    
    93
    +                    if pixbuf_ is None:
    
    94
    +                        continue
    
    95
    +
    
    96
    +                    if pixbuf_ == 'font':
    
    97
    +                        if not self._chooser._font_supports_codepoint(
    
    98
    +                                codepoint_):
    
    99
    +                            continue
    
    100
    +                    else:
    
    101
    +                        emoji_pixbufs[codepoint_] = pixbuf_
    
    102
    +
    
    103
    +                    # Only codepoints are added which the
    
    104
    +                    # font or theme supports
    
    105
    +                    chooser.add_emoji(codepoint_, pixbuf_)
    
    106
    +
    
    107
    +                # Check if we successfully added codepoints with modifiers
    
    108
    +                if chooser.has_child:
    
    109
    +                    # If we have children then add a button
    
    110
    +                    # and set the popover
    
    111
    +                    child = EmojiModifierChild(
    
    112
    +                        codepoint, pixbuf, attrs['desc'])
    
    113
    +                    child.button.set_popover(chooser)
    
    114
    +                    chooser.flowbox.connect(
    
    115
    +                        'child-activated', self._press_cb)
    
    116
    +                else:
    
    117
    +                    # If no children were added, destroy the chooser
    
    118
    +                    # and add a EmojiChild instead of a EmojiModifierChild
    
    119
    +                    chooser.destroy()
    
    120
    +                    child = EmojiChild(codepoint, pixbuf, attrs['desc'])
    
    90 121
     
    
    91 122
                     if pixbuf != 'font':
    
    92 123
                         emoji_pixbufs[codepoint] = pixbuf
    
    93 124
     
    
    94
    -                for codepoint, attrs in variations.items():
    
    95
    -                    pixbuf = self._get_next_pixbuf()
    
    96
    -                    if pixbuf is None:
    
    97
    -                        continue
    
    98
    -                    chooser.add_emoji(codepoint, pixbuf)
    
    99
    -
    
    100
    -                    if pixbuf != 'font':
    
    101
    -                        emoji_pixbufs[codepoint] = pixbuf
    
    125
    +                self.flowbox.add(child)
    
    102 126
                 else:
    
    103 127
                     # We dont have a image for the base codepoint
    
    104 128
                     # so skip all modifiers of it
    
    ... ... @@ -112,13 +136,6 @@ class Section(Gtk.Box):
    112 136
                 emoji.destroy()
    
    113 137
             self.flowbox.foreach(_remove_emoji)
    
    114 138
     
    
    115
    -    def _get_emoji_modifier(self, codepoint, pixbuf, attrs):
    
    116
    -        chooser = ModifierChooser()
    
    117
    -        modifier_button = EmojiModifierChild(codepoint, pixbuf, attrs['desc'])
    
    118
    -        modifier_button.button.set_popover(chooser)
    
    119
    -        self.flowbox.add(modifier_button)
    
    120
    -        return chooser
    
    121
    -
    
    122 139
         def _get_next_pixbuf(self):
    
    123 140
             if self.pixbuf_generator is None:
    
    124 141
                 return 'font'
    
    ... ... @@ -193,6 +210,7 @@ class ModifierChooser(Gtk.Popover):
    193 210
         def __init__(self):
    
    194 211
             Gtk.Popover.__init__(self)
    
    195 212
             self.set_name('EmoticonPopover')
    
    213
    +        self._has_child = False
    
    196 214
     
    
    197 215
             self.flowbox = Gtk.FlowBox()
    
    198 216
             self.flowbox.get_style_context().add_class(
    
    ... ... @@ -202,8 +220,13 @@ class ModifierChooser(Gtk.Popover):
    202 220
             self.flowbox.show()
    
    203 221
             self.add(self.flowbox)
    
    204 222
     
    
    223
    +    @property
    
    224
    +    def has_child(self):
    
    225
    +        return self._has_child
    
    226
    +
    
    205 227
         def add_emoji(self, codepoint, pixbuf):
    
    206 228
             self.flowbox.add(EmojiChild(codepoint, pixbuf, None))
    
    229
    +        self._has_child = True
    
    207 230
     
    
    208 231
     
    
    209 232
     class EmojiChooser(Gtk.Popover):
    
    ... ... @@ -224,6 +247,7 @@ class EmojiChooser(Gtk.Popover):
    224 247
             self.set_name('EmoticonPopover')
    
    225 248
             self._text_widget = None
    
    226 249
             self._load_source_id = None
    
    250
    +        self._pango_layout = Pango.Layout(self.get_pango_context())
    
    227 251
     
    
    228 252
             self._builder = get_builder('emoji_chooser.ui')
    
    229 253
             self._search = self._builder.get_object('search')
    
    ... ... @@ -232,7 +256,7 @@ class EmojiChooser(Gtk.Popover):
    232 256
             self._sections = OrderedDict()
    
    233 257
             for name in self._section_names:
    
    234 258
                 self._sections[name] = Section(
    
    235
    -                name, self._search, self._on_emoticon_press)
    
    259
    +                name, self._search, self._on_emoticon_press, self)
    
    236 260
     
    
    237 261
             section_box = self._builder.get_object('section_box')
    
    238 262
             for section in self._sections.values():
    
    ... ... @@ -326,21 +350,35 @@ class EmojiChooser(Gtk.Popover):
    326 350
             self._clear_sections()
    
    327 351
             emoji_pixbufs.clear()
    
    328 352
     
    
    329
    -        factory = self._emoji_factory()
    
    353
    +        factory = self._emoji_factory(theme == 'font')
    
    330 354
             self._load_source_id = GLib.idle_add(lambda: next(factory, False),
    
    331 355
                                                  priority=GLib.PRIORITY_LOW)
    
    332 356
     
    
    333
    -    def _emoji_factory(self):
    
    357
    +    def _emoji_factory(self, font):
    
    334 358
             for codepoint, attrs in emoji_data.items():
    
    335 359
                 if not attrs['fully-qualified']:
    
    336 360
                     # We dont add these to the UI
    
    337 361
                     continue
    
    338 362
     
    
    363
    +            if font and not self._font_supports_codepoint(codepoint):
    
    364
    +                continue
    
    365
    +
    
    339 366
                 section = self._sections[attrs['group']]
    
    340 367
                 yield section.add_emoji(codepoint, attrs)
    
    341 368
             self._load_source_id = None
    
    342 369
             emoji_pixbufs.complete = True
    
    343 370
     
    
    371
    +    def _font_supports_codepoint(self, codepoint):
    
    372
    +        self._pango_layout.set_text(codepoint, -1)
    
    373
    +        if self._pango_layout.get_unknown_glyphs_count():
    
    374
    +            return False
    
    375
    +        if len(codepoint) > 1:
    
    376
    +            # The font supports each of the codepoints
    
    377
    +            # Check if the rendered glyph is more than one char
    
    378
    +            if self._pango_layout.get_size()[0] > 19000:
    
    379
    +                return False
    
    380
    +        return True
    
    381
    +
    
    344 382
         def _get_next_pixbuf(self, path):
    
    345 383
             src_x = src_y = cur_column = 0
    
    346 384
             atlas = GdkPixbuf.Pixbuf.new_from_file(path)