Skip to content

Commit 39d5228

Browse files
committed
nx-X11/programs/Xserver/hw/nxagent/Screen.c: add screen boxes generation algorithm/function.
1 parent e8678ac commit 39d5228

File tree

1 file changed

+178
-0
lines changed
  • nx-X11/programs/Xserver/hw/nxagent

1 file changed

+178
-0
lines changed

nx-X11/programs/Xserver/hw/nxagent/Screen.c

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)