什么是窗口管理器?
这里首先需要解释一下窗口管理器(Windows Manager)和桌面环境(Desktop Environment)的概念。窗口管理器负责绘制窗口的边框,处理窗口运行比如移动、最小化之类的行为。而桌面环境则是窗口管理器的超集,它使用窗口管理器及其其他软件提供一个完整的工作环境。比如说,gnome就是一个桌面环境,默认使用Metacity作为窗口管理器。
什么是平铺式窗口管理器?
那么什么是平铺式窗口管理器?简单来说,所谓的平铺就是之所有的窗口都不会相互重叠,而是 自动的 被调整大小使得它们能够刚好占满整个屏幕。
以往的窗口管理器大多是浮动式窗口管理器,由于屏幕空间有限,当前激活的窗口会浮在最上面,而遮住下面的窗口。如果你同时打开了多个窗口并进行操作,那么你就需要不停的按Alt+Tab来回切换,这有时会让人感到眼花缭乱。

浮动式窗口管理器的问题
如果窗口之间不遮掩,那么就没有了这个问题。当然,手动调整窗口大小和位置可以达到这个效果,但这绝对不会是一件让人喜欢干的事情。于是Compiz、KDE,甚至Windows 7之后的窗口管理器都提供了粘性窗口,可以让窗口在靠近边缘的时候铺满半屏或满屏,如下面这张图:

粘性窗口
但这种做法仍然有不足之处:
- 只能平铺不多于两个窗口,如果当前有三个以上的窗口的时候,依然会存在遮掩。对此,Compiz的解决方式是自动将被遮掩的窗口移动到其他桌面,但相信不止我一个人曾被这种古怪的设计搞晕。
- 仍然需要用鼠标手动平铺,这对于正在高速敲键盘的码农而言,无疑是“超音速飞机的紧急迫降”。
平铺式窗口管理器就是针对这种需求提出的窗口管理器,它可以帮助用户将多个窗口按照某种布局方式来平铺在一起。可以看看这张图:

平铺式窗口管理器
并且,用它来调整、切换窗口几乎可以不使用鼠标。这对于硬派的linux狂热者以及痛恨使用笔记本触控板的人来说也是一个不错的选择。
为什么是Awesome?
平铺式窗口管理器并不是一个新概念,在施乐公司几十年前最早开始研究图形界面的时候就已经有了平铺的概念了(尽管和现在我说的不太一样),linux下面也有不少成熟的平铺式窗口管理器–Ion, XMonad都是有名的平铺窗口管理器。但是比较之下Awesome有不少鲜明的特点:
- 体积小,运行迅速,占用资源少。不过在3.0以后的版本似乎向变得巨大和缓慢的方向发展的趋势。
- 支持多种窗口布局。Awesome并不仅仅支持平铺,它还支持好几种各不相同的窗口布局方案。
- 使用Lua脚本的配置文件,灵活性高。由于lua脚本的强大能力,Awesome 3.0甚至把窗口管理器运行的逻辑部分放到了配置文件里面。好处是这使得很多其他窗口管理器里面不可能做到的用法在这里变成了可能,坏处是配置文件及其庞大和复杂。
- 更新迅速。它的作者一直在不停地完善Awesome,每次版本升级都能带来一些方便的新特性。不过弊端是造成了Awesome的配置文件一直都在改变,说不定什么时候自己以前的配置文件就不能用了。
- 良好的鼠标支持。比起其他平铺式窗口管理器,Awesome的一大优势是它能够提供良好的鼠标支持。只要你喜欢,Awesome完全可以当作一个浮动窗口管理器来使用,但对于键盘控而言,真正吸引他们的当然是Awesome强大的键盘控制能力。
- 多显示器支持。Awesome支持多显示器间的窗口管理,这是官网上的一张照片:

Awesome 的多显示器支持
总而言之,对于喜欢折腾自己电脑的人来说,Awesome是一个很不错的玩具。
安装Awesome
Awesome一个最新的稳定版本(3.4.11)已经包含在Ubuntu 12.04的源里,因此对于Ubuntu 12.04的用户,安装Awesome非常简单:
| 1 | $ sudo apt-get install awesome | | — | — |
如果需要编译安装Awesome,请参考Awesome的官方wiki编译指南。
Awesome提供了一个设置文件 rc.lua ,放在 /etc/xdg/Awesome/ 里,需要把它拷贝到~/.config/Awesome/里。
Awesome初窥
切换Awesome
安装完Awesome后,注销当前用户回到用户选择界面,然后选择使用Awesome桌面环境。对于Ubuntu用户,在用户选择菜单的右上角有一个按钮,点击之后会打开一个桌面环境选择菜单,选择“Awesome”登陆即可。
状态栏
第一次启动Awesome后会发现整个屏幕只有一个空空的桌面和顶部的一条类似Windows任务栏的东西。这条任务栏叫做状态栏(Status Bar)。
主菜单
状态栏的最左侧是Awesome的图标,点击它将会打开一个小菜单,这就是Awesome的主菜单,再点击一次图标就可以将这个菜单关闭。
标签
在Awesome图标的右侧可以看到阿拉伯数字1-9,这些叫做标签(Tag),类似GNome或者KDE下的虚拟桌面。
布局切换器
在状态栏最右侧是布局切换器,布局(Layout)是根据屏幕上的可用空间来调整窗口位置、尺寸的方式。Awesome支持多种布局:
- 平铺
Tiled平铺模式下屏幕被分为master和stacking两个区域。master中的窗口包含了需要最多关注的窗口(通常这表示master中的窗口会占据更大的屏幕空间),而stacking区域中包含了其它窗口。如果你想的话master区域可以被划分为多行和多列。
- 最大化 Max
每个窗口都是全屏显示。
- 放大 Magnifier
当前窗口(也就是被鼠标点选中,正在操作的窗口)会显示在屏幕中间,占据大部分屏幕空间。剩下的窗口都处在stacking区域,并放到当前窗口的后面。
- 浮动 Floating
每个窗口都可以自由的移动和调整大小,就好像普通的窗口管理器一样。无论当前是什么布局,对话框窗口总是处在浮动状态。
- 螺旋 Spiral
和平铺有点类似,但窗口的调整采用了螺旋形的排列方式。
常用快捷键
下面是常用的一些快捷键组合。注意:在默认情况下,Mod4被映射到Win键,即Ctrl和Alt中间夹着的那个Windows徽标键,它可以根据你的喜好来更改。
| 快捷键 | 功能 |
|---|---|
| Mod4 + Enter | 打开终端 |
| Mod4 + r | 执行程序或命令 |
| Mod4 + w | 打开Awesome主菜单(鼠标右键关闭) |
| 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 | 把主区域的宽度增大5% |
| Mod4 + l | 把主区域的宽度减少5% |
| Mod4 + m | 最大化窗口 |
| Mod4 + n | 最小化窗口 |
| Mod4 + Shift + h | 增加主区域窗口的数量 |
| Mod4 + Shift + l | 减少主区域窗口的数量 |
| Mod4 + Space | 切换窗口布局 |
| Mod4 + Shift + space | 把当前tag更换为前一种布局 |
| Mod4 + Control + space | 切换当前窗口是否为浮动 |
| Mod4 + Shift + i | 显示当前窗口的Class和instance,这在写脚本的时候尤其有用 |
| Mod4 + Shift + r | 重绘当前窗口 |
| Mod4 + t | 标记窗口(可标记多个) |
| Mod4 + Shift + F1~F9 | 把标记的窗口移动到第1~9个标记上 |
| Ctrl + Mod4 + 1~9 | 把当前桌面和1~9桌面是显示 |
| Mod4 + 1~9 | 恢复 |
| Mod4 + Esc | 快速切换到上一个桌面 |
定制Awesome
由于 Awesome 更新的幅度较大,下面的一些配置已经过时。我的最新配置放在 github 。
找回Gnome的指示器
第一次启动,会发现原本Gnome下的电源管理指示器、网络指示器都不见了,还有Gnome程序的主题变得很难看。
如果是使用startx/slim等命令来启动X的,可以通过修改 ~/.xinitrc 来解决这些问题。参考这个例子:
#!/bin/sh #启用gnome的主题 gnome-settings-daemon & #电源管理程序 gnome-power-manager & #网络管理程序 nm-applet –sm-disable & #自动更新程序 update-notifier & exec awesome
完成后重启一下,看看网络指示器是不是回来了。
如果是用kdm/gdm/…等工具来登录管理器的话,这时应该修改的是 ~/.xprofile 里的内容。因为系统默认将执行 ~/.xprofile 文件的命令,而会忽略 ~/.xinitrc 。将上面的内容保存成 ./xprofile 文件即可,或者干脆使用下面这条命令:
$ ln -s ~/.xinitrc ~/.xprofile
将.xprofile链接到.xinitrc上。
定制布局和标签
定制布局
如果希望改变默认的布局和修改布局的切换顺序,可以通过修改 rc.lua 文件来实现。找到像这样的一段代码:
layouts = { awful.layout.suit.floating, awful.layout.suit.tile, awful.layout.suit.tile.left, awful.layout.suit.tile.bottom, awful.layout.suit.tile.top, awful.layout.suit.fair, awful.layout.suit.fair.horizontal, awful.layout.suit.spiral, awful.layout.suit.spiral.dwindle, awful.layout.suit.max, awful.layout.suit.max.fullscreen, awful.layout.suit.magnifier }
这是所有Awesome提供的布局方案,并且是按切换顺序排列的。可以通过调整顺序来改变实际的布局切换顺序。如果不喜欢其中的一些布局方案,你可以把相应的代码给去掉。比如,对于我而言,全屏、放大和螺旋式布局都是不常用的,并且我希望第一个布局是平铺,而不是浮动,因此可以改成:
layouts = { awful.layout.suit.tile, awful.layout.suit.tile.left, awful.layout.suit.tile.bottom, awful.layout.suit.tile.top, awful.layout.suit.fair, awful.layout.suit.fair.horizontal, awful.layout.suit.floating, awful.layout.suit.max }
完成后保存修改,然后按 Mod4 + Control + r 重启 Awesome看看变化。
浮动窗口
有些程序的窗口不适合采用平铺的方式,比如Firefox的下载窗口,或者Gimp的图层窗口、工具栏窗口等,这时候我们希望将这样的窗口设置为浮动:
– 需要自动设置为浮动的程序 – 只需要把你想要设置为浮动窗口的程序的Instance或者class按照下面的格式写进去就行 – 了。在awesome下用Mod4 + Ctr + i就可以看到当前程序的instance和class名字 awful.rules.rules = { – All clients will match this rule. {rule = {}, properties = {border_width = beautiful.border_width, border_color = beautiful.border_normal, focus = true, keys = clientkeys, buttons = clientbuttons}}, {rule = {class = “MPlayer”}, properties = {floating = true}}, {rule = {class = “Smplayer”}, properties = {floating = true, tag = tags[1][6]}}, { rule = { class = “pinentry” }, properties = { floating = true } }, { rule = { class = “gimp” }, properties = { floating = true } }, {rule = {class = “Firefox”}, properties = {tag = tags[1][1]}}, {rule = {class = “Firefox”, name = “Download”}, properties = {floating = true}}, {rule = {class = “VirtualBox”}, properties = {floating = true, tag = tags[1][2]}}, – Set Firefox to always map on tags number 2 of screen 1. – { rule = { class = “Firefox” }, – properties = { tag = tags[1][2] } }, }
定制标签
只要你愿意,你可以为每一个标签命名,并为每一个标签设置默认布局。这是 rc.lua 里默认的标签设置:
– Define a tag table which hold all screen tags. tags = {} for s = 1, screen.count() do – Each screen has its own tag table. tags[s] = awful.tag({ 1, 2, 3, 4, 5, 6, 7, 8, 9 }, s, layouts[1]) end
现在我们可以改变每个标签的名字,并为每一个设置默认布局。参考下面这段代码:
– Define a tag table which will hold all screen tags. tags = { names = { “main”, “www”, “im”, “gimp”, “office”, “music”, “virtual”, 8, 9 }, layout = { layouts[1], layouts[8], layouts[8], layouts[7], layouts[1], layouts[7], layouts[8], layouts[1], layouts[1]} } for s = 1, screen.count() do – Each screen has its own tag table. tags[s] = awful.tag(tags.names, s, tags.layout) end
在这个例子中,我们还为前5个标签分别命名为”main”, “www”, “im”, “gimp” 和”office”, 你可以根据自己的喜好进行更改。另外,我们还使用 layouts来指定每一个标签的布局, “[]“里的数字就是我们刚刚 定制布局的时候设置的布局的顺序,例如[1] 就是第1个布局。
设置默认终端和编辑器
可以在 rc.lua 中修改下面的代码来设置默认的终端和编辑器:
| 行号 | 代码 |
|---|---|
| 12 | terminal = "xterm"editor = os.getenv("EDITOR") or "nano" |
修改Mod键
要修改默认的Mod键,可以在 rc.lua 中修改这一句话:
| 行号 | 代码 | | —- | —- | | 1 | modkey = "Mod4" | 将”Mod4”改为其他按键即可。
美化Awesome
更换Awesome主题
觉得默认的主题不够漂亮?Awesome自带了三套主题: default 、 sky 和 zenburn 。要更换主题,可以打开 rc.lua 配置文件,找到这一行内容:
| 行号 | 代码 |
|---|---|
| 1 | beautiful.init("/usr/share/awesome/themes/default/theme.lua") |
把其中的 default 更换成其他主题名字即可。如果嫌主题太少,这里有很多PP的用户定制主题:Beautiful_themes 。到它的 Github主页 下载下来然后拷贝到~/.config/awesome/themes即可以使用。
更换背景图片
不喜欢那个黑不溜秋的背景图片?可以修改一下你正在使用的主题的theme.lua文件,将这一句
| 行号 | 代码 |
|---|---|
| 1 | theme.wallpaper_cmd = { "awsetbg /usr/share/awesome/themes/default/background.png" } |
里的图片的文件路径更改为你喜欢的图片的文件路径即可。
修改主菜单
可以通过修改 rc.lua 的相应内容来定制主菜单的内容。下面是我的配置。里面的设置完全根据我个人口味,而且用了几个第三方的icon。因此代码仅供参考,不建议照搬:
– 创建一个主菜单 myawesomemenu = { { “manual”, terminal .. “ -e man awesome” }, { “edit config”, editor_cmd .. “ “ .. awesome.conffile }, { “restart”, awesome.restart }, { “quit”, awesome.quit } }
– 创建一个 favorite 子菜单 myfavoriteapps = { { “Terminal”, terminal }, { “Firefox”, “firefox” }, { “QQ”, “qq2012” }, { “XMind”, “/usr/local/xmind/xmind” }, { “Synaptic”, “gksudo synaptic” }, { “Transmission”, “transmission-gtk” }, { “Software-Center”, “gksudo software-center” }, { “Update-Manager”, “gksudo update-manager” }, { “JabRef”, “sh /home/ehome/JabRef.sh” } }
– 创建主菜单 mymainmenu = awful.menu({ items = { { “awesome”, myawesomemenu, beautiful.awesome_icon }, { “Debian”, debian.menu.Debian_menu.Debian, theme.deb_icon }, { “Favorite”, myfavoriteapps, theme.fav_icon }, { “Home”, “dolphin”, theme.home_icon }, { “Emacs”, “emacs” }, { “Chrome”, “google-chrome” }, { “Log out”, “/usr/local/shutdown.sh” } } })
– 创建一个启动器 mylauncher = awful.widget.launcher({ image = image(beautiful.awesome_icon), menu = mymainmenu })
修改的主菜单如下图所示。

修改后的主菜单
5.6 关机对话框
Awesome有个让人有点不习惯的地方是没有一个可视化的关机对话框。如果不想每次关机都得手动敲命令,可以写一个shell脚本,实现一个可视化的关机对话框,如下图所示。

关机对话框
为了正确执行这个脚本,你需要确保系统已经安装了下列的程序:
- zenity (用来产生对话框)
- gksudo (可视化获取系统权限)
- pm-utils (用来和dbus一起实现挂起功能)
- dbus (实现挂起功能)
- hal (管理硬件)
- slock (实现屏幕锁定)之后创建一个脚本,保存为 shutdown_dialog.sh ,并在里面添加下面的内容:
完成后,修改 rc.lua ,给主菜单添加一个菜单项:
{ “Log out”, “your/path/to/shutdown_dialog.sh” }
自带的 Mod4 + X 启动工具搜索能力有限,例如,搜索 ‘dc’ 只会找到以 ‘dc’ 开头的程序,e.g. ‘dcgui’ 或 ‘dc2k’;而使用dmenu的话,可以找到任何包含 ‘dc’ 字段的程序,e.g. ‘linuxdcpp’。因此,推荐使用dmenu取而代之。
将 rc.lua 的相应内容修改为:
– 使用 dmenu 替代默认启动器 awful.key({ modkey }, “r”, function () local f_reader = io.popen(“dmenu_path | dmenu -b -nb ‘”.. beautiful.bg_normal ..”’ -nf ‘”.. beautiful.fg_normal ..”’ -sb ‘#955’”) local command = assert(f_reader:read(‘*a’)) f_reader:close() if command == “” then return end awful.util.spawn(command) end )
多显示器支持
Awesome的一大强处在于可以同时控制多个显示器的窗口。你可以随心所欲的把某个窗口移动到另一个显示器上,并且不同的显示器可以使用不同的标签,因此可以组合出各种布局效果。具体的快捷键已经在 常用快捷键 提及。
要使用多个显示器,首先要确保其他的显示器正常工作。在Awesome下,一个新的显示器插入之后并不能立即工作,而需要先经过设置。不同的显卡有不同的设置方法。详细的方法请参考 官方的多显示器设置教程 。由于我使用的是 nvidia 独显驱动,因此我主要介绍使用 nvidia 独显的简单设置方法。
nvidia独显使用多显示器
在设置多显示器之前,建议先备份现有的 xorg.conf 文件:
$ sudo cp /etc/X11/xorg.conf /etc/X11/xorg_single.conf
新插入一个显示器后,首先以管理员身份启动 nvidia 设置工具(nvidia-settings)。如果已经配置好 dmenu,可以按 Mod4 + r,然后输入以下命令:
gksudo nvidia-settings
启动 nvidia设置工具 。然后选择 X Server Display Configuration,如图所示。点击当前为Disabled的那个显示器,然后在 Configuration 设为 TwinView,再根据喜好设Position。如果需要将这个显示器设为主显示器,则勾选“Make this the primary display for the X screen”。完成后 不要 点击”Apply”按钮,而是点击 “Save to X Configuration File”,覆盖原来的 xorg.conf 文件。

nvidia 设置多显示器
退出nvidia-settings,然后重启X,或者注销后再登录,此时另一个显示器已经开始工作。
使用投影仪
如果是投影仪,通常不需要扩展屏幕,而是同步显示器和投影仪的画面。因此 Position 需要设置为 Clones,而且由于大部分的投影仪分辨率都是 1024*768 ,因此需要将主显示器的 Resolution 也设置为 1024*768。
单显示器和多显示器间的切换
为了方便以后在单显示器和多显示器之间切换,可以将现在的 xorg.conf 备份为 xorg~mul~.conf 文件。这样,以后要切换单显示器或多显示器时,只需要使用cp命令将对应的配置文件覆盖当前的 xorg.conf 文件即可。
插件
什么是插件?
Awesome里的插件指的是你可以在 wibox 上添加的小插件,通过使用插件(Widget),我们可以在状态栏上添加一些有用的信息,例如内存使用、CPU温度、电池状态,等等。官方wiki上有很详细的介绍:http://awesome.naquadah.org/wiki/Widgets_in_awesome
对于新手,可以使用其他用户创建的插件库,这些插件库集成了功能齐全的插件,因此免去了自己编写插件的工作。这类的插件库有很多,常用的有Vicious、 Obvious 等。
创建插件
要创建插件,可以使用 widget() 函数,例如:
-- Create a system tray widget
mysystray = widget({ type = "systray" })
-- Create an imagebox widget
myicon = widget({ type = "imagebox" })
myicon.image = image(awful.util.getdir("config") .. "/myicon.png")
-- Create a textbox widget
mytextbox = widget({ type = "textbox" })
mytextbox.text = "Hello, world!"
插件的类型
使用 widget() 函数创建插件的时候需要指定插件类型,Awesome自带的插件包括:
- systray系统托盘插件。Awesome默认已经添加,就在状态栏上位于日期和时间左侧的区域。对于一些支持最小化到系统托盘的程序,例如ibus、chrome、shutter等,它们的图标将被放置在这里。
- imagebox展示一张图片。常用来和textbox一起搭配使用,创建启动器、图标和分隔符。这里 收集了很多精美的图标。
- textboxtextbox插件用来显示一段文本,这是最常用的插件。例如,在创建插件部分我们已经创建了一个名为mytextbox的textbox插件,并且插件显示的文本内容是”Hello, World!”。要修改文本内容,可以直接修改 rc.lua文件中的相应代码,或在终端中使用下面命令:
$ echo 'mytextbox.text = "Foo Bar!"' | awesome-client
Awesome 还提供了 计时器的 API,允许我们周期性地执行或更新插件。例如:
mytimer = timer({ timeout = 30 })
mytimer:connect_signal("timeout", function()
mytextbox.text = "Hello awesome world!"
end)
mytimer:start()
textbox 的文本属性(如颜色、字体)可以通过使用 Pango 标记语言来修改。以下是一个简单的例子:
mytextbox.text = '<span color="white">Sacrebleu, I have seen a ghost!</span>'
要了解更多textbox的设置,例如改变背景颜色、边框、文本对齐等,可以参看Awesome的API文档。
实用插件
Awesome的官方Wiki 收集了丰富的插件。下面介绍其中几个实用的插件。
音量控制插件
Awesome 自己不提供音量控制插件,如果未经设置,还会发现原本键盘上的多媒体按键都会失效,这是因为没有让 Awesome 绑定这些热键。下面实现一个音量控制插件,并且将音量控制绑定到多媒体键盘的音量加(XF86AudioRaiseVolume)、音量减(XF86AudioLowerVolume)、静音(XF86AudioMute)几个按键上。
首先实现一个音量控制插件,将它保存为 ~/.config/awesome/volume.lua:
-- Create a volume control
volume_widget = widget({ type = "textbox", name = "tb_volume", align = "right" })
function update_volume(widget)
local fd = io.popen("amixer sget Master")
local status = fd:read("*all")
fd:close()
local volume = tonumber(string.match(status, "(%d?%d?%d)%%")) / 100
status = string.match(status, "%[(o[^%]]*)%]")
-- Starting color
local sr, sg, sb = 0x3F, 0x3F, 0x3F
-- Ending color
local er, eg, eb = 0xDC, 0xDC, 0xCC
local ir = volume * (er - sr) + sr
local ig = volume * (eg - sg) + sg
local ib = volume * (eb - sb) + sb
local interpol_colour = string.format("%.2x%.2x%.2x", ir, ig, ib)
if string.find(status, "on", 1, true) then
volume = " <span background='#" .. interpol_colour .. "'> </span>"
else
volume = " <span color='red' background='#" .. interpol_colour .. "'> M </span>"
end
widget.text = volume
end
update_volume(volume_widget)
awful.hooks.timer.register(1, function() update_volume(volume_widget) end)
参考资料
- http://awesome.naquadah.org/wiki/
- http://wiki.ubuntu.org.cn/Awesome
- http://linuxtoy.org/archives/awesome.html