aboutsummaryrefslogblamecommitdiffstats
path: root/xpybar/config/myxmonad.py
blob: 0b57cefb0f304841d41f9f10607a669e3a8ebfee (plain) (tree)





























































































































































                                                                                                                                       
# -*- 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