aboutsummaryrefslogblamecommitdiffstats
path: root/xpybar/config/common.py
blob: fca2b73faaed40230e865d91d5ed3ce4fa6ac9bd (plain) (tree)






































































































































































































































                                                                             
# -*- python -*-

import os
import pwd
import sys
import time
import threading
import subprocess

from util import *
from __main__ import Bar

import Xlib.X, Xlib.XK, Xlib.protocol.event

class Globals:
    def __init__(self):
        self.globals = None

    @property
    def bar(self):
        return self.globals['bar']
    @property
    def display(self):
        return self.globals['display']

    @property
    def OUTPUT(self):
        return self.globals['OUTPUT']
    @property
    def HEIGHT_PER_LINE(self):
        return self.globals['HEIGHT_PER_LINE']
    @property
    def YPOS(self):
        return self.globals['YPOS']
    @property
    def TOP(self):
        return self.globals['TOP']
    @property
    def HEIGHT(self):
        return self.globals['HEIGHT']

    @OUTPUT.setter
    def OUTPUT(self, value):
        self.globals['OUTPUT'] = value
    @HEIGHT_PER_LINE.setter
    def HEIGHT_PER_LINE(self, value):
        self.globals['HEIGHT_PER_LINE'] = value
    @YPOS.setter
    def YPOS(self, value):
        self.globals['YPOS'] = value
    @TOP.setter
    def TOP(self, value):
        self.globals['TOP'] = value
    @HEIGHT.setter
    def HEIGHT(self, value):
        self.globals['HEIGHT'] = value
    
G = Globals()

LEFT_BUTTON = 1
MIDDLE_BUTTON = 2
RIGHT_BUTTON = 3
SCROLL_UP = 4
SCROLL_DOWN = 5
SCROLL_LEFT = 6
SCROLL_RIGHT = 7
FORWARD_BUTTON = 8 # X1
BACKWARD_BUTTON = 9 # X2

limited = lambda v : min(max(int(v + 0.5), 0), 100)

def t_(f):
    try:
        f()
    except Exception as e:
        time.sleep(1)

t = lambda f : (lambda : t_(f))

def pdeath(signal, *command):
    try:
        path = os.environ['PATH'].split(':')
        for p in path:
            p += '/pdeath'
            if os.access(p, os.X_OK, effective_ids = True):
                return (p, signal, *command)
    except:
        pass
    return command

HOME = pwd.getpwuid(os.getuid()).pw_dir

SEPARATOR = ' │ '

def invalidate():
    try:
        G.bar.invalidate()
    except:
        pass

mqueue_map = {}

class Entry:
    def __init__(self, wrap = None, left = True, line = 0, prev = None):
        self.left = left
        self.line = line
        self.prev = prev
        self.width = 0
        self.offset = 0
        self.last_text = None
        self.short_layout = None
        self.wrapped = self.function if wrap is None else wrap(self.function)
    
    def invalidate(self):
        wrapper = self.wrapped
        if isinstance(wrapper, Clocked):
            wrapper = wrapper.sometimes
        if isinstance(wrapper, Sometimes):
            wrapper.counter = 0
        invalidate()
    
    def action(self, col, button, x, y):
        pass
    
    def click(self, row, lcol, rcol, button, x, y):
        if row == self.line:
            col = (lcol if self.left else rcol) - self.offset
            if 0 <= col < self.width:
                if self.left:
                    x -= self.offset * G.bar.font_width
                else:
                    col = self.width - 1 - col
                    x = G.bar.width - x
                    x -= self.offset * G.bar.font_width
                    x = self.width * G.bar.font_width - x
                y -= self.line * G.HEIGHT_PER_LINE
                try:
                    self.action(col, button, x, y)
                except Exception as err:
                    print(str(err), file = sys.stderr, flush = True)
                return True
        return False
    
    def function(self):
        return SEPARATOR
    
    def __call__(self, *args, **kwargs):
        try:
            text = self.wrapped(*args, **kwargs)
            if text is not self.last_text:
                self.width = Bar.coloured_length(text)
            self.last_text = text
            return text
        except Exception as err:
            print(err, file = sys.stderr, flush = True)
    
    def update_position(self):
        if self.prev is not None:
            self.prev.update_position()
            self.offset = self.prev.offset + self.prev.width

class Group:
    def __init__(self, functions):
        self.pattern = ''
        self.posupdate = []
        left = None
        right = None
        lineno = 0
        atleft = True
        newline = False
        lastright = None
        new_functions = []
        separator = None
        for entry in functions:
            if entry is None:
                newline = not atleft
                lineno += 1 if newline else 0
                atleft = not atleft
                continue
            entry.left = atleft
            entry.line = lineno
            if newline:
                self.pattern += '\n'
                newline = False
                if left is not None:
                    self.posupdate.append(left)
                if right is not None:
                    self.posupdate.append(right)
                left = None
                right = None
                lastright = None
            if entry.left:
                if left is not None:
                    separator = Entry(left = True)
                    new_functions.append(separator)
                    self.pattern += '%s'
                    separator.prev = left
                    left = separator
                entry.prev = left
                left = entry
            elif right is None:
                if left is not None:
                    self.pattern += '\0    '
                right = entry
                lastright = entry
            else:
                separator = Entry(left = False)
                new_functions.append(separator)
                self.pattern += '%s'
                lastright.prev = separator
                separator.prev = entry
                lastright = entry
            new_functions.append(entry)
            self.pattern += '%s'
        if left is not None:
            self.posupdate.append(left)
        if right is not None:
            self.posupdate.append(right)
        height = (lineno + 1) * G.HEIGHT_PER_LINE
        if G.HEIGHT < height:
            G.HEIGHT = height
        self.functions = new_functions

def colour_interpol(low, high, weight):
    rl, rh = (low >> 16) & 255, (high >> 16) & 255
    gl, gh = (low >>  8) & 255, (high >>  8) & 255
    bl, bh = (low >>  0) & 255, (high >>  0) & 255
    r = int(rl * (1 - weight) + rh * weight)
    g = int(gl * (1 - weight) + gh * weight)
    b = int(bl * (1 - weight) + bh * weight)
    return '38;2;%i;%i;%i' % (r, g, b)