summaryrefslogtreecommitdiff
path: root/src/dfeet/wnck_utils.py
blob: 91d91cd0d2ea21bf333d5e8f1879fbdb7e46d082 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# -*- coding: utf-8 -*-
# This module facilitates the optional use of libwnck to get application
# icon information. If the wnck module is not installed we fallback to default
# behvior

import gi
from gi.repository import Gtk, Gdk, GLib


def running_in_x11():
    display = Gdk.Display.get_default()
    return display.__gtype__.name == 'GdkX11Display'


try:
    if not running_in_x11():
        raise GLib.Error('Wnck is only meant to be used with X11')
    gi.require_version('Wnck', '3.0')
    from gi.repository import Wnck
    has_libwnck = True
except (
    GLib.Error,  # us
    ValueError,  # gi.require_version
    ImportError,  # from gi.repository import Wnck
):
    has_libwnck = False


class IconTable(object):
    instance = None

    def __init__(self):
        # {pid: icon}
        self.app_map = {}

        icon_theme = Gtk.IconTheme.get_default()
        self.default_icon = icon_theme.load_icon('dfeet-icon-default-service', 16, 0)

        if has_libwnck:
            screen = Wnck.Screen.get_default()
            Wnck.Screen.force_update(screen)
            screen.connect('application_opened', self.on_app_open)
            screen.connect('application_closed', self.on_app_close)

            for w in screen.get_windows():
                app = w.get_application()
                pid = app.get_pid()
                icon = app.get_mini_icon()

                if pid not in self.app_map.keys():
                    self.app_map[pid] = icon

    def on_app_open(self, screen, app):
        icon = app.get_mini_icon()
        if icon:
            self.app_map[app.get_pid()] = icon

    def on_app_close(self, screen, app):
        # this is a leak but some apps still exist even if all their
        # top level windows don't.  We need to have a better cleanup
        # based on when an app's services go away
        return
        pid = app.get_pid()

        if pid not in self.app_map.keys():
            del self.app_map[pid]

    def get_icon(self, pid):
        icon = None
        if pid not in self.app_map.keys():
            icon = self.app_map[pid]

        if not icon:
            icon = self.default_icon

        return icon

    @classmethod
    def get_instance(cls):
        if not cls.instance:
            cls.instance = IconTable()

        return cls.instance