cssgnome-shell-extensionsgjscluttercinnamon

How to get a `St.BoxLayout` to 100% width in a Cinnamon applet (CJS / GJS)?


I am writing my first Cinnamon applet (after I managed to write a desklet).

I have a St.BoxLayout embedded in a PopupMenu.PopupBaseMenuItem in order to get in in a popup menu.

Now I want it's width to be 100% of the popup menu width, but it (i.e. the box containing 1 +2 = 3 in the screenshot) looks like this and just takes its minimal width to contain the embedded text and it grows when you type into it:

screenshot Cinnamon calc applet

I tried:

But it just doesn't expand its width. What else could I try?

I must admit that I'm still looking for a extensive CJS / GJS documentation, browsing other applets' sources seem to be the best way to find out what is actually working ...

Here's the code:

applet.js:

        this.widgets.expressionItem = new PopupMenu.PopupBaseMenuItem({reactive: false, focusOnHover: true});
        this.menu.addMenuItem(this.widgets.expressionItem);
        this.widgets.expressionBox = new St.BoxLayout({
            style_class: "expression-box",
            vertical: true,
            x_align: Clutter.ActorAlign.FILL,
            x_expand: true
        })

stylesheet.css:

.expression-box {
    background-color: lightslategray;
    color: black;
    border-radius: 4px;
    width: 100%;
    padding: 4px;
}

You can find the complete source code in GitHub.


Solution

  • CSS won't help you with layout in this case, as this is handled by the widget toolkit. While pixel widths like width: 100px; may work, percentages will not (unless something has changed quite recently).

    It appears Cinnamon is using JavaScript wrappers around Clutter actors. The function in current master looks like this:

    // adds an actor to the menu item; @params can contain %span
    // (column span; defaults to 1, -1 means "all the remaining width", 0 means "no new column after this actor"),
    // %expand (defaults to #false), and %align (defaults to
    // #St.Align.START)
    addActor(child, params) {
        params = Params.parse(params, { span: 1,
                                        expand: false,
                                        align: St.Align.START });
        params.actor = child;
        this._children.push(params);
        this._signals.connect(this.actor, 'destroy', this._removeChild.bind(this, child));
        this.actor.add_actor(child);
    }
    

    This was also the previous approach used in GNOME Shell, but as you can see the allocation here gets pretty complicated. Since I don't use Cinnamon I can't test this myself, but I would assume that you need to add the child actor with the parameters desired like:

    this.widgets.expressionItem.addActor(this.widgets.expressionBox, {
        expand: true,
        span: -1,
    });
    

    It's unclear whether the child properties on St.BoxLayout will make a difference here, but you may have to play around with those a bit to get the desired effect.