You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Python在GNOME桌面中将窗口移动至桌面图标层下方

GNOME X11会话下用Python将窗口置于桌面图标层下方

本方案仅适用于Ubuntu GNOME的X11会话,Wayland会话下Xlib无全局窗口操作权限,无法实现该需求。登录时在登录界面点齿轮选择「GNOME on Xorg」即可切换到支持的会话,登录后执行echo $XDG_SESSION_TYPE返回x11即为环境符合要求。

核心实现逻辑

GNOME X11下窗口按栈顺序叠放,从最底层到最顶层顺序固定:

  • 最底层:X根窗口,即系统绘制桌面壁纸的层
  • 向上第二层:桌面图标容器窗口,Ubuntu默认桌面图标扩展、GNOME原生图标功能都运行在这层,窗口会携带标准的_NET_WM_WINDOW_TYPE_DESKTOP类型标记
  • 中间层:所有普通应用窗口
  • 最顶层:置顶窗口、弹窗、通知等元素
    要把目标窗口放到桌面图标层下方,本质就是操作X服务器的窗口栈,把目标窗口的层级调整到桌面图标容器窗口的紧邻下方即可。

前置依赖安装

执行以下命令安装所需的Python Xlib库,二选一即可:

# 系统源安装(推荐,兼容性更好)
sudo apt update && sudo apt install python3-xlib

# pip安装
pip install python3-xlib

完整实现代码

from Xlib import X, display, Xatom
from Xlib.protocol import event

# 初始化当前用户的X服务器连接
d = display.Display()
root = d.screen().root

# 预定义需要用到的X协议原子
NET_WM_WINDOW_TYPE = d.intern_atom('_NET_WM_WINDOW_TYPE')
NET_WM_WINDOW_TYPE_DESKTOP = d.intern_atom('_NET_WM_WINDOW_TYPE_DESKTOP')
NET_WM_NAME = d.intern_atom('_NET_WM_NAME')
UTF8_STRING = d.intern_atom('UTF8_STRING')
NET_WM_PID = d.intern_atom('_NET_WM_PID')

def get_desktop_window():
    """遍历所有顶层窗口,定位桌面图标所在的容器窗口"""
    raw_windows = root.query_tree().children
    for win in raw_windows:
        try:
            win_type_prop = win.get_full_property(NET_WM_WINDOW_TYPE, X.AnyPropertyType)
            if not win_type_prop:
                continue
            # 匹配标记为桌面类型的窗口
            if win_type_prop.value[0] == NET_WM_WINDOW_TYPE_DESKTOP:
                return win
        except Exception:
            continue
    raise RuntimeError("未找到桌面图标层窗口,请确认当前运行在GNOME X11会话且已启用桌面图标功能")

def get_target_window_by_title(title_keyword):
    """按标题关键词匹配需要调整层级的目标窗口"""
    raw_windows = root.query_tree().children
    for win in raw_windows:
        try:
            title_prop = win.get_full_property(NET_WM_NAME, UTF8_STRING)
            if not title_prop:
                continue
            win_title = title_prop.value.decode('utf8', errors='ignore')
            if title_keyword in win_title:
                return win
        except Exception:
            continue
    raise RuntimeError(f"未找到标题包含「{title_keyword}」的窗口")

if __name__ == "__main__":
    # 1. 获取桌面图标层窗口对象
    desktop_win = get_desktop_window()
    # 2. 替换为你要操作的窗口的标题关键词,比如要操作Firefox就传"Firefox"
    target_win = get_target_window_by_title("替换为你的目标窗口标题关键词")
    
    # 3. 核心操作:将目标窗口调整到桌面窗口的下方
    target_win.configure(
        sibling=desktop_win,
        stack_mode=X.Below
    )
    
    # === 可选配置开始 ===
    # 如果需要窗口长期停留在图标层下方,不会被GNOME WM自动抬回普通层,可以取消下面这段注释
    # 注意:加了这个属性后窗口不会出现在Alt+Tab切换列表,适合动态壁纸、桌面挂件类场景
    # target_win.change_property(
    #     NET_WM_WINDOW_TYPE,
    #     Xatom.ATOM,
    #     32,
    #     [NET_WM_WINDOW_TYPE_DESKTOP],
    #     X.PropModeReplace
    # )
    # === 可选配置结束 ===
    
    # 将所有操作提交到X服务器生效
    d.sync()
    print("窗口层级调整完成")

使用说明

  • 把代码里get_target_window_by_title的参数替换成目标窗口的标题关键词即可,比如要调整终端窗口就传"终端"或"Terminal"。
  • 如果需要按进程PID匹配窗口,可以参考get_target_window_by_title的逻辑,读取窗口的_NET_WM_PID属性做匹配即可。
  • 不要用sudo运行脚本,否则会因为权限上下文不对找不到当前用户的X会话。

常见问题排查

  • 调整完窗口过几秒自动跳回普通层:把代码里可选配置段的注释打开,给目标窗口打上桌面类型标记,GNOME窗口管理器就不会自动调整它的栈顺序。
  • 找不到桌面窗口:如果用了第三方桌面图标扩展未按标准标记窗口类型,可以在终端执行xwininfo -tree -root打印完整窗口树,手动找到承载图标的窗口ID,直接传入调整逻辑即可。
  • 窗口被图标完全挡住:属于正常现象,因为窗口已经在图标层下方,如果需要交互可以暂时隐藏桌面图标,或者只给不需要点击的壁纸类窗口用这个层级。

内容的提问来源于stack exchange,提问作者Fido_de07

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 17:06:26