一般确实是在窗口管理器里做。
比如我用的是 xmonad,这是 Haskell 写的一个非常 primitive 的窗口管理器,稍微熟悉 Haskell 的话,一下午就可以看完核心部分的代码(而如果你想学 Haskell,xmonad 又是非常不错的入门项目)。它本身功能很少,但是非常的简单和稳定。它的特点是完全的 hackable——核心代码只提供很少的功能,而配置文件由用户用 Haskell 自己写,这个配置文件也并非通常意义上的“配置”——它就是一个 Haskell 程序,而窗口管理器的 main 函数,是在这个配置文件里面的!
比如说这是我的 xmonad 配置文件中的 main 函数:
> main = do
>  xmonad $ ewmh $ defaultConfig {
>    workspaces = ["pri", "2", "3", "4", "misc"],
>    modMask = mod4Mask,
>    terminal = "xfce4-terminal",
>    normalBorderColor = "#000000",
>    focusedBorderColor = "#e63312",
>    focusFollowsMouse = False,
>    clickJustFocuses = False,
>    borderWidth = 0,
>    layoutHook =
>      logModifier (gaps [(U, 32)] (
>        windowSwitcherDecorationWithButtons shrinkText decorationTheme
>         (
>          smartBorders (spacingRaw True (Border 0 0 0 0) False (Border 0 0 0 0) False (
>            draggingVisualizer (
>              boringWindows (
>                maximizeWithPadding 0 (
>                  minimize (
>                    layoutHook defaultConfig))))))))),
>    manageHook = myManageHook,
>    handleEventHook = handleEventHook def <+> 
>      -- fullscreenEventHook <+>
>      fullscreenEventHook2 <+>
>      minimizeEventHook,
>      -- testEventHook,
>    keys = myKeys
>  }
这里面需要注意的是几个 hook,比如 layoutHook 中,minimize 和 maximizeWithPadding 负责最小化和最大化功能,boringWindows 可以在切换窗口时无视掉最小化的窗口,draggingVisualizer 和 windowSwitcherDecorationWithButtons 添加了窗口拖动和标题栏等 stacking WM 的功能,smartBorders 可以在窗口最大化时禁用边框的绘制(当然我现在把边框整个禁用了)——这些都是 Haskell 函数,而这些函数一个个嵌套组合起来传进 layoutHook 这个配置项,再调用 xmonad 提供的 xmonad 函数,就是 main 函数。
layoutHook 中的这些函数不属于 xmonad 核心,而是外部插件,比如这里的 windowSwitcherDecorationWithButtons 我用的是我自己在官方仓库提供的插件的基础上修改过的版本,改出了这么一个标题栏: 
https://i.loli.net/2021/02/10/aUAFmL7DJOHd54C.png注意 Chrome 和 Emacs 的标题栏使用的是不同的背景和字体颜色,实现这个区别的代码就在上面的 Emacs 窗口里。
... 但是本回复的目的并非安利 yet another window manager 。说上面这一大堆只是因为貌似推荐 WM 是本贴的标准格式而已 ... 上面 layoutHook 有一个没提就是 gaps,这个可以禁止 xmonad 使用屏幕边框的区域,比如我这个配置中就保留了屏幕上方 32 像素高的位置放状态栏——这是我看到楼主的问题时的本能反应。但是仔细想来,其他窗口管理器也能处理各种 bar 和 dock 的占位,而它们 99% 没有 xmonad 这么强的定制性,这是什么原理呢?
Gaps 模块的文档( 
https://hackage.haskell.org/package/xmonad-contrib-0.16/docs/XMonad-Layout-Gaps.html )给出了线索:Gaps 仅仅是一个 workaround,处理“dock-type applications”的占位推荐使用 ManageDocks 提供的功能,这是因为这类窗口一般都设置了“STRUTS”属性。
xmonad 这个名字中的 X 来自于 X Window,X Window 本身是应用和系统之间通信的一套协议(至于 Monad 嘛,自然是“a monoid in the category of endofunctors”咯)。其中规定窗口和窗口管理器之间通信的主要是 ICCCM (Inter-Client Communication Conventions Manual, 
https://www.x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html ) 和 EWMH (Extended Window Manager Hints, 
https://specifications.freedesktop.org/wm-spec/wm-spec-1.3.html ),这个 STRUTS,以及“dock-type applications”,属于 EWMH 的范畴。
xmonad 的 ManageDocks 模块就是通过检查 EWMH 规定的这些属性来实现保留 dock 空间功能的: 
https://hackage.haskell.org/package/xmonad-contrib-0.16/docs/src/XMonad.Hooks.ManageDocks.html类似的处理也出现在 Cinnamon 的默认窗口管理器 muffin 中: 
https://github.com/linuxmint/muffin/blob/46b555c27a9abf6b4a05f711770786bf4f6a2361/src/core/constraints.c#L863所以楼主这个问题,可以考虑的标准解决方案是想办法给任务栏窗口设置 EWMH 相关的属性,之后的布局问题,窗口管理器应该会自动处理。