@@ -55,6 +55,7 @@ is" without express or implied warranty.
5555#include "../../randr/randrstr.h"
5656#include "inputstr.h"
5757#include "mivalidate.h"
58+ #include "list.h"
5859
5960#include "Agent.h"
6061#include "Display.h"
@@ -3931,6 +3932,28 @@ typedef struct {
39313932 INT32 * y_splits ;
39323933} nxagentScreenSplits ;
39333934
3935+ /*
3936+ * Structure containing the boxes an nxagent session window is split into.
3937+ *
3938+ * Only used locally, not exported.
3939+ */
3940+ typedef struct {
3941+ struct xorg_list entry ;
3942+ BoxRec box ; /*
3943+ * You might be tempted to use RegionRec here. Do not.
3944+ * A region is really an ordered and minimal set of horizontal
3945+ * bands. A window tiling will in most cases not be minimal,
3946+ * due to the need to split at display boundaries.
3947+ * A Region is more minimal than this.
3948+ * C.f., https://web.archive.org/web/20170520132137/http://magcius.github.io:80/xplain/article/regions.html
3949+ */
3950+ } nxagentScreenBoxesElem ;
3951+
3952+ /*
3953+ * Can't typedef struct xorg_list to nxagentScreenBoxes, or else I would have.
3954+ */
3955+ typedef struct xorg_list nxagentScreenBoxes ;
3956+
39343957/*
39353958 * Helper function that takes a potential split point, the window bounds,
39363959 * a split count and a splits array.
@@ -4118,6 +4141,161 @@ static nxagentScreenSplits* nxagentGenerateScreenSplitList(XineramaScreenInfo *s
41184141 return (ret );
41194142}
41204143
4144+ /* Helper function printing out a splits list. */
4145+ static void nxagentPrintSplitsList (const INT32 * splits , const size_t count , const char * func , Bool is_x ) {
4146+ fprintf (stderr , "%s: " , func );
4147+ if (is_x ) {
4148+ fprintf (stderr , "X" );
4149+ }
4150+ else {
4151+ fprintf (stderr , "Y" );
4152+ }
4153+ fprintf (stderr , " split list: [" );
4154+
4155+ for (size_t i = 0 ; i < count ; ++ i ) {
4156+ if (i > 0 ) {
4157+ fprintf (stderr , ", " );
4158+ }
4159+
4160+ fprintf (stderr , "%u" , splits [i ]);
4161+ }
4162+
4163+ fprintf (stderr , "]\n" );
4164+ }
4165+
4166+ /* Helper to clear out a screen boxes list. */
4167+ static void nxagentFreeScreenBoxes (nxagentScreenBoxes * boxes ) {
4168+ if (!(boxes )) {
4169+ return ;
4170+ }
4171+
4172+ nxagentScreenBoxesElem * cur = NULL ,
4173+ * next = NULL ;
4174+
4175+ xorg_list_for_each_entry_safe (cur , next , boxes , entry ) {
4176+ xorg_list_del (& (cur -> entry ));
4177+ SAFE_FREE (cur );
4178+ }
4179+
4180+ xorg_list_init (boxes );
4181+ }
4182+
4183+ /*
4184+ * Given a list of splits, sorts them and calculates a tile pattern for the
4185+ * current window.
4186+ * In case of errors, returns an empty list.
4187+ */
4188+ static nxagentScreenBoxes * nxagentGenerateScreenCrtcs (nxagentScreenSplits * splits ) {
4189+ struct xorg_list * ret = NULL ;
4190+
4191+ ret = calloc (sizeof (nxagentScreenBoxes ), 1 );
4192+ if (!(ret )) {
4193+ return (ret );
4194+ }
4195+
4196+ xorg_list_init (ret );
4197+
4198+ if (!(splits )) {
4199+ return (ret );
4200+ }
4201+
4202+ qsort (splits -> x_splits , splits -> x_count , sizeof (* splits -> x_splits ), nxagentCompareSplits );
4203+ qsort (splits -> y_splits , splits -> y_count , sizeof (* splits -> y_splits ), nxagentCompareSplits );
4204+
4205+ #ifdef DEBUG
4206+ nxagentPrintSplitsList (splits -> x_splits , splits -> x_count , __func__ , TRUE);
4207+ nxagentPrintSplitsList (splits -> y_splits , splits -> y_count , __func__ , FALSE);
4208+ #endif
4209+
4210+ /*
4211+ * Since the split lists are sorted now, we can go ahead and create boxes in
4212+ * an iterative manner.
4213+ */
4214+ #ifdef DEBUG
4215+ {
4216+ /* Avoid using %zu printf specifier which may not be supported everywhere. */
4217+ long long unsigned x_splits = splits -> x_splits ;
4218+ long long unsigned x_splits = splits -> x_splits ;
4219+ fprintf (stderr , "%s: should generate (x_splits [%llu] + 1) * (y_splits [%llu] + 1) = %llu boxes.\n" , __func__ , x_splits , y_splits , (x_splits + 1 ) * (y_splits + 1 ));
4220+ }
4221+ #endif
4222+ /* v-- implicit split point at agent window's bottommost edge! */
4223+ for (size_t i = 0 ; i <= splits -> y_count ; ++ i ) {
4224+ /* Looping over "rows" here (hence y splits). */
4225+ CARD32 start_y = -1 ,
4226+ end_y = -1 ;
4227+
4228+ if (0 == i ) {
4229+ start_y = nxagentOption (Y );
4230+ }
4231+ else {
4232+ start_y = splits -> y_splits [i - 1 ];
4233+ }
4234+
4235+ if (i == splits -> y_count ) {
4236+ end_y = splits -> y_splits [i ];
4237+ }
4238+ else {
4239+ end_y = (start_y + nxagentOption (Height ));
4240+ }
4241+
4242+ /* v-- implicit split point at agent window's rightmost edge! */
4243+ for (size_t y = 0 ; y <= splits -> x_count ; ++ y ) {
4244+ /* Looping over "cols" here (hence x splits). */
4245+ CARD32 start_x = -1 ,
4246+ end_x = -1 ;
4247+
4248+ if (0 == y ) {
4249+ start_x = nxagentOption (X );
4250+ }
4251+ else {
4252+ start_x = splits -> x_splits [y - 1 ];
4253+ }
4254+
4255+ if (y == splits -> x_count ) {
4256+ end_x = splits -> x_splits [y ];
4257+ }
4258+ else {
4259+ end_x = (start_x + nxagentOption (Width ));
4260+ }
4261+
4262+ nxagentScreenBoxesElem * new_box = calloc (sizeof (nxagentScreenBoxesElem ), 1 );
4263+
4264+ if (!(new_box )) {
4265+ nxagentFreeScreenBoxes (ret );
4266+ return (ret );
4267+ }
4268+
4269+ /* Box extends from (start_x, start_y) to (end_x, end_y). */
4270+ new_box -> box .x1 = start_x ;
4271+ new_box -> box .x2 = end_x ;
4272+ new_box -> box .y1 = start_y ;
4273+ new_box -> box .y2 = end_y ;
4274+
4275+ xorg_list_add (& (new_box -> entry ), ret );
4276+ }
4277+ }
4278+
4279+ #if defined(DEBUG ) || defined(WARNING )
4280+ {
4281+ long long unsigned count = 0 ;
4282+ nxagentScreenBoxesElem * cur = NULL ;
4283+ xorg_list_for_each_entry (cur , ret , entry ) {
4284+ ++ count ;
4285+ }
4286+ #ifdef DEBUG
4287+ fprintf (stderr , "%s: generated %llu boxes\n" , __func__ , count );
4288+ #endif
4289+ if (count < ((splits -> x_count + 1 ) * (splits -> y_count + 1 ))) {
4290+ long long unsigned expect = ((splits -> x_count + 1 ) * (splits -> y_count + 1 ));
4291+ fprintf (stderr , "%s: WARNING! Generated only %llu boxes, expected: %llu\n" , __func__ , count , expect );
4292+ }
4293+ }
4294+ #endif
4295+
4296+ return (ret );
4297+ }
4298+
41214299/*
41224300 Destroy an output after removing it from any crtc that might reference it
41234301 */
0 commit comments