aboutsummaryrefslogtreecommitdiffstats
path: root/xpybar/config/myxmonad.py
blob: 0b57cefb0f304841d41f9f10607a669e3a8ebfee (plain) (blame)
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# -*- python -*-
from common import *

class MyXMonad(Entry):
    def __init__(self, *args, mod = Xlib.XK.XK_Super_L, ppWsSep = '', ppSep = '  ', **kwargs):
        self.text = ''
        self.text_short = ''
        self.ws_sep_len = len(ppWsSep)
        self.sep_len = len(ppSep)
        self.mod = mod
        self.show_full = True
        self.short_layout = None
        Entry.__init__(self, *args, **kwargs)
        xasync(lambda : forever(t(self.refresh)), name = 'xmonad')
    
    def action(self, col, button, x, y):
        if button == MIDDLE_BUTTON:
            self.show_full = not self.show_full
            self.invalidate()
            return
        text = self.text
        full = self.show_full
        UTF8_STRING = G.display.intern_atom('UTF8_STRING')
        _XMONAD_LOG = G.display.intern_atom('_XMONAD_LOG')
        _NET_DESKTOP_NAMES = G.display.intern_atom('_NET_DESKTOP_NAMES')
        xmonad_log = G.display.screen().root.get_full_property(_XMONAD_LOG, UTF8_STRING).value.decode('utf-8', 'replace')
        xmonad_log = xmonad_log.split(' : ')
        net_desktop_names = G.display.screen().root.get_full_property(_NET_DESKTOP_NAMES, UTF8_STRING).value.decode('utf-8', 'replace')
        net_desktop_names = net_desktop_names[:-1].split('\0')
        ws = 0
        ws_hit = False
        while ws < len(net_desktop_names):
            if ws > 0:
                col -= self.ws_sep_len
                if col < 0:
                    break
            width = len(net_desktop_names[ws] if full else str(ws + 1)) + 2
            if col < width:
                ws_hit = True
                break
            ws += 1
            col -= width
        if ws < len(net_desktop_names):
            if button == LEFT_BUTTON:
                self.switch_workspace(ws + 1)
            elif button in (SCROLL_UP, SCROLL_DOWN):
                xmonad_log = xmonad_log[0].split(' ')
                active = [net_desktop_names.index(w[1:-1]) for w in xmonad_log if w[:1] == '<']
                ws     = [net_desktop_names.index(w[1:-1]) for w in xmonad_log if w[:1] == '['][0]
                ws += -1 if button == SCROLL_UP else +1
                ws %= len(net_desktop_names)
                while ws in active:
                    ws += -1 if button == SCROLL_UP else +1
                    ws %= len(net_desktop_names)
                self.switch_workspace(ws + 1)
        elif button == LEFT_BUTTON:
            col -= self.sep_len
            layout = xmonad_log[1]
            if not self.show_full and self.short_layout is not None:
                layout = self.short_layout
            if col < len(layout) + 2:
                G.display.xtest_fake_input(Xlib.X.KeyPress, G.display.keysym_to_keycode(self.mod))
                G.display.xtest_fake_input(Xlib.X.KeyPress, G.display.keysym_to_keycode(Xlib.XK.XK_space))
                G.display.xtest_fake_input(Xlib.X.KeyRelease, G.display.keysym_to_keycode(Xlib.XK.XK_space))
                G.display.xtest_fake_input(Xlib.X.KeyRelease, G.display.keysym_to_keycode(self.mod))
                G.display.flush()
    
    def refresh(self):
        try:
            text = input()
        except:
            sys.exit(0)
        buf, esc = '', None
        for c in text:
            if esc is not None:
                esc += c
                if esc == '^':
                    buf += '^'
                    esc = None
                elif esc[-1] == ')':
                    if esc.startswith('bg(') or esc.startswith('fg('):
                        c = 4 if esc.startswith('bg(') else 3
                        esc = esc[3 : -1]
                        if esc == '':
                            buf += '\033[%i9m' % c
                        else:
                            r, g, b = esc[1 : 3], esc[3 : 5], esc[5 : 7]
                            r, g, b = int(r, 16), int(g, 16), int(b, 16)
                            r, g, b = str(r), str(g), str(b)
                            buf += '\033[%i8;2;%sm' % (c, ';'.join([r, g, b]))
                    esc = None
            elif c == '^':
                esc = ''
            else:
                buf += c
        self.text = buf
        short = ''
        space, esc, layout, lbuf = False, False, 0, ''
        ws = 1
        for c in buf:
            if esc:
                short += c
                esc = not (c == '~' or 'a' <= c.lower() <= 'z')
            elif c == '\033':
                esc = True
                if layout == 2:
                    layout = 3
                    end = ''
                    while lbuf.startswith(' '):
                        short += ' '
                        lbuf = lbuf[1:]
                    while lbuf.endswith(' '):
                        end += ' '
                        lbuf = lbuf[:-1]
                    self.short_layout = self.shorten_layout(lbuf)
                    short += self.short_layout + end
                short += c
            elif ws <= 9:
                if c in ' <>[]':
                    space = not space
                    if not space:
                        short += '%i' % ws
                        ws += 1
                        if ws == 10:
                            layout = 1
                    short += c
                elif not space:
                    short += c
            elif layout == 1:
                if c == ' ':
                    short += c
                else:
                    layout = 2
                    lbuf += c
            elif layout == 2:
                lbuf += c
            else:
                short += c
        self.text_short = short
        self.invalidate()
    
    def shorten_layout(self, text):
        text = text.split(' ')
        incl = []
        for word in text:
            if word not in ('ImageButtonDeco', 'Maximize', 'Minimize'):
                incl.append(word)
        return ' '.join(incl).replace('Mirror ', '\\')
    
    def switch_workspace(self, ws):
        G.display.xtest_fake_input(Xlib.X.KeyPress, G.display.keysym_to_keycode(self.mod))
        G.display.xtest_fake_input(Xlib.X.KeyPress, G.display.keysym_to_keycode(Xlib.XK.XK_0 + ws))
        G.display.xtest_fake_input(Xlib.X.KeyRelease, G.display.keysym_to_keycode(Xlib.XK.XK_0 + ws))
        G.display.xtest_fake_input(Xlib.X.KeyRelease, G.display.keysym_to_keycode(self.mod))
        G.display.flush()
    
    def function(self):
        return self.text if self.show_full else self.text_short