Tags: window manager

在Awesome中怀念八位机

按理说一个窗口管理器是不应该和怀旧小游戏扯上多大关系的,但是在Awesome中这的确发生了。前两天在把玩Awesome的时候发现源代码的icon文件夹里面有一写叫做enemy和player的图片,就像这个样子:
enemy_1.pngenemy_2.pngenemy_3.pngplayer.png
这不禁让人纳闷,难道Awesome里面还有彩蛋之类的程序?搜索了一下发现还真有这么一个东西,这就是invader。

invader是一个用lua脚本写的小游戏,整个代码只有一个五百多行的文件。通过如下方法可以运行它:

$awesome-client
require("invaders")
invaders.run()

游戏显示在桌面背景上,所以如果你当前桌面上开的有窗口的话会把它挡住。你会看到一个类似八位机时代小蜜蜂的游戏。似乎是没有多大用处,但是想想看用lua脚本就可以在桌面上绘制这么些东西,那么完全有可能做出利用Awesome提供的lua库做出很多很有意思的东西出来。现在官方网站上能找到的Awesome的lua脚本还比较少,但是浏览了一下它的lua接口,发现已经有模有样了。如果有足够多的用户为它贡献lua插件的话说不定能发展成一个异常强大且快速的窗口管理器。

Awesome使用&简单配置

默认键位

如果你是一个和我一样懒的人,不介意自己的手指头被默认键位扭曲得像麻花的话,那么完全可以参照我这里给出的部分默认键位的介绍:)

当然你可以通过修改配置文件来更改这些键位。这里的Mod4可以在配置文件中定义,默认是Windows键。

Mod4 + Return
打开一个终端
Mod4 + F1
运行命令
Mod4 + Shift + c
关掉当前窗口
Mod4 + Control + r
重启awesome
Mod4 + Shift + q
退出awesome

Mod4 + j
切换到下一个窗口
Mod4 + k
切换到前一个窗口
Mod4 + Left
查看前一个tag
Mod4 + Right
查看后一个tag
Mod4 + 1-9
切换到tag 1-9
Mod4 + Control + j
切换到下一个屏幕
Mod4 + Control + k
切换到前一个屏幕

Mod4 + Shift + j
当前窗口和前一个窗口互换位置
Mod4 + Shift + k
当前窗口和后一个窗口互换位置
Mod4 + h
把主区域(master width)的宽度增大5%
Mod4 + l
把主区域(master width)的宽度减少5%
Mod4 + Shift + h
增加主区域窗口的数量
Mod4 + Shift + l
减少主区域窗口的数量
Mod4 + Control + h
增加非主区域窗口的数量
Mod4 + Control + l
减少非主区域窗口的数量
Mod4 + space
把当前tag更换为下一种布局
Mod4 + Shift + space
把当前tag更换为前一种布局
Mod4 + Control + space
切换当前窗口是否为浮动的

Mod4 + Shift + i
显示当前窗口的class和instance。这在写脚本的时候尤其有用

Mod4 + Shift + r
重绘当前窗口

配置

修改xinitrc

你已经按照之前的步骤安装上了Awesome。但是你会发现进去以后几乎什么都没有,gnome程序的界面没有了主题变得极其丑陋,屏保也不会自动运行了。其实只需要一些设置你就能让它变得很顺手。

首先我们来修改.xinitrc中的内容。

#!/usr/bin/env bash
sleep 100
xsetroot -solid black &
#启动屏保程序
gnome-screensaver &
#启用gnome的主题,否则你的awesome下的gnome程序会非常难看
gnome-settings-daemon &
#电源管理程序
gnome-power-manager &
#网络管理程序
nm-applet &
#自动更新程序
update-notifier &
exec /usr/local/bin/awesome

编写rc.lua 让我们来点花样

从3.0开始awesome转而使用lua作为配置文件的格式,配置文件位于~/.config/awesome/rc.lua。这一改变极大的增加了awesome的灵活性,但是也让配置文件变的庞大而复杂。

还好lua不是一门很复杂的语言,所以基本上用不着多少关于lua的专门介绍就可以看明白这个配置文件。你可以运行在awesome下面修改配置文件,然后用快捷键ctr-mod4-R来重新读取配置文件。不过要小心的是如果配置文件里面有错的话有可能整个awesome会直接死掉,这时候就只能重启X了…

注意1:以下的讨论仅适用于awesome3.x版本。8.04源里面的2.4版本用的是完全不同配置文件格式,不能和3.0的通用
注意2:Awesome3的配置文件的格式、lua库函数一直都在变动当中,所以以下说的方法可能只适用于一个特定的git仓库中的版本。等到它稳定以后我会重新更新的:)

因为rc.lua实在是很庞大,没办法每一行都介绍它的意思,所以下面只是介绍一下默认的配置文件中的一些比较有用的部分:

杂项

-- 下面这一行指明了当前配置文件使用的主题文件。awesome的主题非常简单,只需要指明几个颜色就可以了
theme_path = "/usr/local/share/awesome/themes/default"

-- 这里设置默认的终端程序。默认的xterm显示中文有问题,我用的是urxvt
terminal = "urxvt"

-- 还记得之前提到的Mod4键么?你可以在这里重新设置它为其他任意一个键
modkey = "Mod4"

浮动窗口

你下载文件时Firefox打开了一个下载窗口,结果它却可怕的占据了屏幕的一半大小,把其他窗口挤得大小便失禁。英明神武的你当然不想这样。解决方法就是把这样的窗口设置为浮动, 在它们启动的时候就自动把他们设置为浮动窗口,这样就不会让你的屏幕天下大乱了.

-- 需要自动设置为浮动的程序
-- 只需要把你想要设置为浮动窗口的程序的Instance或者class按照下面的格式写进去就行
-- 了。在awesome下用Mod4 + Ctr + i就可以看到当前程序的instance和class名字
floatapps =
{
    ["MPlayer"] = true,
    ["gimp"] = true,
    ["smplayer"] = true,
    ["mocp"] = true,
    ["Codeblocks"] = true,
    ["Dialog"] = true,
    ["Download"] = true,
    ["empathy"] = true,
}

-- 把指定的程序自动移动到某个特定的屏幕的某个tag上面
apptags =
{
    ["smplayer"] = { screen = 1, tag = 7 },
    ["amarokapp"] = { screen = 1, tag = 8 },
    ["VirtualBox"] = { screen = 1, tag = 9 },
    ["Firefox"] = { screen = 1, tag = 1},
    ["Thunderbird-bin"] = { screen = 1, tag = 7 },
    ["Linux-fetion"] = { screen = 1, tag = 6 },
}

我要我的tags

如果你觉得默认的9个tag太多或者是太少,或者是觉得不想用1-9这样的数字来作为Tag 的名字的话,往下看:

-- 下面这个循环创建了默认的9个tag
tags = {}
for s = 1, screen.count() do
    -- 每个屏幕都有一个tag的table(这里所说的table指的是lua中的概念,大致等价于数组)
    tags[s] = {}

    -- 每个屏幕创建9个tag,把9改为其他数字就能改变tag的数目
    for tagnumber = 1, 9 do
        tags[s][tagnumber] = tag({ name = tagnumber, layout = layouts[1] })
        tags[s][tagnumber].screen = s
    end
    -- 另最后一个屏幕的第一个tag处于选中状态
    tags[s][1].selected = true
end

-- 默认的tag名字是数字1-9,对于鼠标点击来说有点太小。
-- 你可以通过如下的方法设置自己的tag名称
tags[1][1].name = "Internet"
tags[1][2].name = "Term"
tags[1][3].name = "IRC"
tags[1][4].name = "Tag1"
tags[1][5].name = "Tag2"
tags[1][6].name = "Tag3"
tags[1][7].name = "Email"
tags[1][8].name = "Music"
tags[1][9].name = "Virtual"

时间

第一次用awesome的人肯定会很奇怪屏幕右上角不断增长的数字是什么?我第一次看到它的时候花了很长时间才反应过来它不是CPI。

-- 显示时间
-- 默认显示的是从1970年1月1日到现在经过了多少秒。话说应该没人喜欢这样的时间显示
-- 难道awesome的作者觉得有人可以心算这个数字得到当前的时间? 囧
-- 查找awful.hooks.timer.register这一行,改为如下的设置就可以显示正常的时间了
awful.hooks.timer.register(1, function ()
    mytextbox.text = " " .. os.date() .. " "
end)

开机自动启动

每次开机都重复打开一些程序并且把它们移动到特定的Tag上面是一件很乏味的事情。Awesome并没有提供一个类似gnome的session管理之类的东西,但是我们可以通过修改配置文件来达到开机自动启动程序的目的。

在rc.lua的任意位置添加如下代码:

-- Autorun programs
autorun = "true"
autorunApps =
{
    "firefox",
    "thunderbird",
    "amarok",
    "linux-fetion",
    "amule",
}

if autorun then
    for app = 1, #autorunApps do
        awful.util.spawn(autorunApps[app])
    end
end

其中把autorunApps中的内容替换为你想要运行的程序就可以了。
注意:X下的程序需要在Awesome启动完毕之后再运行,因而不能放在.xinirc中自动启动。另外在rc.lua中也只能通过 awful.util.spawn(“cmd”)的方式来运行程序,其他的方式比如os.execute或者io.popen都会使awesome失去响应,原因还不清楚。

Awesome下wicked库的使用

获取wicked

git clone git://git.glacicle.com/awesome/wicked.git
sudo cp wicked/wicked.lua /usr/share/awesome/lib/
sudo cp wicked/wicked.7.gz /usr/share/man/man7/

在rc.lua中使用wicked

把wicked库装好以后就可以在rc.lua中使用它了,方法如下:

  • 要使用wicked库首先你得在你的rc.lua文件开始处添加对它的引用
  • require("wicked")
  • 然后再把你想要的wicked的widget的代码加进去,例如显示内存的代码如下(其他更多的widget代码在最后列出):
  • memwidget = widget({
        type = 'textbox',
        name = 'memwidget'
    })
    
    wicked.register(memwidget, wicked.widgets.mem,
        ' <span color="white">Memory:</span> $1 ($2Mb/$3Mb)')
    
  • 最后把你要的widget加入到一个已有的wibox或者新创建的wibox中去。比如说我创建了一个在屏幕下沿的状态栏:
  • -- 设置状态栏的位置、颜色
    mystatebar = wibox( {position = "bottom", fg = beautiful.fg_normal, bg = beautiful.bg_normal} )
    -- 把你创建过的widget添加进去,比如说上面所说的memwidget
    mystatebar.widgets = {
        cpugraphwidget,
        memwidget,
        fswidget,
        netwidget
    }
    -- 设置状态栏所在的显示器,对于单显示器的机器来说设置为1就可以了
    mystatebar.screen = 1
    

    各种可用的widget

    wicked提供好几种widget可以使用,包括CPU占用率、内存使用率、文件系统空间、网络传输速率等。 基本上wicked的使用方法就是先调用widget()函数创建一个widget,然后设置好参数调用wicked.register(),最后再创建一个wibox把先前创建的widget放在里面就好了。有的widget不能用,会导致awesome当掉(估计应该是bug)。经过我实验可以用的有:内存占用率、文件系统使用率、网络流量、CPU占用率和CPU图像。

    日期

    在状态栏里面显示现在的时间

    datewidget = widget({
        type = 'textbox',
        name = 'datewidget'
    })
    wicked.register(datewidget, wicked.widgets.date,
        ' <span color="white">Date:</span> %c')
    

    MPD 正在播放

    显示正在Music Playing Daemon中正在播放的歌曲

    mpdwidget = widget({
        type = 'textbox',
        name = 'mpdwidget'
    })
    
    wicked.register(mpdwidget, wicked.widgets.mpd,
        ' <span color="white">Now Playing:</span> $1')

    如果你想要它只是在播放歌曲的时候显示的话,可以把register函数的调用改为如下所示:

    wicked.register(mpdwidget, wicked.widgets.mpd,
    	function (widget, args)
    		   if args[1]:find("volume:") == nil then
    		      return ' <span color="white">Now Playing:</span> '..args[1]
    		   else
                          return ''
                       end
    		end)

    内存监视器

    在状态栏中显示已用/总共的内存量

    memwidget = widget({
        type = 'textbox',
        name = 'memwidget'
    })
    
    wicked.register(memwidget, wicked.widgets.mem,
        ' <span color="white">Memory:</span> $1 ($2Mb/$3Mb)')

    内存占用率进度条

    用一个进度条显示内存的相对使用情况

    membarwidget = widget({
        type = 'progressbar',
        name = 'membarwidget',
        align = 'right'
    })
    
    membarwidget:properties_set('mem', {
    width = 40,
    height = 0.65,
    gap = 0,
    border_padding = 1,
    border_width = 1,
    ticks_count = 0,
    ticks_gap = 0,
    vertical = false
    })
    
    membarwidget:bar_properties_set('mem', {
    bg = '#222222',
    fg = '#285577',
    fg_center = '#285577',
    fg_end = '#285577',
    fg_off = '#222222',
    reverse = false,
    min_value = 0,
    max_value = 100
    })
    
    wicked.register(membarwidget, wicked.widgets.mem, '$1', 1, 'mem')

    CPU占用率

    显示CPU占用率的百分比

    cpuwidget = widget({
        type = 'textbox',
        name = 'cpuwidget'
    })
    
    wicked.register(cpuwidget, wicked.widgets.cpu,
        ' <span color="white">CPU:</span> $1%')

    CPU占用率图像

    用一个图像来显示CPU占用率的变化

    cpugraphwidget = widget({
        type = 'graph',
        name = 'cpugraphwidget',
        align = 'right'
    })
    
    cpugraphwidget.height = 0.85
    cpugraphwidget.width = 45
    cpugraphwidget.bg = '#333333'
    cpugraphwidget.border_color = '#0a0a0a'
    cpugraphwidget.grow = 'left'
    
    cpugraphwidget:plot_properties_set('cpu', {
        fg = '#AEC6D8',
        fg_center = '#285577',
        fg_end = '#285577',
        vertical_gradient = false
    })
    
    wicked.register(cpugraphwidget, wicked.widgets.cpu, '$1', 1, 'cpu')

    文件系统

    显示已用/总共的文件空间,以及百分比

    fswidget = widget({
        type = 'textbox',
        name = 'fswidget'
    })
    
    wicked.register(fswidget, wicked.widgets.fs,
        ' <span color="white">FS:</span> ${/ used}/${/ size} (${/ usep} used)', 120)

    网络监视器

    显示eth0的网络流量

    netwidget = widget({
        type = 'textbox',
        name = 'netwidget'
    })
    
    wicked.register(netwidget, wicked.widgets.net,
        ' <span color="white">NET</span>: ${eth0 down} / ${eth0 up} [ ${eth0 rx} //  ${eth0 tx} ]',
    nil, nil, 3)

    电池电量

    显示电池的电量

    settings.batteries = 2
    
    -- Label
    batterywidget = widget({type = 'textbox',
                            name = 'batterywidget',
                            align = 'right'})
    wicked.register(batterywidget, function() return {} end,
                    settings.widget_separator ..
                       beautiful.markup.heading('Bat') ..
                    settings.widget_spacer,
                    nil, nil, 500)
    table.insert(settings.widgets, {1, batterywidget})
    
    -- Function to extract charge percentage
    function read_battery_life(number)
       return function(format)
                 local fh = io.popen('acpi')
                 output = fh:read("*a")
                 fh:close()
    
                 count = 0
                 for s in string.gmatch(output, "(%d+)%%") do
                    if number == count then
                       return {s}
                    end
                    count = count + 1
                 end
              end
    end
    
    -- Display one vertical progressbar per battery
    for battery=0, settings.batteries-1 do
       batterygraphwidget = widget({ type = 'progressbar',
                                     name = 'batterygraphwidget',
                                     align = 'right' })
       batterygraphwidget.height = 0.85
       batterygraphwidget.width = 8
       batterygraphwidget.bg = '#333333'
       batterygraphwidget.border_color = '#0a0a0a'
       batterygraphwidget.vertical = true
       batterygraphwidget:bar_properties_set('battery',
                                             { fg = '#AEC6D8',
                                               fg_center = '#285577',
                                               fg_end = '#285577',
                                               fg_off = '#222222',
                                               vertical_gradient = true,
                                               horizontal_gradient = false,
                                               ticks_count = 0,
                                               ticks_gap = 0 })
    
       wicked.register(batterygraphwidget, read_battery_life(battery), '$1', 1, 'battery')
       table.insert(settings.widgets, {1, batterygraphwidget})
    
       spacewidget = widget({type = 'textbox',
                               name = 'spacewidget',
                               align = 'right'})
       wicked.register(spacewidget, function() return {} end,
                       settings.widget_spacer,
                       nil, nil, 500)
       table.insert(settings.widgets, {1, spacewidget})
    end

    Awesome编译

    由于Awesome依赖的包还没有进入稳定版本,所以ubuntu的源里面仍然还是老旧的2.4版,ArchLinux也只是在test源里面才有3.0版。想要得到最新的Awesome的话就得自己从源代码编译。下面给出ubuntu下编译Awesom3.x的方法。

    官方wiki中的编译指南地址:

    http://awesome.naquadah.org/wiki/index.php?title=Awesome-3-Ubuntu-git

    http://awesome.naquadah.org/wiki/index.php?title=Awesome-3-git-Ubuntu-Intrepid

    Ubuntu8.10和8.04的编译步骤有点不同,这里只给出8.10的编译步骤:

    1)确定已经安装了编译用的工具

    $ sudo apt-get install build-essential autoconf automake libtool gperf xmlto$ sudo apt-get install dpatch fakeroot git git-core debhelper


    2)安装awesome编译所需要的X.org包

    $ sudo apt-get install libx11-dev libxinerama-dev libxrandr-dev
    libpango1.0-dev libimlib2-dev libgtk2.0-dev libxcb-shm0-dev
    libxcb-render0-dev  libxcb-randr0-dev libxcb-shape0-dev
    libcairo2-dev libxcb-xinerama0-dev liblua5.1-filesystem0
    liblua5.1-logging libdirectfb-dev libxt-dev libx11-xcb-dev cmake
    lua5.1 liblua5.1-0-dev libev3 libev-dev luadoc liblua5.1-doc0 libxcb-aux0


    3)安装asciidoc(可选, 如果你不需要创建文档的话可以跳过这步)
    Optionally you should get asciidoc (to build documentations and developer reference)

    $ sudo apt-get install asciidoc


    4)编译依赖库
    下载并编译xcb-util:

    $ git clone git://anongit.freedesktop.org/git/xcb/util$ cd util && ./autogen.sh && make && sudo make install


    5)编译awesome

    $ git clone git://git.naquadah.org/awesome.git$ cd awesome && make && sudo make install


    6)创建~/.xinitrc并且链接到~/.Xsession

    ~/.xinitrc中内容如下:

    #!/usr/bin/env bashxsetroot -solid black &exec /usr/local/bin/awesome

    创建一个从.xinitrc到.Xsession的软链接

    ln -s ~/.xinitrc ~/.Xsession


    7)大功告成。你只需要在登录界面选择’Sessions’,并且在列表中选择’Xsession’。照常登录就能运行.xinitrc中的内容进入awesome了。