Today's Dev #21

December 5, 2024

Today was entirely focused on continuing to polish the definition work on the Display Configuration Batch system. Carved out the definition for the batch actions, cleaned up some extraneous class definitions for Enabling / Disabling Batch classes, and did an initial pass at the DisplayConfigurationCalculation class definition. Right now my current line of thinking is reflected in the following breakdown: You have one DisplayConfigurationBatchSystem. It is expected that the applications which would integrate this batch system (for example Budgie Control Center) would use a D-Bus method to perform a reset of the system when loading the view that'd show displays. Maybe there could be other ways of clearing it like if you were to suspend your system or something, but I am not too worried about automatically clearing it at this time. This class would hold a QMap of our output serials to DisplayConfigurationBatch classes, so there would be at most one for each output serial. Adding a batch for the same serial would clear out any existing one. It would also hold a reference to a DisplayConfigurationCalculation, assuming that either apply or test are called to call our internal createCalculation function on the batch system. This calculation class would be responsible for...well the calculation obviously. It would aggregate all batch system actions, filter out duplicate ones that would have added earliest (for example setting an anchor, then changing it later, this would filter out the first one), calculate the global space and positions for each output, etc. To accomplish this, our DisplayConfigurationBatch createCalculate would call the DisplayConfigurationCalculation::addAction, then at the end call its calculate function. addAction would add it to a QList of buffered actions. calculate would process these and add them to a new QList just called m_actions. Doing some investigating work today, I came across QRect and QSize. QRect seems pretty dope: it enables us to define coordinates (x, y), dimensions (width, height), and keeps it all in a nice container that we could use during our calculation to determine and avoid intersections (it has functions like intersected and intersects). For rotation, I could basically just call transpose to swap width and height (e.g. 90deg or -90deg rotations). I could use several united calls to get the bounding rectangle between two, which would be handy for iterating over output rects to get the global space (total height and width of all the outputs, with proper handling of mirrored outputs). All extremely handy stuff, so my current thinking is having a QRect of the global space, then a QMap of each output to their own QRect. For DisplayConfigurationBatch, you create it for a specific serial with one of two types: DisplayConfigurationBatchType::Enable or DisplayConfigurationBatchType::Disable. If you set it to Enable, you will be allowed to add actions. DisplayConfigurationBatchAction contains basically all the possible properties (as members) for every possible type of an action. Maybe not the best way to do it but it can be cleaned up later after I get some feedback on it. Current types are:
  • SetGamma
  • SetMirrorOf
  • SetMode
  • SetPositionAnchor
  • SetScale
  • SetTransform
Each of these map to a different constructor, all taking the relevant args for their given type. I won't get into all of them...because why...but here are a couple examples:
DisplayConfigurationBatchAction mode(QSize *dimensions, int refresh, QObject *parent = nullptr);
DisplayConfigurationBatchAction setPositionAnchor(
  QString *serial,
  DisplayConfigurationHorizontalAnchor horizontal,
  DisplayConfigurationVerticalAnchor vertical,
  QObject *parent = nullptr
);
In the first one, you might see that I am using QSize instead of specifying width and height separately. Not sure that'll stick around but figured I'd change things up a bit. For setPositionAnchor, it takes a couple different anchor types (one for horizontal and another for vertical). I already described anchoring in a previous Today's Dev, but to here are the current literal enum values:
enum DisplayConfigurationVerticalAnchor {
    Above,
    Top,
    Middle,
    Bottom,
    Below
};

enum DisplayConfigurationHorizontalAnchor {
    Left,
    Right,
    Center,
};
So yea, sorted out all the definitions. Bit of thinking involved I'd say. Started working on implementing some of the actual methods, starting with DisplayConfigurationBatchSystem but a lot of it is placeholder / TODOs until I carve more of the methods out. And guess what I'll be working on tomorrow? :)
Did you know?
You can follow me on Bluesky, Mastodon, or Threads!