Search code examples
awesome-wm

How to get width and height of widget after it's been drawn in awesome?


So this is the scenario: Let's say I have a textbox that I want to place exactly at the right-hand side of the screen, but STILL letting the textbox retain its own dimensions. In other words, I want to just specify the font, let the textbox pick the right dimensions and then place it at the edge of the screen. It'd be really easy if I knew the dimensions, since then I can do

local awful = require("awful")
local wibox = require("wibox")

local text_widget = wibox.widget({
    widget = wibox.widget.textbox,
    font = "Roboto Medium 15",
    text = "hello world",
})

local rightmost_place = wibox.widget({
    layout = wibox.layout.manual,
    {
        text_widget,
        point = {
            y = 0, 
            -- You can't actually do the `text_widget.geometry.width`
            x = awful.screen.focused().geometry.width
                - text_widget.geometry.width
        },
        -- We're not setting these so the textbox
        -- will get its size automatically
        -- forced_width = 
        -- forced_height = 
    },
})

So this way, whenever I were to type something in, the textbox will get bigger, but it would automatically reposition itself according to the x coordinate.

Also, this is not just about textboxes. I've had the same problem with other widgets, so my question is: is there some way to let the widgets get the dimensions that they prefer, but still get their geometry to reposition them where you'd like?


Solution

  • The issue is that widgets can be placed in multiple location (with multiple size) at the same time. This is useful for some case like the textclock to have a single instance (with a single timer) for all screens. This makes getting the size a bit tricky. If you don't plan to use the widget in multiple location, you can cheat and add the width/height properties.

    -- in the declarative syntax, add an `id`
    id = `id_of_the_widget_with_size`,
    
    -- Get the widget (somewhere outside of the declarative section)
    local w = rightmost_place:get_children_by_id("id_of_the_widget_with_size")[1]
    w._real_draw = w.draw
    w.draw = function(self, context, cr, width, height)
        self.width, self.height = width, height
        w._real_draw(self, context, cr, width, height)
    end
    

    Now, in theory, the widget will have a width and height property.