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

GNOME扩展窗口边框层级问题求助:边框覆盖所有窗口

GNOME扩展窗口边框层级问题解决

问题根源

你的代码存在两个核心问题导致边框覆盖所有窗口:

  • 将边框作为窗口actor的子节点,使得边框层级始终高于窗口内容,且所有边框的堆叠层级继承自同一父容器,无法随窗口层级变化。
  • restack函数逻辑错误,未正确关联边框与对应窗口的层级关系,遍历子节点的操作完全不符合需求。

修改方案

以下是调整后的代码,关键修改点已标注:

_add_orange_border_to_window = function (win) {
    if (!win) return;

    // 获取窗口的实际 compositor actor(而非其父节点)
    let windowActor = win.get_compositor_private();
    if (!windowActor) return;
    // 获取窗口actor的父容器(所有窗口actor都在这个容器里)
    let parentContainer = windowActor.get_parent();
    if (!parentContainer) return;

    const BORDERSIZE = 3;

    if (!borders[win]) {
        borders[win] = new St.Bin({
            style_class: 'border'
        });
        // 将边框添加到窗口actor的父容器(作为兄弟节点)
        parentContainer.add_child(borders[win]);
        // 初始时将边框置于窗口actor下方
        parentContainer.set_child_below_sibling(borders[win], windowActor);
    }

    function redrawBorder() {
        let rect = windowActor.get_allocation_box();
        // 基于窗口actor的实际位置和大小计算边框位置
        borders[win].set_position(rect.x1 - BORDERSIZE, rect.y1 - BORDERSIZE);
        borders[win].set_size(rect.x2 - rect.x1 + 2 * BORDERSIZE, rect.y2 - rect.y1 + 2 * BORDERSIZE);
    }

    // 修正restack逻辑:每次窗口堆叠变化时,将边框置于对应窗口下方
    function restack() {
        if (borders[win] && windowActor.get_parent()) {
            windowActor.get_parent().set_child_below_sibling(borders[win], windowActor);
        }
    }

    redrawBorder();

    // 连接信号,注意使用窗口的restacked信号而非Display的全局信号
    signalHandlers[win] = {
        sizeChangedId: win.connect('size-changed', redrawBorder),
        positionChangedId: win.connect('position-changed', redrawBorder),
        // 监听窗口自身的restacked信号,而非全局Display信号,更精准
        restackHandlerID: win.connect('restacked', restack),
        unmanagedId: win.connect('unmanaged', () => {
            if (borders[win]) {
                borders[win].destroy(); // 直接销毁边框actor
                delete borders[win];
            }
            // 断开所有信号
            win.disconnect(signalHandlers[win].sizeChangedId);
            win.disconnect(signalHandlers[win].positionChangedId);
            win.disconnect(signalHandlers[win].restackHandlerID);
            win.disconnect(signalHandlers[win].unmanagedId);
            delete signalHandlers[win];
        })
    };
}

关键修改说明

  • 边框容器调整:将边框从窗口actor的子节点改为兄弟节点,放入同一父容器,这样可以独立控制边框与窗口的堆叠顺序。
  • 堆叠顺序控制:使用set_child_below_sibling将边框固定在对应窗口actor的正下方,确保窗口始终在边框之上,且边框层级随窗口变化。
  • 信号优化:监听窗口自身的restacked信号而非全局Display信号,避免不必要的全局触发,提升性能和精准度。
  • 坐标计算优化:使用窗口actor的get_allocation_box()获取实际渲染的位置和大小,比win.get_frame_rect()更准确,避免因窗口装饰导致的偏移。
  • 资源清理优化:直接调用borders[win].destroy()彻底清理边框actor,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 10:33:17