# -*- python -*- ''' xpybar – xmobar replacement written in python Copyright © 2014, 2015, 2016, 2017, 2018, 2019 Mattias Andrée (m@maandreese) 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 . ''' # A xpybar configuration example when application launchers import os import sys import time from plugins.image import Image from plugins.application import Application OUTPUT, HEIGHT, YPOS, TOP = 0, 24, 24, True Image.theme_preferences = ['hicolor', 'mate', 'gnome', 'Adwaita', ..., 'ContrastHigh'] class Launcher: def __init__(self, icon, *command): self.icon = Image(icon, height = HEIGHT, icon = '/' not in icon) self.command = list(command) def launch(self): if os.fork() == 0: if os.fork() == 0: os.setpgrp() os.execvp(self.command[0], self.command) sys.exit(0) def scroll_up(self): pass def scroll_down(self): pass class LauncherSet: def __init__(self, launchers): self.launchers = [Launcher(x[0], *x[1:]) for x in launchers] self.current = 0 self.icon = self.launchers[self.current].icon def launch(self): self.launchers[self.current].launch() def scroll_up(self): self.current = (self.current - 1) % len(self.launchers) self.icon = self.launchers[self.current].icon bar.invalidate() def scroll_down(self): self.current = (self.current + 1) % len(self.launchers) self.icon = self.launchers[self.current].icon bar.invalidate() def desktop(file): application = Application(file) icon = application.get_setting('Icon') command = Application.strip_placeholders(application.get_setting('Exec')) return (icon, 'sh', '-c', command) launchers = [ [ ('accessories-calculator', 'mate-calc') , ('accessories-character-map', 'mucharmap') , ('scanner', 'simple-scan') , ('meld', 'meld') ] , [ ('dia', 'dia') , desktop ('inkscape') , desktop ('gimp') , ('calligrakrita', 'krita') , ('blender', 'blender') , ('/usr/share/pixmaps/openscad.png', 'openscad') ] , [ ('emacs', 'emacs') , ('audacity', 'audacity') , ('/usr/share/ardour4/icons/ardour_icon_48px.png', 'ardour4') ] , [ ('vlc', 'vlc') , ('deluge', 'deluge') , ('/usr/share/pixmaps/amule.xpm', 'amule') ] , ('claws-mail', 'claws-mail') , [ ('terminator', 'terminator') , ('cool-retro-term', 'cool-retro-term') , ('/usr/share/pixmaps/xterm-color_48x48.xpm', 'xterm') ] ] launchers = [Launcher(x[0], *x[1:]) if isinstance(x, tuple) else LauncherSet(x) for x in launchers] start_ = start def start(): start_() def reaper(): while True: try: os.wait() except: time.sleep(3) xasync(reaper, name = 'reaper') def redraw(): bar.clear() offset = 0 for launcher in launchers: launcher.icon.draw(bar, offset, 0) offset += HEIGHT LEFT_BUTTON = 1 RIGHT_BUTTON = 3 SCROLL_UP = 4 SCROLL_DOWN = 5 def unhandled_event(e): ''' Invoked when an unrecognised even is polled, feel free to replace this completely @param e The event ''' if isinstance(e, Xlib.protocol.event.ButtonPress): x = e.event_x // HEIGHT button = e.detail if 0 <= x < len(launchers): if button == LEFT_BUTTON: launchers[x].launch() elif button == RIGHT_BUTTON: launchers[x].scroll_down() elif button == SCROLL_UP: launchers[x].scroll_up() elif button == SCROLL_DOWN: launchers[x].scroll_down() # TODO support for dropping files onto the launchers to open with those files would be nice