news 2026/10/18 5:43:10

dwm平铺窗口管理器Arch Linux实战:从源码编译到config.h定制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
dwm平铺窗口管理器Arch Linux实战:从源码编译到config.h定制

拿 Arch Linux 折腾平铺式窗口管理器,绕不开 dwm。这个名字在开源社区里出现频率极高,但真正上手的人远比听说过它的人少。原因很简单:别的桌面环境装完带图标、带启动器、带设置面板,dwm 装完只有一个灰扑扑的屏幕,连个壁纸都没有,一切操作靠键盘,配置还要改 C 源码重新编译。听起来劝退,但用过一段时间的人大多回不去了。

这篇文章不是把 dwm 的安装命令罗列一遍就完事,而是把整个过程中涉及的设计思路、依赖关系、编译原理和故障场景都讲透。你不仅能学会怎么把 dwm 跑起来,还能理解为什么要改 config.h、为什么补丁会冲突、为什么字体缺失会让整个界面显示成方块。适合的对象有两类:一类是刚接触 Arch、准备把平铺式窗口管理器作为日常主力环境的用户;另一类是已经在用别的平铺管理器(比如 i3)但想试试 dwm 的人。前者可以照顺序操作,后者可以直接跳到配置和补丁章节,核心差异点有足够多,值得花点时间看完。

1. dwm 为什么值得折腾:理念与使用场景

1.1 平铺式窗口管理器到底是什么

传统桌面环境下,窗口是“堆叠”的:打开几个程序,窗口互相叠着,鼠标能拖动位置、调整大小,点击哪个哪个就到最前面。这种模式叫浮动式窗口管理,主流桌面环境基本都是这套逻辑。

平铺式完全反过来。窗口不重叠,系统自动把它们铺满整个屏幕,就像拼瓷砖一样。一个窗口占左边一大块,其余窗口在右边竖着排;切到另一个标签页,又会有另一组已经排好的窗口等着你。dwm 会在你启动新窗口的瞬间自动决定它该占多大、放在哪里,不需要你手动拖拽。

生活里类比一下:浮动式窗口是你坐在一张大桌子前,文件随便摊开,互相压着也没事,想用哪张就用手拨到最上面;平铺式则是把所有文件像书架一样一格一格摆整齐,永远不需要“把压住的文件抽出来”这个动作。后者对使用效率的提升非常明显,尤其是同时开大量终端、编辑器、浏览器分屏工作时,平铺方式能最大化利用屏幕空间,也减少了调窗口位置的操作次数。

1.2 dwm 的极简哲学:配置即源码

dwm 的作者是一位坚持极简主义的开发者,suckless 社区的核心信条就是“软件要简单到没有冗余”。dwm 整个项目的源代码非常精简,核心程序不到两千行 C代码。和动辄几十万行、带一堆后台服务和图形化配置界面的桌面环境相比,它小得惊人。

这种极简设计带来的直接后果是:dwm 没有一个独立的“设置文件”。它的所有配置都集中在一个叫 config.h 的头文件里,而你在安装前看到的只是默认模板 config.def.h。第一次编译时,构建系统会自动根据 config.def.h 生成 config.h。之后你改 config.h,重新编译,配置就直接烧进二进制文件里了。

为什么这么设计?因为没有运行时配置解析,就没有额外的 CPU 开销,也没有“改了配置忘了重启”这种状态不一致的问题。你得到一个确定的、完全受控的程序。代价是修改配置必须重新编译,这也是 dwm 玩家日常操作里最频繁的一步。

1.3 与其它平铺窗口管理器对比

同类软件里最常被拿来跟 dwm 比较的是 i3、awesome 和 xmonad。它们都属于平铺式窗口管理器,但思路差别很大,我用一张表说明。

维度dwmi3awesomexmonad
配置方式改 C 源码后编译独立文本配置文件改 Lua 脚本改 Haskell 源码后编译
运行时依赖极少中等中等偏重需要 Haskell 运行时
上手门槛较高较低中等最高
灵活性靠补丁扩展配置自身很灵活内置功能丰富函数式组合最强
资源占用极低低较低中等

如果你的目标是“开箱即用、配置简单”,i3 更合适,因为它有详尽的文本配置格式,改起来直观,图形化工具也多。但如果你喜欢“极小的程序 + 自己动手拼装”这种风格,而且愿意花时间去读源码、打补丁,dwm 带来的掌控感是 i3 很难给的。awesome 功能庞大但配置文件学习成本不低,xmonad 需要熟悉 Haskell 的类型系统,对大多数用户来说门槛反而比 dwm 的 C 源码还高。

2. 安装前的准备工作:环境、字体与依赖

2.1 确认系统基础状态

开始之前,先确认手上这台 Arch 系统是干净可用的。基础检查其实很简单:能联网、能用 pacman 正常安装软件、知道 root 密码。由于 dwm 是 X11 程序,还要确保系统里有完整的 X 环境基础。

我在实际装机的过程中,见过不少人跳过依赖检查直接去源码目录 make,结果报出一堆 “X11/Xlib.h: No such file or directory” 之类的错误。这些错误本质上是缺了 X 开发库的头文件,不是什么难事,但提前确认可以省下不少定位时间。

2.2 Xorg 还是需要装的

一个常见误区是“Arch 装好了就有图形界面”。事实是 Arch 本体默认只有命令行,图形环境完全靠用户自己搭建。dwm 依赖 Xorg,所以先装最小化的 X 环境:

sudo pacman -S xorg-server xorg-xinit xorg-xrandr
  • xorg-server 是 X 服务本体
  • xorg-xinit 提供了 startx 启动脚本
  • xorg-xrandr 用来管理屏幕分辨率、缩放和多显示器

不建议安装整个 xorg 软件组。那个组包含大量你可能永远用不到的输入驱动、显示驱动和辅助工具,装完之后不仅体积大,还可能在日志里刷一堆无关紧要的警告。按需安装是 Arch 的哲学,也是排查问题时的友好做法:环境越干净,出问题时定位越快。

2.3 字体问题要提前解决

字体是 dwm 使用体验的第一道门槛,也是中文用户最容易踩的坑。

dwm 默认字体是 9 号大小的 Courier,在这个分辨率普遍较高的时代,显示效果偏小且不美观。更麻烦的是,如果系统里没有中文字体,dwm 状态栏和 dmenu 里的中文就会渲染成一个个方块或者空白,直接没法用。

推荐安装这几组字体:

sudo pacman -S noto-fonts noto-fonts-cjk ttf-dejavu otf-font-awesome
  • noto-fonts 提供基本的拉丁字符,覆盖绝大多数系统界面
  • noto-fonts-cjk 是中文显示的核心依赖,包含简体中文字形,没有它中文就是方块
  • ttf-dejavu 是终端模拟器里的常用回退字体,很多软件不指定字体时默认找它,装了能避免奇怪的回退行为
  • otf-font-awesome 是图标字体,dwm 状态栏里常见的 CPU 图标、内存图标、网络图标都靠它显示

装完之后可以用 fontconfig 命令验证:

fc-list | grep -i "noto sans cjk"

有输出就说明中文字体已被系统收录。

2.4 编译工具链与 X 开发库

dwm 从源码编译,依赖两大块:编译工具链和 X11 开发库。

编译工具链直接用 Arch 的包组:

sudo pacman -S base-devel

这个包组里包含 gcc、make、pkg-config 等必备工具。如果你平时用 yay、paru 之类的 AUR 助手,系统里大概率已经有了 base-devel,但明确确认一下总没错。

X11 开发库有三件套是关键:

sudo pacman -S libx11 libxft libxinerama
  • libx11 是 X 协议的基础库,缺了它 dwm 根本无法编译
  • libxft 负责字体渲染,状态栏和 dmenu 显示文字都依赖它
  • libxinerama 是多显示器支持的关键库

2.5 配套工具:dmenu、st、slstatus

dwm 不是孤立存在的。一个完整的 dwm 工作环境通常还要搭配同属 suckless 生态的几个小工具:

  • dmenu:程序启动器。在 dwm 里按快捷键后,屏幕顶部会跳出一个输入框,输入关键字即可启动程序。dmenu 按前缀匹配你的输入,实时显示候选结果。它不仅是启动器,还常被脚本用来自定义菜单。
  • st:极简终端模拟器。和 dwm 出自同一作者,风格一致,配置方式也一致。用 dwm 而不搭配 st,会发现默认的终端快捷键指向一个不存在的程序,按了没反应。
  • slstatus:状态栏工具。dwm 自带状态栏比较朴素,slstatus 可以通过编辑 config.h 决定显示 CPU、内存、电池、网络、时间等信息,每隔几秒刷新一次。

这三件套可以稍后再装,但既然是同一生态,建议一次性搞齐。它们的安装方式和 dwm 一模一样:克隆源码、改 config.h、make、make install。后面我会把 dmenu 和 slstatus 的具体安装一起讲。

3. 编译安装 dwm:核心操作流程

3.1 拿到官方源码

进入平时放源码的目录,然后克隆仓库:

cd ~/src git clone https://git.suckless.org/dwm cd dwm

suckless 官网的 git 服务是官方主要分发渠道。如果网络访问不稳定,也可以从开源代码托管平台的镜像仓库拉取,两者在源码层面没有本质区别。

克隆完之后,可以先看一眼目录里有什么:

ls -l

关键文件包括:

  • config.def.h:默认配置模板
  • config.mk:构建配置文件,定义编译器和安装路径
  • dwm.c:主程序源码
  • Makefile:make 的入口

3.2 读懂 config.mk:编译参数的起点

用编辑器打开 config.mk,会看到类似这段:

PREFIX = /usr/local MANPREFIX = ${PREFIX}/share/man X11INC = /usr/X11R6/include X11LIB = /usr/X11R6/lib

这里有几个在 Arch 上需要留心的点。

Arch 的 X11 头文件实际路径是 /usr/include/X11,库路径是 /usr/lib。config.mk 里的默认值 /usr/X11R6/include 和 /usr/X11R6/lib 是为 BSD 系系统准备的,在 Arch 上编译时,较新版本的源码会通过 pkg-config 自动处理,一般不需要手动改。但如果你的 make 过程报错,提示找不到 X11 相关头文件,就把这两行改成 Arch 实际路径:

X11INC = /usr/include/X11 X11LIB = /usr/lib

还有一个关键字段是 PREFIX。默认 /usr/local 意味着安装时二进制会被放到 /usr/local/bin,这对个人用户足够。如果你希望和 pacman 管理的文件保持高度隔离,保留默认;如果你想跟系统文件混在一起,可以改成 /usr。我个人推荐保留默认,因为后续卸载时直接删 /usr/local/bin/dwm 就可以了,不会污染系统包管理器的数据库。

3.3 make 的三个命令

第一次编译只需要三条命令:

make clean make sudo make install

make clean 是清掉上一次编译产生的中间文件。第一次编译时不是必须的,但如果你改过 config.h 再重新编译,这个命令能防止旧的 .o 文件残留导致最终链接结果不对。实际体验里,不改 config.h 直接 make 也能过,但养成 make clean 的习惯能省去不少诡异问题。

make 会读取 config.mk 里的参数,编译 dwm.c 等源文件,最终生成 dwm 可执行文件。如果依赖完整,这个过程通常在几秒内完成,屏幕上会滚动几行编译信息,最终生成一个名为 dwm 的二进制。

sudo make install 把编译好的 dwm 复制到 PREFIX 指定的目录,同时把文档页放到对应位置。装完后可以验证:

dwm -v

能输出版本号,就说明二进制已经正确安装。另一个验证点是:

which dwm

正常会输出 /usr/local/bin/dwm。

3.4 配置 .xinitrc 并首次启动

dwm 不带登录管理器,也不提供桌面环境那种“点击图标进入”的入口。启动路径是:通过 startx 进入 X 会话,然后由 .xinitrc 脚本决定启动哪个窗口管理器。

在用户目录创建 .xinitrc:

echo "exec dwm" > ~/.xinitrc

然后进入 X:

startx

如果你是从终端直接启动,并且当前没有运行中的 X 会话,startx 会拉起来一个 X 服务并执行 .xinitrc。到这里,你看到的是一个灰白色屏幕,顶部有一条浅灰色的状态栏,上面显示当前标签号和窗口标题,这就是 dwm 的默认外观。

这里要特别强调一个非常重要的细节:不建议直接用 exec dwm 作为 .xinitrc 的唯一内容。更好的写法是把 dwm 放进一个循环里,避免它因为意外崩溃直接退出整个 X 会话:

#!/bin/sh slstatus & while true; do dwm done

这个循环的作用是:如果 dwm 进程因为某种原因终止,系统会立刻重新拉起它,而不是把用户丢回黑乎乎的启动终端。这个技巧在改配置、测试补丁的初期阶段极为实用,因为你大概率会经历几次窗口管理器挂掉的情况。

3.5 st、dmenu、slstatus 同步安装

三个配套工具安装路径都差不多,以 dmenu 为例:

git clone https://git.suckless.org/dmenu cd dmenu sudo make install

st 和 slstatus 同理。它们的 config.h 也都可以改,比如 st 的字体和配色都在 config.h 里,slstatus 的显示模块选择也在 config.h 里。这些工具我不建议用发行版的打包版本,因为一旦用源码方式安装了 dwm,再搭配发行版打包的 dmenu,两者风格虽然能用,但改配置的思路就不统一了。保持“全家桶源码安装”的一致性,后续管理会省心很多。

slstatus 装完后,记得在 .xinitrc 里先启动它再启动 dwm,否则状态栏就是空白。dmenu 不需要显式启动,它是被 dwm 的快捷键动态调用的。

4. 配置 dwm:config.h 深入解析

4.1 config.h 的核心结构

第一次编译后,目录下会生成 config.h。在配置阶段,你编辑的主要就是这个文件。里面全是结构体和数组定义,核心字段可以分成几大块:字体、颜色、Mod 键、标签、按键绑定、鼠标绑定、布局、浮动规则。

我建议先花十分钟把整个 config.h 读一遍,不需要立刻理解每个函数指针的含义,但至少要知道改变量对应哪个功能。dwm 的源码很小,这种“阅读源码”的体验在别的软件里几乎找不到。

4.2 字体、Mod 键与标签

字体字段是这样一段数组:

static const char *fonts[] = { "monospace:size=10" };

我实际使用的配置是:

static const char *fonts[] = { "Fira Code:size=10:antialias=true", "Noto Sans CJK SC:size=10", "JoyPixels:size=10" };

第一个字体是主字体,第二个是中文回退字体,第三个覆盖图标字体。这个数组按优先级排序,缺失第一个字体时会自动尝试第二个。把中文字体放进去,状态栏里的中文标签才能正常渲染。

Mod 键字段决定了所有快捷键的主修饰键:

static const int modkey = MOD4Mask;

MOD4Mask 对应 Super 键,也就是键盘上的 Win 键。MOD1Mask 对应 Alt 键。我见过很多用户改来改去,最后发现 Super 键其实更适合 dwm,因为 Alt 在很多终端程序里也被占用,容易冲突。最终还是推荐默认的 Super 键。

标签数组控制工作区数量与名称:

static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };

我改成:

static const char *tags[] = { "终端", "代码", "网络", "聊天", "媒体" };

这样状态栏上就能直观显示每个工作区的用途。标签数量不一定要 9 个,常用 3 到 5 个就足够。标签名尽量短一些,否则状态栏空间会比较紧张。

4.3 键盘绑定:spawn 与自定义启动

config.h 里这一段是按键绑定列表,每条绑定由四个部分组成:修饰键、按键、动作类型、动作参数。最常见的是 spawn 动作,即启动外部程序。

默认已经有一条核心绑定:

static const char *termcmd[] = { "st", NULL }; { MODKEY, XK_Return, spawn, {.v = termcmd } },

这表示按 Mod + Enter 时运行 st。如果你不想装 st,想把终端换成 alacritty,可以改成:

static const char *termcmd[] = { "alacritty", NULL };

同理,可以给常用程序加固定快捷键。比如我用 Mod + b 打开浏览器、Mod + e 打开文件管理器:

static const char *browsercmd[] = { "firefox", NULL }; static const char *filemanagercmd[] = { "thunar", NULL }; { MODKEY, XK_b, spawn, {.v = browsercmd } }, { MODKEY, XK_e, spawn, {.v = filemanagercmd } },

每次修改 config.h 后,都需要重新编译才会生效:

make clean make sudo make install

重装后,当前正在运行的 dwm 还是旧版本,需要重启 dwm 才会加载新二进制。重启方式很简单:

pkill -x dwm

如果你用的是上面建议的循环启动写法,dwm 会在退出后立刻重新启动,并且直接切换到新版本。如果没有循环,pkill 之后 X 会话也会跟着退出,你就只能重新 startx 了。

4.4 布局、浮动规则与鼠标控制

dwm 有三种基础布局:平铺、浮动、单窗口。默认按键绑定时:

  • Mod + t 切到平铺布局
  • Mod + f 切到浮动布局
  • Mod + m 切到单窗口布局

平铺布局是 dwm 默认模式,主窗口在左侧占据较大空间,次窗口在右侧竖直排列。浮动布局下窗口可以自由拖动、缩放,适合处理那些需要精确定位的程序,比如对话框、GIMP 工具箱。

config.h 里的 floatingrules 数组可以指定某些程序强制以浮动方式启动:

static const Rule rules[] = { { "Gimp", NULL, NULL, 0, True, -1 }, { "firefox", NULL, NULL, 1 << 8, True, -1 }, };

第一项的含义是:凡是窗口类名匹配 “Gimp” 的程序,始终以浮动模式打开。第二项把 Firefox 固定到第 9 个标签。这个机制非常实用,因为有些程序天生不适合平铺,比如设置弹窗、截图工具、输入法候选窗口。

鼠标绑定默认是:按住 Mod 键拖动窗口可以移动浮动窗口,Mod + 右键拖动可以调整大小。这些都可以在 config.h 里的 Mouse 数组里调整,但多数用户改的地方不多。

4.5 自动启动程序

dwm 本身没有“开机自启动”的配置项。因为设计哲学是极简,它不为用户预设任何桌面服务。你需要在 .xinitrc 里自己启动需要的程序。

我的 .xinitrc 长这样:

#!/bin/sh xrandr --output eDP-1 --mode 2560x1600 --rate 120 & feh --bg-scale ~/Pictures/Wallpapers/desert.jpg & slstatus & dunst & exec dbus-launch dwm
  • feh 设置壁纸
  • slstatus 启动状态栏
  • dunst 启动通知守护进程
  • dbus-launch 保证桌面环境需要的 D-Bus 会话存在

修改 .xinitrc 后不需要重启系统,只需退出当前 X 会话再重新 startx,就能测试新的启动项。

5. 打补丁:定制 dwm 的正确方式

5.1 为什么补丁是 dwm 的灵魂

dwm 官方仓库只提供最基础的核心功能,这是刻意为之。作者认为特性的取舍由用户自己决定,因此社区维护了一个补丁页面,上面挂着几百个补丁,覆盖了你能想到的几乎所有个性化需求。补丁通常是一个 .diff 文件,指明了对源文件的哪一行做怎样的修改。

补丁流程也让 dwm 呈现出一种特别的生态:没有两个人的 dwm 是完全相同的。每个用户编译出的 dwm 都携带了自己选择的功能组合,这是“配置即源码”哲学的极致体现。

5.2 打补丁的标准流程

假设你要给 dwm 加上 uselessgap 这个补丁,它的作用是在窗口之间留出间隙,让布局不那么拥挤:

cd ~/src/dwm patch -p1 < patches/uselessgap.diff

patch 命令的参数 -p1 表示忽略路径中最前面的一层目录,也就是源码根目录下的那个前缀,这样 .diff 里的路径就能正确匹配到当前目录下的源文件。

如果补丁成功应用,会看到类似这样的输出:

patching file config.def.h patching file dwm.c

然后重新编译:

make clean make

此刻如果编译通过,再 install 即可。

5.3 补丁冲突与 .rej 文件

打补丁必然会遇到冲突。最常见的情况:两个补丁都修改了 dwm.c 里同一个函数,第二个补丁就无法干净地应用。patch 命令会跳过冲突部分,并生成一个 .rej 文件,里面记录了未能应用的部分。

这时不要慌,这是 dwm 玩家的日常。处理步骤是:

ls *.rej cat dwm.c.rej

打开 .rej 文件,你会看到补丁希望加入的内容,以及上下文。然后在 dwm.c 中找到对应位置,手动合并这段代码。合并完成后,删除 .rej 文件,重新编译验证。

手动合并补丁需要一点 C 语言阅读能力。如果你完全不会 C,也不用太担心,很多补丁的冲突只是行号变化,把补丁内容贴到对应函数附近即可。但复杂冲突还是建议先搞懂每个函数在干什么,再去合并。

5.4 值得关注的补丁清单

补丁名称作用推荐程度
uselessgap在窗口间留出间隙,改善视觉拥挤高
movestack用快捷键移动窗口在堆栈中的位置高
swallow让终端内启动的 GUI 程序接管终端窗口高
systray状态栏增加系统托盘区,图标软件必备中
alpha让终端和矩形窗口支持透明度中
roundedcorners窗口圆角化,视觉更柔和低
fibonacci增加斐波那契分屏布局中
grid增加网格布局,适合大量窗口平铺中

我从实际经验给出的建议是:先打功能类补丁,比如 movestack 和 swallow,它们能直接提升操作效率;视觉类补丁可以等你对 dwm 源码结构更熟悉之后再考虑,因为视觉补丁通常改动面更大,冲突概率也更高。dwm 那种干净利落的观感本身就是它的魅力,加太多视觉修饰反而容易显得臃肿。

5.5 用 git 管理补丁过程

打补丁是个反复试错的过程,强烈建议用 git 管理源码目录。具体做法:

cd ~/src/dwm git init git add . git commit -m "original dwm" # 打第一个补丁 patch -p1 < patches/uselessgap.diff make clean && make sudo make install # 确认没问题后保存进度 git add . git commit -m "add uselessgap" # 打第二个补丁 patch -p1 < patches/movestack.diff

如果第二个补丁把源码改坏了,你随时可以回滚到上一个 commit,而不是重新 clone 仓库。这是我在多次折腾中总结出来的最重要经验之一。

6. 常见问题与排查技巧

6.1 启动黑屏,X 闪退

这是新手的最大障碍。现象是 startx 之后屏幕一黑,然后马上退回终端,甚至直接卡住。

排查思路从 .xinitrc 入手。最常见原因是 .xinitrc 里写了不存在的程序:

exec some-nonexistent-wm

X 启动时尝试执行这个不存在的程序会直接失败,于是整个会话退出。把 .xinitrc 写对,只保留:

slstatus & exec dwm

如果确认 .xinitrc 没问题,再看 X 日志:

cat /var/log/Xorg.0.log | tail -50

这里能看到 X 服务启动过程的报错,比如显卡驱动没加载、分辨率设置失败、缺少 DRI 权限等。大多数情况下,跟着日志里的提示去安装对应驱动或者调整 xrandr 设置就能解决。

6.2 快捷键按了没反应

进入 dwm 后按 Mod + Shift + Enter,预期会打开终端,但实际没有反应。这种情况要先确认默认终端命令是否指向了一个已安装的程序。

默认配置里 termcmd 是 st。如果你没装 st,快捷键自然不会生效。两种解决方式:装 st,或者在 config.h 里把 termcmd 改成你已有的终端模拟器。

另外,检查你的键盘是不是出问题的另一个常见场景:插着多键盘或者使用了非标准键盘映射。可以用 xev 命令按下按键观察 keysym,确认 Mod 键是否正常识别。

6.3 中文显示成方块

这是字体缺失问题。如果在状态栏、dmenu、st 终端里看到方块状字符,说明系统里没有可用的中文字体。安装了 noto-fonts-cjk 后,还要确认内核字体配置正确:

fc-list :lang=zh

如果没输出,说明中文字体安装失败。重新安装:

sudo pacman -S noto-fonts-cjk fc-cache -fv

fc-cache 刷新字体缓存,之后重启 dwm 就能正常显示。

6.4 状态栏不刷新,或者不显示信息

dwm 自带状态栏默认内容很少,只有标签和窗口标题。如果你期望看到时间、CPU 使用率之类的内容,需要启动 slstatus。确认 .xinitrc 里有:

slstatus &

如果 slstatus 已经启动但内容不刷新,检查它的 config.h 里对应的模块是否编译错误。slstatus 的每个模块比如 cpu_perc、battery_perc 都会在启动时输出一次文本,如果某个模块无法获取底层数据(比如没有电池接口),整个状态栏可能都不刷新。可以先注释掉可疑模块,逐步缩小范围。

6.5 多显示器下窗口布局混乱

dwm 对多显示器的支持依赖 libxinerama。安装后,每个显示器被当作一个独立的“桌面”,窗口会分配到鼠标当前所在的屏幕。如果你的两个屏幕分辨率不一样,窗口大小可能看起来不协调,这是正常现象,dwm 不会帮你在双屏之间自动同步分辨率。

确认 X 是否正确识别双屏:

xrandr

如果两个屏幕没有正常显示,检查驱动和连接。只要 xrandr 能看到两个输出,dwm 就能正确工作。要改变窗口去的哪个屏幕,只需把鼠标移过去再启动新窗口。

6.6 补丁冲突后源码混乱

这是最让人头疼的场景之一。处理原则是:先把源码恢复到可编译的状态,再重新应用补丁。用 git 的话一条命令:

git checkout -- .

这会丢弃所有未提交的修改,回到上次 commit 的状态。然后逐个补丁重新打,每打一个就测试一次编译。如果没做 git 管理,也可以用原始 tar 包重新解压一份源码,但那样你之前改过的 config.h 也会丢失,所以一开始就建议用 git。

6.7 退出 dwm 时整个会话跟着退出

这是正常行为。.xinitrc 里 exec dwm 会替换掉当前 shell 进程,dwm 退出就意味着 X 客户端的最后一个进程结束,X 会话自然关闭。如果你希望 dwm 崩溃后自动重启,使用循环启动方式就不会遇到这个"问题"。

7. 配套生态与日常使用心法

到这里,你已经有了一套能正常使用的 dwm 环境。但距离真正“顺手”还有一段路。这节分享一些我在长期使用中形成的习惯。

7.1 状态栏信息的取舍

slstatus 能显示的东西非常多,但我不建议把 CPU、内存、磁盘、温度、网络、音量、电量一股脑全塞进去。信息太多会导致状态栏拥挤、刷新负担大,而且人眼根本无法时刻关注每条信息。

我的状态栏只留三块:左边是当前工作区标签,中间是窗口标题,右边显示时间和电池。没有网络速度,没有 CPU 频率。原因很简单:这些数据看多了意义不大,真正需要监控的时候自然会用终端工具。状态栏的价值是让你瞟一眼就知道时间和电量,不是把桌面变成监控中心。

7.2 让你的常用程序适应平铺

平铺窗口管理器改变的不只是窗口排列方式,还有启动程序的习惯。以前你可能习惯开着一个软件面板随时点选,现在更合理的是用 dmenu 输入程序名的前几个字母快速调起。

另外,有些程序明显不适合平铺。例如虚拟机窗口、截图选区工具、文件保存对话框,这类窗口需要自由移动。在 config.h 的 rules 数组里为它们加一条浮动规则,能避免每次手动切到浮动布局的麻烦。

7.3 给新手的节奏建议

我知道很多人装完 dwm 的第一件事就是到处找好看的 dotfiles 复制粘贴。我的建议恰恰相反:先用默认配置跑一段时间,哪怕它看起来很简陋。

默认配置的好处是逻辑最纯粹,你每改一个字段都能明显感受到效果。比如把标签改成中文,你会立刻看到状态栏变化;加一个快捷键,你能立刻验证绑定是否正确。这种“改动-编译-观察”的反馈循环是学习 dwm 的最佳方式。等你理解了默认配置的每一个字段,再去看别人的 config.h,就能看懂每一项的意义,而不是盲目复制。

补丁也一样。先给 dwm 一两周的时间适应用户的习惯,这期间你会发现哪些功能是自己真正需要的,然后有针对性地找补丁。不要一次性把所有热门补丁全装上,那样一来出了问题你根本不知道是哪个补丁引起的。

7.4 我的一些具体配置细节

最后分享几个比较实用的微调,都是在 config.h 里几行代码的事。

把标题栏文字去掉?dwm 本身就没有标题栏,这个不用调。但状态栏左边会显示窗口标题,如果嫌它太占地方,可以改 titleformat:

static const char *titleformat = "%s";

保持默认即可。

窗口间距调整,uselessgap 补丁装好后,改 gap 数值:

static const int gappx = 8;

这个值表示窗口之间的像素间距,我一般设在 6 到 12 之间。太大会浪费屏幕,太小看不出效果。

还有一个很多人不知道的技巧:dwm 的 cmap 功能可以用 Mod + 数字键直接在标签之间跳转,Mod + Shift + 数字键可以把当前窗口发送到另一个标签页并把焦点跟过去。这在多任务并行时效率极高。

8. 结语与实践心得

从下载源码到配置成自己习惯的形状,整个过程其实没有网上说的那么玄学。很多觉得 dwm 难上手的人,卡在的不是某个具体技术点,而是心理预期——总觉得平铺窗口管理器一定要很极客才能用。实际上它的核心概念非常朴素:窗口不重叠、键盘操作、配置写死进二进制。你需要的只是两三天的时间,把快捷键形成肌肉记忆,之后就一切顺畅了。

我个人的体会是,dwm 的每一次重编译都是一次和系统对话的过程。改字体、调布局、打补丁、修冲突,这些动作看似繁琐,却逼着你去理解自己的环境。这种“亲手打造”的成就感,是任何可视化配置界面都给不了的。用久了以后再看那些天天弹出更新提示的桌面环境,反而会觉得它们非常吵闹。

如果你在安装过程中遇到问题,顺着依赖、配置、启动这三个方向排查,绝大多数问题都能解决。最后再分享一个小技巧:dwm 的配置折腾频繁,一定保持 commit 习惯。每次成功构建就提交一次,出问题回滚不过是一条命令的事。祝你在平铺的世界里玩得开心,这套配置值得你为它付出的时间。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/18 5:41:40

百考通资源平台:从海量题库到结构化数据的高效开发实践

1. 为什么我说"百考通"不是又一个资料堆做开发这些年&#xff0c;我攒过的资料库、模板站、教程合集没有十套也有八套&#xff0c;但说实话&#xff0c;大部分都是"收藏即吃灰"。原因很简单&#xff1a;资源数量再多&#xff0c;跟实际开发需求对不上&…

作者头像 李华
网站建设 2026/10/18 5:39:53

大模型工具调用实战:从Function Calling原理到代码实现

1. 为什么大模型需要“外挂工具”&#xff1a;从一个让人抓狂的场景说起先讲一个我实际遇到的场景。刚接触大模型应用开发那会儿&#xff0c;我用某个开源模型写了个内部小助手&#xff0c;准备让它接管公司周报里的数据整理。模型本身很能聊&#xff0c;你问它“上周销售数据怎…

作者头像 李华
网站建设 2026/10/18 5:34:37

Spring Boot健身房管理系统毕设全流程:从数据库设计到答辩指南

一到毕设季&#xff0c;就有不少同学拿着“健身房管理系统”的题目来问我&#xff0c;这个选题在Java毕设里确实常青。Spring Boot做后端、MySQL存数据、页面管会员课程预约收费&#xff0c;业务链路完整&#xff0c;难度又不会高到做不完&#xff0c;是一个性价比很高的经典选…

作者头像 李华
网站建设 2026/10/18 5:33:15

集群安全加固实战:从边界防护到东西向流量管控

给计算机集群加一道安全屏障&#xff0c;这事听起来很宏大&#xff0c;但落到实操上&#xff0c;往往就是一组组规则、一条条策略、几次配置调整。我服务过不少业务集群&#xff0c;从十几台节点的中小规模&#xff0c;到上百台节点的分布式系统都接触过&#xff0c;最大的感受…

作者头像 李华
网站建设 2026/10/18 5:32:18

基于AMESim的NVH仿真:频率域划分、扭振分析与建模实践

简介&#xff1a;面向汽车NVH工程师与仿真分析人员&#xff0c;这份AMESim系统仿真振动噪声NVH解决方案资料&#xff0c;系统讲解如何利用LMS Imagine.Lab AMESim对动力传动、底盘、悬架、制动等系统进行多物理场建模与仿真&#xff0c;覆盖从低频行驶动力学到高频声学舒适性的…

作者头像 李华