aboutsummaryrefslogblamecommitdiffstats
path: root/src/__main__.py
blob: 83d45f757b91b048ebb19b64cd143f5e093f3860 (plain) (tree)
1
2
3
4
5
6
7
8
9
                      


                                                            
 



                                                                    
 



                                                               
 


                                                                     
 
                                                       
 
               
 
 



                                                              



                                                   

             

                                        






                                                          
                                        







                                                                      
                                        



               








                                                
 













































































                                                                                                                                                  

                               





































                                                                              








                                                                                
 
 


                          
        
                       
                        
       
 




                                          

                              

                             
            
                   
 
      
         
 
#!/usr/bin/env python3
'''
xpybar – xmobar replacement written in python
Copyright © 2014  Mattias Andrée (maandree@member.fsf.org)

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
'''

import Xlib.display, Xlib.Xatom, Xlib.ext.randr, Xlib.X

from x import *


global OUTPUT, HEIGHT, YPOS, TOP, FONT, BACKGROUND, FOREGROUND
global dislay, outputs, redraw, Bar, start, stop

OUTPUT, HEIGHT, YPOS, TOP = 0, 12, 0, True
FONT = '-misc-fixed-*-*-*-*-10-*-*-*-*-*-*-*'
BACKGROUND, FOREGROUND = (0, 0, 0), (192, 192, 192)


def redraw():
    '''
    Invoked when redraw is needed,
    feel free to replace this completely
    '''
    global bar
    bar.clear()

def start():
    '''
    Invoked when it is time to create panels and map them,
    feel free to replace this completely
    '''
    global bar
    bar = Bar(OUTPUT, HEIGHT, YPOS, TOP, FONT, BACKGROUND, FOREGROUND)
    bar.map()

def stop():
    '''
    Invoked when it is time to unmap the panels,
    feel free to replace this completely
    '''
    global bar
    bar.unmap()

def unhandled_event(e):
    '''
    Invoked when an unrecognised even is polled,
    feel free to replace this completely
    
    @param  e  The event
    '''
    pass


class Bar:
    '''
    Docked panel
    
    @variable  window            The X window
    @variable  gc                The window's graphics context
    @variable  cmap              The window's colour map
    
    @variable  width:int         The output's pixel width
    @variable  height:int        The output's pixel height
    @variable  left:int          The output's left position
    @variable  ypos:int          The position of the panel in relation to either the top or bottom edge of the output
    @variable  panel_height:int  The panel's height
    @variable  at_top:bool       Whether the panel is to be docked to the top of the output, otherwise to the bottom
    
    @variable  background        The default background
    @variable  foreground        The default foreground
    @variable  font              The default font
    @variable  font_metrics      The default font's metrics
    @variable  font_height:int   The height of the default font
    '''
    
    def __init__(self, output, height, ypos, top, font, background, foreground):
        '''
        Constructor
        
        @param  output:int                                 The index of the output within the screen as printed by xrandr, except primary is first
        @param  height:int                                 The height of the panel
        @param  ypos:int                                   The position of the panel in relation the either the top or bottom edge of the output
        @param  top:int                                    Whether the panel is to be docked to the top of the output, otherwise to the bottom
        @param  font:str                                   The default font
        @param  background:(red:int, green:int, blue:int)  The default background
        @param  foreground:(red:int, green:int, blue:int)  The default foreground
        '''
        ## Panel position
        pos = outputs[output][:3] + [ypos, height, top]
        self.width, self.height, self.left, self.ypos, self.panel_height, self.at_top = pos
        ## Create window and create/fetch resources
        self.window = create_panel(*pos)
        self.gc = self.window.create_gc()
        self.cmap = self.window.get_attributes().colormap
        ## Graphics variables
        self.background = self.create_colour(*background)
        self.foreground = self.create_colour(*foreground)
        (self.font, self.font_metrics, self.font_height) = self.create_font(font)
    
    def map(self):
        '''
        Map the window
        '''
        self.window.map()
        display.flush()
    
    def unmap(self):
        '''
        Unmap the window
        '''
        self.window.unmap()
    
    def text_width(self, text):
        '''
        Get the width of a text
        
        @param   text:str  The text
        @return  :int      The width of the text
        '''
        return self.font.query_text_extents(text).overall_width
    
    def draw_text(self, x, y, text):
        '''
        Draw a text
        
        @param  x:int     The left position of the text
        @param  y:int     The Y position of the bottom of the text
        @param  text:str  The text to draw
        '''
        draw_text(bar.window, bar.gc, x, y, text)
    
    # TODO add draw_colour_text
    
    def create_colour(self, red, green, blue):
        '''
        Create a colour instance
        
        @param   red:int    The red component [0, 255]
        @param   green:int  The green component [0, 255]
        @param   blue:int   The blue component [0, 255]
        @return             The colour
        '''
        return self.cmap.alloc_color(red * 257, green * 257, blue * 257).pixel
    
    def create_font(self, font):
        '''
        Create a font
        
        @param   font:str  The font
        @return            The font, font metrics, and font height
        '''
        font = display.open_font(font)
        font_metrics = font.query()
        font_height = font_metrics.font_ascent + font_metrics.font_descent
        return (font, font_metrics, font_height)
    
    def change_colour(self, colour):
        '''
        Change the current colour
        
        @param  colour  The colour
        '''
        self.gc.change(foreground = colour)
    
    def change_font(self, font):
        '''
        Change the current font
        
        @param  font  The font
        '''
        self.gc.change(font = font)
    
    def clear(self):
        '''
        Fill the panel with its background colour and reset the colour and font
        '''
        self.change_colour(self.background)
        self.window.fill_rectangle(self.gc, 0, 0, self.width, self.panel_height)
        self.change_colour(self.foreground)
        self.change_font(self.font)


# TODO load configurations


open_x()
display = get_display()
outputs = get_monitors()
start()

while True:
    try:
        e = display.next_event()
        if e.type == Xlib.X.DestroyNotify:
            break
        else:
            unhandled_event(e)
    except KeyboardInterrupt:
        break
    redraw()
    display.flush()

stop()
close_x()