首页 > 代码库 > Linux窗口管理器——Qtile之初体验

Linux窗口管理器——Qtile之初体验

Tiling window manager——平铺式窗口管理器,不同于浮动式那样以层的形式管理窗口,平铺式将所有窗口平铺开来,窗口之间无缝对接,这有助于同时查看多个窗口的内容,对于程序员来说这尤其有用。

平铺式窗口管理器有很多,比较有名的像awesome,i3等等,不过awesome是以lua语言写的,我没用过,对此不做介绍。而qtile是以纯Python写的,作为一个Python迷(虽然海是菜鸟中的菜鸟),我自然选择qtile。

Qtile的官网:http://www.qtile.org

Qtile的图形对象(object graph)共七个部分:layouts、windows、screen、groups、bars、widgets还有一个root。

layouts:布局,以什么方式来分布窗口,包括Max(单窗口占据整个屏幕)、Tiling(按比例分配窗口)、Floationg(浮动窗口)、MonadTall(模拟XMonad的平铺式窗口)、Slice、Stack(将屏幕分成多个栈),TreeTab、Zoomy

groups:相当于其他桌面环境的工作区。

screens:物理屏幕

bar:栏,可以理解为任务栏

widget:小工具,组件,包括很多,像是时间,天气,邮件查看,任务列表,groupbox等等。。。


安装qtile的方法可以参考官网,不过我当时照着官网编译的时候提示错误,是一个ImportError,好像是说缺少某个模块,不过这个模块我没有找到。。。后来在google了一番后,找到如下的解决方法:

pip install cffi
pip install xcffib
git clone -b xcb https://github.com/flacjacket/cairocffi.git
cd cairocffi && sudo python setup.py install
git clone git://github.com/qtile/qtile.git
cd qtile
sudo python setup.py install

貌似是作者把几个模块编译到了一起。。。


关于配置文件的写法官网上提供了很多,既有默认配置,也有其他用户写的配置,可以借鉴后使用。之后我会给出我的配置,不过就是并不好。

详细的内容可以看官方文档,不过官方文档并不全面,很多配置都未提到。尤其是关于windows(窗口对象)方面的,除了官方默认配置外,其他用户的配置都用到了windows方面的内容。我谷歌、度娘了半天,一无所获(也可能是我查的方式不对)。看来可能要直接看源代码了。。。


刚才传了一下,好像不怎么好上传,现直接贴出配置文件:

#!/usr/bin/env python
#-*-coding:utf-8-*-

import os

from libqtile import layout,widget,bar,manager,hook
from libqtile.widget import base
from libqtile.manager import Screen,Drag
from libqtile.command import lazy
try:
    from libqtile.manager import Key,Group
except ImportError:
    from libqtile.config import Key,Group

sup=‘mod4‘
alt=‘mod1‘

#键位映射
keys=[
    #Layout
    Key([sup],‘Down‘,lazy.layout.down()),
    Key([sup],‘Up‘,lazy.layout.up()),
    Key([alt],‘Tab‘,lazy.layout.next()),
    Key([alt,‘shift‘],‘Tab‘,lazy.layout.previous()),
    Key([sup],‘space‘,lazy.nextlayout()),
    Key([sup],‘k‘,lazy.layout.increase_ratio()),
    Key([sup],‘j‘,lazy.layout.decrease_ratio()),
    Key([sup],‘l‘,lazy.layout.increase_nmaster()),
    Key([sup],‘h‘,lazy.layout.decrease_nmaster()),

    #Window
    Key([alt],‘F4‘,lazy.window.kill()),
    Key([alt],‘F10‘,lazy.window.toggle_maximize()),

    #Group
    Key([sup],‘Left‘,lazy.group.prevgroup()),
    Key([sup],‘Right‘,lazy.group.nextgroup()),


    #Application launchers
    Key([sup],‘Return‘,lazy.spawn(‘sakura‘)),
    Key([sup],‘f‘,lazy.spawn(‘firefox‘)),
    Key([sup],‘m‘,lazy.spawn(‘vlc‘)),
    Key([sup],‘v‘,lazy.spawn(‘virtualbox‘)),
    Key([sup],‘t‘,lazy.spawn(‘Thunar‘)),
    Key([sup],‘q‘,lazy.spawn(‘QQ‘)),
    Key([sup],‘z‘,lazy.spawn(‘zim‘)),

    #Audio
    Key([sup],‘F8‘,lazy.spawn(‘amixer --quiet set Master mute‘)),
    Key([sup],‘F9‘,lazy.spawn(‘amixer --quiet set Master unmute‘)),
    Key([alt],‘minus‘,lazy.spawn(‘amixer --quiet set Master 2dB-‘)),
    Key([alt,‘shift‘],‘equal‘,lazy.spawn(‘amixer --quiet set Master 2dB+‘)),

    #restart qtile
    Key([sup],‘r‘,lazy.restart()),
    #shutdown
    Key([sup,‘shift‘],‘q‘,lazy.spawn(‘shutdown -h now‘)),

    #interact with prompts:
    Key([sup],‘s‘,lazy.spawncmd()),    
]

mouse=[
    Drag([sup],"Button1",lazy.window.set_position_floating(),
        start=lazy.window.get_position()),
    Drag([sup],"Button3",lazy.window.set_size_floating(),
        start=lazy.window.get_size()),
]

#建立groups
group_names=[
    ("code1",{‘layout‘:‘tile‘}),
    ("code2",{"layout":‘tile‘}),
    ("web",{"layout":"max"}),
    ("vbox",{"layout":"max"}),
    (‘music‘,{‘layout‘:‘max‘}),
    (‘doc‘,{‘layout‘:‘max‘}),
    (‘chat‘,{‘layout‘:‘max‘})
]

groups=[Group(name,**kwargs) for name,kwargs in group_names]

for i , (name,kwargs) in enumerate(group_names,1):
    keys.append(Key([sup],str(i),lazy.group[name].toscreen()))
    keys.append(Key([sup,‘shift‘],str(i),lazy.window.togroup(name)))

#建立layouts
layouts=[
    layout.Tile(border_focus=‘#196ff2‘,border_width=1),
    layout.Max()
]



font=‘WenQuanYi Micro Hei‘
fontsize=16
foreground=‘#FFFFFF‘
background=‘#000000‘


def humanize_bytes(value):
    suff=[‘B‘,‘K‘,‘M‘,‘G‘,‘T‘]
    while value > 1024. and len(suff)>1:
        value/=1024.
        suff.pop(0)
    return "% 3s%s" %(‘%.3s‘%value,suff[0])


#本来这个是用来显示CPU、Mem、Net的情况,后来不知为何无法显示
class Metrics(base._TextBox):
    
    defaults=[
        (‘font‘,‘Arial‘,‘Metrics font‘),
        (‘fontsize‘,None,‘Metircs pixel size‘),
        (‘pading‘,None,‘Metrics padding‘),
        (‘background‘,‘00000‘,‘background color‘),
        (‘foreground‘,‘ffffff‘,‘foreground color‘)
        ]


    def __init__(self,**kwargs):
        base._TextBox.__init__(self,**kwargs)
        self.cpu_usage,self.cpu_total=self.get_cpu_stat()
        self.interfaces={}
        self.idle_ifaces={}

    def _configure(self,qtile,bar):
        base._TextBox._configure(self,qtile,bar)
        self.timeout_add(0,self._update)

    def get_cpu_stat(self):
        stat=[int(i) for i in open(‘/proc/stat‘).readline().split()[1:]]
        return sum(stat[:3]),sum(stat)

    def get_cpu_usage(self):
        new_cpu_usage,new_cput_total=self.get_cpu_stat()
        cput_usage=new_cpu_usage-self.cpu_usage
        cpu_total=new_cpu_total-self.cpu_total
        self.cpu_usage=new_cpu_usage
        self.cpu_tptal=new_cpu_total
        return ‘Cpu: %d%%‘ % (float(cpu_usage)/float(cpu_total)*100.)

    def get_mem_usage(self):
        info={}
        for line in open(‘/proc/meminfo‘):
            key,val=line.split(‘:‘)
            info[key]=int(val.spilt()[0])
        mem=info[‘MemTotal‘]
        mem-=info[‘MemFree‘]
        mem-=info[‘Buffers‘]
        mem-=info[‘Cached‘]
        return ‘Mem: %d%%‘ % (float(mem)/float(info[‘MemTotal‘])*100)

    def get_net_usage(self):
        interfaces=[]
        basedir=‘/sys/class/net‘
        for iface in os.listdir(basedir):
            j=os.path.join
            ifacedir=j(basedir,iface)
            statdir=j(ifacedir,‘statistics‘)
            idle=iface in self.idle_ifaces
            try:
                if int(open(j(ifacedir, ‘carrier‘)).read()):
                    rx = int(open(j(statdir, ‘rx_bytes‘)).read())
                    tx = int(open(j(statdir, ‘tx_bytes‘)).read())
                    if iface not in self.interfaces:
                        self.interfaces[iface] = (rx, tx)
                    old_rx, old_tx = self.interfaces[iface]
                    self.interfaces[iface] = (rx, tx)
                    rx = rx - old_rx
                    tx = tx - old_tx
                    if rx or tx:
                        idle = False
                        self.idle_ifaces[iface] = 0
                        rx = humanize_bytes(rx)
                        tx = humanize_bytes(tx)
                        interfaces.append(‘%s: %s / %s‘ % (iface, rx, tx))
            except:
                pass
            if idle:
                interfaces.append(‘%s: %-11s‘ % (iface, ("%ds idle" % self.idle_ifaces[iface]))
                )
                self.idle_ifaces[iface] += 1
                if self.idle_ifaces[iface] > 30:
                    del self.idle_ifaces[iface]
        return " | ".join(interfaces)
    

    def _update(self):
        self.update()
        self.timeout_add(1, self.update)
        return False

    def update(self):
        stat = [self.get_cpu_usage(), self.get_mem_usage()]
        net = self.get_net_usage()
        if net:
            stat.append(net)
        self.text = " | ".join(stat)
        self.bar.draw()
        return True


screens=[
    Screen(top=bar.Bar([
        widget.TextBox(text=‘◤ ‘,fontsize=40,foreground=‘#323335‘,padding=0),
        widget.GroupBox(font=font,fontsize=fontsize,active=foreground,inactive="#808080",borderwidth=3),
        widget.Prompt(font=font,fontsize=fontsize),
        widget.CurrentLayout(font=font,foreground=foreground,fontsize=fontsize),
        widget.Sep(foreground=background,linewidth=3),
        widget.WindowName(font=font,fontsize=fontsize,foreground=foreground),
        widget.Notify(font=font,fontsize=fontsize),
        Metrics(font=font,fontsize=fontsize,foreground=foreground),
        widget.Volume(foreground="#70ff70"),
        widget.BatteryIcon(),
        widget.Systray(icon_size=18),
        widget.Clock(font=font,fontsize=fontsize,foreground=foreground,fmt=‘%Y-%m-%d %a %H:%M‘),
    ],30))
]


@hook.subscribe.client_new
def dialogs(window):
    if(window.window.get_wm_type() == ‘dialog‘
        or window.window.get_wm_transient_for()):
        window.floating = True


本文出自 “莲的思念” 博客,请务必保留此出处http://liandesinian.blog.51cto.com/7737219/1552667

Linux窗口管理器——Qtile之初体验