0

I am working on a gnome extension. I am trying to put border around windows.

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

    let actor = win.get_compositor_private().get_parent();
    if (!actor) return;

    if (!borders[win]) {
        borders[win] = new St.Bin({
            style_class: 'border'
        });
        actor.add_child(borders[win]);
    }

    const BORDERSIZE = 3;

    function redrawBorder() {
        let rect = win.get_frame_rect();
        borders[win].set_position(rect.x - BORDERSIZE, rect.y - BORDERSIZE);
        borders[win].set_size(rect.width + 2 * BORDERSIZE, rect.height + 2 * BORDERSIZE);
    }

    function restack(display){
        actor.get_children().forEach(
            (child) => {
                let sibling = Meta.get_window_group_for_display(display);
                sibling.set_child_above_sibling(actor, this);
            }
        )
    }

    redrawBorder();

    // Connect to the size-changed and position-changed signals
    signalHandlers[win] = {
        sizeChangedId: win.connect('size-changed', redrawBorder),
        positionChangedId: win.connect('position-changed', redrawBorder),
        restackHandlerID : Display.connect('restacked', restack),
        unmanagedId: win.connect('unmanaged', () => {
            actor.remove_child(borders[win]);
            win.disconnect(signalHandlers[win].sizeChangedId);
            win.disconnect(signalHandlers[win].positionChangedId);
            win.disconnect(signalHandlers[win].restackHandlerID);
            win.disconnect(signalHandlers[win].unmanagedId);
            delete borders[win];
            delete signalHandlers[win];
        })
    };
}

This code works. But there is an issue. When drawing multiple borders all the borders seems to be on top of all the windows.

borders on top of all the windows

I have checked Adding color to borders gnome windows. It says:

That’s because the borders aren’t actually windows. The compositor has no idea where to put them in the stack, so ignores them.

You have to move them to the right layer yourself, and connect to the global.display('restacked') signal to update them.

There is also a working code there.

But I could not figure out what to do. The given code is all i have managed so far and it is giving rectangles on top of all the windows.

What can I do?

4
  • Have you tried the code at the bottom of the post you linked to? The line global.window_group.set_child_above_sibling(window.border, child) in that code looks like it does what you want. Commented Jul 6, 2024 at 17:11
  • I created a text extension with that complete code. It has the same issue he mentioned. I understand that the solution is around global.window_group, but could not get it to work. Commented Jul 7, 2024 at 6:47
  • 1
    Hi Andy, The problem is solved. Please check github.com/blueray453/gnome-utils-by-blueray453/blob/main/… The code at the bottom of the post was buggy (at least did not work for me). Anyways, I have another question, I my code, I need to call a function to markedWindowFunctions.js from windowFunctions.js. I am wondering if there is a standard for that in gnome extension. Commented Jul 8, 2024 at 9:47
  • 1
    There probably isn't a standard function, it seems like something GNOME Shell would do in a very specific way, so not well suited for a general function. Commented Jul 9, 2024 at 17:11

1 Answer 1

1

Alhamdulillah, The problem is solved.

let markedWindowsData = {};

_redraw_border = function (win, border) {
    let rect = win.get_frame_rect();
    border.set_position(rect.x, rect.y);
    border.set_size(rect.width, rect.height);
}

_mark_window(win) {
    if (!win) return;

    let actor = win.get_compositor_private();
    let actor_parent = actor.get_parent();

    let border = new St.Bin({
        style_class: 'border'
    });

    actor_parent.add_child(border);

    this._redraw_border(win, border);

    markedWindowsData[win] = {
        win_id: win.get_id(),
        border: border,
        sizeChangedId: win.connect('size-changed', () => this._redraw_border(win, border)),
        positionChangedId: win.connect('position-changed', () => this._redraw_border(win, border)),
        restackHandlerID: Display.connect('restacked', (display) => {
            let wg = Meta.get_window_group_for_display(display);
            wg.set_child_above_sibling(border, actor);
        }),
        unmanagedId: win.connect('unmanaged', () => {
            global.window_group.remove_child(border);
            win.disconnect(markedWindowsData[win].sizeChangedId);
            win.disconnect(markedWindowsData[win].positionChangedId);
            Display.disconnect(markedWindowsData[win].restackHandlerID);
            win.disconnect(markedWindowsData[win].unmanagedId);
            delete markedWindowsData[win];
        })
    };
}

For complete example, please check here.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.