dwm (简体中文)
dwm是X下的一个动态窗口管理器。它用平铺的、栈式的和全屏的布局方式,借助一些可选的补丁还可以实现其他的布局。布局可以动态得改变,为程序提供最优的环境和性能。dwm特别轻量快速,用C语言编写,被设计的目标是控制在2000行以下的代码。在xrandr和Xinerama支持下可实现multi-head。
安装
这里建议用makepkg从ABS安装。这样你可以在稍后的时间简单地重新配置。如果你只是想安装试用一下的话,简单地安装:
# pacman -S dwm
注意这样是不灵活的,因为dwm的配置要通过修改它的源码来实现。所以接下来的文章假定你从源码编译dwm。
你可能很想同时安装dmenu,一个X下轻量级的动态菜单:
# pacman -S dmenu
需求
你需要用 base-devel 里的基本编程工具来编译dwm,并且需要用 asp 来获得安装脚本:
# pacman -S base-devel asp
下载 PKGBUILD
如果需要的包都准备好了,可以用 asp 从仓库里获得最新的 PKGBUILD 了:
$ asp export community/dwm
编译和安装
用 cd
进入到 asp 导出的目录,然后运行:
$ makepkg -i
这会编译并安装dwm,如果有问题请仔细输出信息。
配置
就像上边提到的那样,dwm是在编译时配置的,确切地说就是修改config.h
和config.mk
。然而它提供了一个很好的初始配置,对一些有经验的用户,它是很好调整的。
方法一:使用 ABS(推荐)
在这里修改dwm是非常简单的。
自定义config.h
进入安装过程中的dwm的源码目录;也就是上边的~/dwm
。里边的config.h
存放着通常的配置信息。这个文件里的大多数配置都很好理解,但其他的可能比较有个性。关于这些配置的详细信息可以查阅dwm website。
一旦修改完成了,更新PKGBUILD里的md5sums:
$ makepkg -g >> PKGBUILD
这样会避免因为和官方的config.h文件不一样导致校验值错误。
现在,编译并重新安装:
$ makepkg -efi
假定配置是有效的,这条命令会编译和重新安装dwm,如果出问题了,请仔细查看输入内容获得详细信息。
最后,重启dwm来使用新的配置。
注意
从现在开始,我们不必每次都更新config.h
的md5sums了,因为会很频繁,我们只需要用--skipinteg
选项来跳过校验。
$ makepkg -efi --skipinteg
在往dwm的启动脚本里添加几行后,我们可以在不登出和退出程序程序的情况下重启dwm。
方法二:使用Mercurial(高级)
上游的dwm是用git版本控制系统来维护的,在suckless.org。熟悉Mercurial的人会发现用它来维护配置和补丁会更方便。
启动dwm
可以用startx
或者SLiM登陆管理器来启动dwm,只需要在~/.xinitrc
添加:
exec dwm
对于GDM,在~/.Xclients
添加上述内容,然后在会话菜单里选择”运行XClient脚本”。
配置状态条
dwm使用根窗口名称来显示状态条信息,可以使用xsetroot -name
来改变。
基本状态条
这个例子显示ISO 8601格式的日期。把下边的内容添加到~/.xinitrc
或者~/.Xclients
,或者可以从GDM-3的讨论页中获得更多细节:
while true; do xsetroot -name "$( date +"%F %R" )" sleep 1m # Update time every minute done & exec dwm
这是个笔记本使用的,依赖acpi包来显示电池信息:
while true ; do xsetroot -name "$( acpi -b | awk '{ print $3, $4 }' | tr -d ',' )" sleep 1m done & exec dwm
这个脚本显示电池剩余电量和充电状态,用awk命令过滤acpi输出的无用信息,然后用tr去除逗号。
另一个方式是根据电池的状态选择性地输出信息:
while true; do batt=$(LC_ALL=C acpi -b) case $batt in *Discharging*) batt="${batt#* * * }" batt="${batt%%, *} " ;; *) batt="" ;; esac xsetroot -name "$batt$(date +%R)" sleep 60 done & exec dwm
最后,要确保在~/.xinitrc
或者~/.Xclients
里只有一个dwm实例, 所以把整合起来应该像这样:
~/.setbg autocutsel & termirssi & urxvt & while true; do xsetroot -name "$(date +"%F %R")" sleep 1m # Update time every minute done & exec dwm
这是另一个显示alsa音量和电池状态的例子。它一直显示到系统退出为止。
#set statusbar while true do if acpi -a | grep off-line > /dev/null; then xsetroot -name "Bat. $( acpi -b | awk '{ print $4 " " $5 }' | tr -d ',' ) | Vol. $(amixer get Master | tail -1 | awk '{ print $5}' | tr -d '[]') | $(date +"%a, %b %d %R")" else xsetroot -name "Vol. $(amixer get Master | tail -1 | awk '{ print $5}' | tr -d '[]') | $(date +"%a, %b %d %R")" fi sleep 1s done &
Conky状态条
Conky可以使用xsetroot -name
来往状态条里输出信息:
conky | while read -r; do xsetroot -name "$REPLY"; done & exec dwm
要想这样做,conky需要只往终端里输出文本。这是个应用于dual core CPU的简单conkyrc,显示几个状态信息:
out_to_console yes out_to_x no background no update_interval 2 total_run_times 0 use_spacer none TEXT $mpd_smart :: ${cpu cpu1}% / ${cpu cpu2}% ${loadavg 1} ${loadavg 2 3} :: ${acpitemp}c :: $memperc% ($mem) :: ${downspeed eth0}K/s ${upspeed eth0}K/s :: ${time %a %b %d %I:%M%P}
状态条颜色
可以在config.def.h
中更改,然后复制到config.h
中。
static const char col_gray1[] = "#000000"; #状态条底色 static const char col_gray2[] = "#FFFFFF"; #当static const unsigned int borderpx不为0时,非活动窗口外边框颜色 static const char col_gray3[] = "#39C5BB"; #当前非活动的title字体颜色 static const char col_gray4[] = "#7FFF00"; #当前活动的title字体颜色 static const char col_cyan[] = "#696969"; #title底色
static const unsigned int borderpx也是config.def.h
的选项,不为0时,会在窗口边缘产生边框
基本用法
Dmenu是dwm的一个有用的扩展。它不是一个单独的列表式菜单,而是生成一个可执行文件的列表并根据输入进行自动补全。比起许多程序启动器,它能与dwm更好地整合。
可以按 Mod1
+ P
来启动Dmenu(Mod1
缺省是 Alt
)。当然你也可以按自己的喜好改变它。然后只需要在上边出现的工具条中输入你想运行的程序的前几个字母,也可以按左右箭头在进行选择,按回车键完成。
更详细的信息请查阅 dmenu.
控制窗口
将窗口移动到另一个tag
将当前的活动窗口移到其他的标签页:Shift
+ Mod1
+ x
, 其中的x是其他的标签页的序号,如果x是5,则表示将当前的活动窗口移到第5号标签页上去。Mod1
缺省是 Alt
键,这个键值可以在config.h中定义。
关闭窗口
关闭当前的活动窗口: Shift
+ Mod1
+ C
.
窗口布局
dwm缺省工作在平铺模式。当新窗口不断出现在同一个标签页时,窗口会越来越小。所有窗口会占满整个屏幕(除了目录条)。然而还有其他两种模式:浮动和单页模式。浮动模式对非平铺窗口管理器用户来说更熟悉,它允许用户重新按自己需要摆放窗口。单页模式会让一个窗口在最上边。
要切换到浮动模式,只需要按Mod1
+ F
。Mod1
缺省是 Alt
。如果你看到标签页右上角有X>这样的标志,就进行了浮动模式。
切换到单页模式,按 Mod1
+ M
。检查上否在单页模式,你会看到[M]标志(如果当前标签页无窗口),或者[n](n是打开窗口的编号)。
回来平铺模式,按Mod1
+ T
,你会看到 []= 这样的标志。
退出dwm
退出dwm(登出): Shift
+ Mod1
+ Q
.
官方关于默认的快捷键的说明: dwm tutorial.
再次说明,快捷键可以根据自己的喜好自由定义,本维基中的快捷键都是指官方默认的快捷键。
扩展使用
补丁和增加窗口布局(tiling modes)
DWM官网上有很多可以给DWM添加功能的补丁, 用户可以通过补丁定制DWM。
bottomstack补丁能够使DWM由原来的垂直布局变为水平布局,而gapless grid补丁则可使窗口变为网格状布局.
实现为每个标签定制布局
dwm的缺省行为是将当前选定的布局应用到所有标签上。如果想为每个标签定制布局可以打pertag这个补丁。
解决模拟终端窗口缝隙问题
如果你发现模拟终端(例如xterm,Urxvt)的窗口占不满屏幕,这是因为其窗口的大小和字体有关。你可以试图调整字体大小直到恰好合适为止(这也许是很困难的),或者只需要把config.h
文件中的 resizehints
设置为 False:
static Bool resizehints = False; /* False means respect size hints in tiled resizals */
这样dwm会忽略所有窗口的改变大小的请求,不只是模拟终端的。这样的缺点是一些模拟终端可能会刷新异常,像显示一些错误的内容。
在不登出和退出程序程序的情况下重启dwm
如果你要在在线重启dwm(不关闭它以及其他应用程序),修改启动脚本,并让dwm在一个while循环中运行,像这样:
while true; do # Log stderror to a file dwm 2> ~/.dwm.log # No error logging #dwm >/dev/null 2>&1 done
这样就可以用Mod-Shift-Q快捷键来实现重启。
把上边的内容写到一个其他的文件(例如~/bin/startdwm
)是一个好主意。然后在 ~/.xinitrc
文件里添加(exec startdwm)。这样我们可以使用 killall startdwm
来真正地退出X会话,或者绑定到一个方便的快捷键上。
把右Alt键作为Mod4(Win键)使用
当把Mod4(Win键)作为 MODKEY
时,你可能希望右Alt键也可以作为Mod4,这样就两个手都可以按到了
首先,找到右Ctrl键对应的键码:
xmodmap -pke | grep Alt_R
然后只需要在启动脚本(比如 ~/.xinitrc
)添加如下内容, 把 113 换成之前xmodmap
的结果:
xmodmap -e "keycode 113 = Super_L" # reassign Alt_R to Super_L xmodmap -e "remove mod1 = Super_L" # make sure X keeps it out of the mod1 group
现在,右Alt键就和Mod4键一样了。
防止鼠标下的程序自动获取焦点
为了防止鼠标下的程序自动获取焦点,可以注释掉dwm.c中的如下代码:
[EnterNotify] = enternotify,
添加个性的快捷键绑定
config.h
文件中的两个地方涉及到创建修改快捷键,一个是"/* */" 注释中,并一个是"static Key keys[] = {"语句中。
static const char *<keybindname>[] = { "<command>", "<flags>", "<arguments>", NULL };
<keybindname> 可以是任何东西, <command> <-flags> and <arguments> 也是,但要用双引号括起来。
{ MODKEY, XK_<key>, spawn, {.v = <keybindname> } },
这会绑定 Mod+<key> 来执行之前定义的命令。
{ MODKEY|ShiftMask, XK_<key>, spawn, {.v = <keybindname> } },
这会绑定 Mod+Shift+<key> ,使用要用Ctrl键是 ControlMask 。
单个按键像Fn或者多媒体键必须要用16进制数来表示,可以用xev程序来获得。或者查看 /usr/include/X11/XF86keysym.h 中的定义。
{ 0, 0xff00, spawn, {.v = <keybindname> } },
这会把0xff00键绑定到<keybindname>。
解决Java程序不正常的问题
对于使用JRE 6u20的Java程序在dwm中可能表现异常,因为dwm不是Java的一个已知的窗口管理器,这会导致一些像鼠标释放使菜单消失之类的小问题。可以先安装里的 [community] 里的wmname:
# pacman -S wmname
然后你只需要用wmname来设置一个Java能识别的WM名称:
$ wmname LG3D
这不是永久的,所以你可以把它写进.xinitrc。
资源
- dwm's official website
- dmenu - Simple application launcher from the developers of dwm
- The dwm thread on the forums
- Hacking dwm thread
- Check out the forums' wallpaper thread for a selection of dwm wallpapers
- HowTo by Snake
- Moved to dwm