1. 前言

dwm 是 X11 下的平铺式窗口管理器,它是用 C 语言编写的,非常轻量级,全部代码也才不到 2k 行。 它提供了一些基本的窗口管理功能,对于额外的功能,可以通过修改源码来实现。 目前 suckless 官网 上提供了非常多的补丁,可以用来扩展 dwm 的功能。

其中一个很重要的补丁就是 swallow , 它可以让 dwm 在启动一个新的应用程序时,将其嵌入到一个已有的窗口中,而不是启动一个新的窗口。 这样可以大幅度减少多余窗口的数量。

swallow

详细信息可以参考 Luke Smith 的视频

2. 需求分析

swallow 固然很好,但是有时候我们并不希望所有的窗口都 swallow 终端窗口, 比如有时候我在开发游戏过程中,我希望可以看到终端窗口的输出来进行 debug ,这时 swallow 补丁就无法满足我的需求了。

我尝试过其他方式,比如使用 dynamicswallow patch , 但是这个 patch 过于重量级,提供了太多不必要的功能。 所以我决定在 swallow patch 的基础上进行修改,实现只有特定窗口才会被 swallow 的功能。

noswallow

上面演示了noswallow的效果: 通过在执行命令前加上noswallow脚本, 比如noswallow ./your_app,就可以防止your_app被 swallow 。

3. 实现原理

实现过程非常简单:

因为我们需要进行进程间通信(终端和 dwm 之间), 所以我们选择最简单的进程间通信方式:文件。

在 dwm 的dwm.c中的swallow函数开始处,我们添加一个if语句:

void
swallow(Client *p, Client *c)
{
    if (c->noswallow || c->isterminal)
        return;
    if (c->noswallow && !swallowfloating && c->isfloating)
        return;
    // add this to your code
    if (!access("/tmp/noswallow", F_OK))
        return;

access("/tmp/noswallow", F_OK)会检查/tmp/noswallow是否存在,如果存在则返回 0 ,否则返回-1 。

这样我们就可以通过创建或删除/tmp/noswallow文件来控制是否 swallow 。

注意需要sudo make clean install重新编译安装 dwm 。

接下来编写一个简单的脚本noswallow

#!/bin/sh

touch /tmp/noswallow

"$@"  # run your command with arguments

rm /tmp/noswallow

这样在执行命令前加上noswallow脚本,就可以防止该窗口被 swallow 了!(记得将noswallow加到环境变量中。)

具体可以参考我的 commit