awesomeWM / awesome

awesome window manager
https://awesomewm.org/
GNU General Public License v2.0
6.37k stars 598 forks source link

Unified way to query the optimal size for a widget or layout #611

Open Elv13 opened 8 years ago

Elv13 commented 8 years ago

Radical use a lot of :fit(9999,9999) or other hacks like this across the board to get the preferred size of a widget. This is usually used to determine the minimum width of the menu wibox to avoid ... strings.

Currently, textboxes have:

    textbox:get_preferred_size()

However, this isn't available for all widgets and for containers (layouts). Naughty have some code to approximate this: https://github.com/awesomeWM/awesome/blob/master/lib/naughty/core.lua#L612

However, it is hardcoded. It compute the size of all actions and text by hand. Using :fit(9999,9999) always was hacky, but work. That being said, an unified/standardized way to get such information for a layout and/or widget would be very useful for notifications, menu, popups and tooltips.

Any idea how to best handle this?

Ref: https://github.com/awesomeWM/awesome/pull/398#issuecomment-134938189

Edit:

Here is a hacky implementation I monkeypatched to all widgets (but textbox)

local function get_preferred_size(self, context, width, height)
  local context = context or 1

  if type(context) == "number" then
    context = {dpi=beautiful.xresources.get_dpi(context)}
  elseif not context.dpi then
    context.dpi = beautiful.xresources.get_dpi(1)
  end

  return self:fit(context, width or 9999, height or 9999)
end
psychon commented 8 years ago

What semantics do you expect from this new function? An imagebox with an image of size 1x1 and with resizing allowed will happily return 9999x9999 for :fit(9999,9999) and I can't really say that this is wrong (the image could be a cairo recording surface that can be freely resized to any size).

Not even textboxes have a single preferred size. They have a size "assuming that unlimited space is available" (:get_preferred_size()) and they can tell you how much height they need for a given width (:get_height_for_width()).

Previously, naughty was using the :fit(-1, -1)-hack. I have naughty.config.defaults.width = something in my config. With the old code that meant that long notifications were ellipsized (...). With the new code (:get_height_for_width()), these notifications are now twice as high and show the full message. I like this new behavior a lot more. However, something like :get_width_for_height() is AFAIK not possible with Pango.

So, even for just textboxes and imageboxes this stuff is complicated. Perhaps we can come up with something usable here first? (I think that GUI toolkits solve this by having fixed sizes for images? That's lame...)

psychon commented 8 years ago

Some GTK docs on how their system works: https://developer.gnome.org/gtk3/stable/GtkWidget.html#geometry-management (But I guess GTK's system will always be much more complicated than what awesome needs)

TL;DR: Widgets have minimum and natural width / height and can be queried for a "height_for_width" / "width_for_height" similar to what is now implemented on textboxes.

(I also like https://developer.gnome.org/gtk3/stable/GtkContainer.html#GtkContainer.description which basically says there are widgets, "layouts containing a single widget" (e.g. draw a frame around it, make it clickable, ...) and "layouts arranging widgets" (similar to wibox.layout.fixed))