#1235 closed todo (fixed)

draft solution for size-constrained widgets

Reported by: Ichthyostega Owned by: Ichthyostega
Priority: urgent Milestone: 0integration
Component: lumieraGui Keywords: GTK design gui
Sub Tickets: Parent Tickets: #1213, #1219, #1238, #1242

Description (last modified by Ichthyostega)

As a Lumiera UI developer,
I want to control a custom widget's extensions precisely,
to allow for calibrated representation of temporal relations on the timeline.

Background

With our timeline display and the chosen implementation road, we're moving into an arcane corner case of GTK usage. By its very fundamental design choices, GTK layout does not work based on fixed widget sizes and positions. This is a very reasonable choice, since it opens the possibility of translation into various languages, and allows for custom styling in combination with platform and user provided themes.

However, in our case we want to calibrate the timeline canvas, so a given time span corresponds to a fixed horizontal extension.

Thus we need to work out a way to make GTK conform to pre established size constraints, while still retaining some degree of style flexibility. Since GTK seemingly does not offer any public API to define the exact extension of a widget, we need to understand the inner workings of GTK's layout engine and come up with creative ways to (ab)use the existing APIs, so to make the GTK layout engine deliver those extensions we pre-established from our timeline calibration.

Acceptance Criteria

This is a research task; the goal is to find out

  • if the desired behaviour can even be achieved
  • implement a prototype, ready for later refinement



Change history (7)

comment:1 by Ichthyostega, at 2022-09-23T20:29:37Z

Status: newaccepted

Picked up some pre-investigation I did last year; up to now I had used button widgets as placeholder while developing a framework for gestures and dragging of clips in the timeline. During that design work, I already found out that it is impossible to size confine a GTK widget, while it might be possible to manipulate the calculation of a "size allocation" by returning rigged values from the get_preferred_width_vfunc(). Today I did a in-depth GTK code survey and basically confirmed this "point of attack"

For context, last year I also posted a question on Stackoverflow with a detailed description of the problem, asking for a canonical solution approach. This question only got 55 views, zero upvotes on the question, no comments and no responses, and was deleted by the "Community" bot after being stale for over one year. This is a telltale sign that we're in danger territory here — our use-case just seems to be off the regular focus of the GTK community (the point to note is that we deliberately do not want to do all with custom drawing, we want to use GTK widgets).

Last edited at 2022-09-23T20:32:09Z by Ichthyostega (previous) (diff)

comment:2 by Ichthyostega <prg@…>, at 2022-09-24T00:41:47Z

In 3f4f2d3/Lumiera:

ElementBox: detailed survey of GTK layout code (see #1235)

Investigate how the GTK implementation allocates size extension
to widgets and child widgets; identify possible extensions points
and work out a solution strategy to make GTK observe our specific
size constraints, which are derived from a time calibrated canvas.

comment:3 by Ichthyostega, at 2022-09-24T00:42:32Z

Summary: draft solution for size-confined widgetsdraft solution for size-constrained widgets

comment:4 by Ichthyostega, at 2022-09-29T21:37:58Z

Solution approach confirmed to work

  • started a page in the Lumiera documentation to collect findings about the GTK implementation
  • GTK never squeezes widgets, but only ever expands size allocation
  • most containers use the natural size request as base, but relevant containers (esp Gtk::Layout) starts with the minimal size request.
  • thus we need to return our size constraint from these get_preferred_*-VFuncs
    • obviously we also need to implement get_request_mode_vfunc()
    • it is advisable to implement both get_desired_width|height()
      (even while in normal usage only the first one will be called, GTK code is not especially concise and implementation patterns are often repeated redundantly, and thus it's quite possible that the other one will be invoked on occasion). However, we only need to implement get_preferred_height_for_width_vfunc(), since the dual counterpart has a sane fallback (get_preferred_width_for_height() by default invokes get_preferred_width() )
  • and in addition we should override the Gtk::Widget::on_size_allocate() virtual function and then impose the provided allocation onto our child widgets
    • to make this work, it is our own responsibility to manipulate those children to fit (since we have declared to GTK that our widget only needs this limited extension)
    • we can at this point safely hide child widgets — the function is called already prior to the first drawing, and the hidden state is reflected immediately in all layout calculations
    • we should be prepared for very frequent and redundant calls to these functions; they are invoked on each focus change...
    • we need to care that CSS does not add any further margin or borders, since we can only control the nominal extension with this method

I have conducted a very extensive survey of the layout engine and I'm confident this solution is not a hack, but completely in-line with the semantics of the engine. As long as we don't add further extension via CSS and as long as we don't add the ElementBoxWidget into a container with fill-layout, GTK will precisely reflect the size request of the widgets. In case we misrepresent the numbers or break the layout constraints, no harm will be done beyond possibly garbled drawing on screen.

Last edited at 2022-09-29T21:53:52Z by Ichthyostega (previous) (diff)

comment:5 by Ichthyostega, at 2022-10-16T01:18:42Z

blocking: 12191213, 1219, 1238, 1242
Description: modified (diff)

Meanwhile I have conducted further experiments with the implementation draft of ElementBoxWidget

  • immediately retrieving the extension of sub-widgets directly from resizing code: ✔ works
  • hiding sub-widgets directly when receiving a size-constraint: ✔ works (without flickering)
  • adaptation of text content: was experimentally confirmed
    ⟹ further implementation delayed ⌛ (#1242)
Last edited at 2022-10-16T01:28:22Z by Ichthyostega (previous) (diff)

comment:6 by Ichthyostega <prg@…>, at 2022-10-21T17:18:47Z

Resolution: fixed
Status: acceptedclosed

In eb500dd/Lumiera:

ElementBox: successfully implemented size-constrained ClipWidget (closes #1235)

  • restructure the widgets used to implement ElementBox
  • inject a Gtk::EventBox top-level base type to capture all Gdk-Events
  • push the Gtk::Frame one level down (TODO: API for managing children)

With these changes

  • dragging of Clips in the timeline works as expected
  • size constraints are observed precisely
  • all warnings and assertion failures from GTK disappeared

Thus we can conclude that the solution approach for size constrained widgets
was successful and this challenging problem is solved.

comment:7 by Undercover Agent, at 2025-12-25T00:00:00Z

blocking: 1213, 1219, 1238, 1242
Parent Tickets: 1213, 1219, 1238, 1242

Migration MasterTickets ⟼ Subtickets-plugin

Note: See TracTickets for help on using tickets.