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
相关产品推荐
相关产品推荐

