CTWM
Loading...
Searching...
No Matches
/usr/src/RPM/BUILD/ctwm-4.1.0/r_layout.c
Go to the documentation of this file.
1/*
2 * Copyright notice...
3 */
4
5#include "ctwm.h"
6
7#include <stdlib.h>
8#include <stdio.h>
9#include <string.h>
10
11#include "r_layout.h"
12#include "r_area_list.h"
13#include "r_area.h"
14#include "util.h"
15
16
17/*
18 * Prototype internal funcs
19 */
20static void _RLayoutFreeNames(RLayout *self);
22 const RArea *far_area);
24 const RArea *far_area);
26 const RArea *area);
28 const RArea *area);
29
30/* Foreach() callbacks used in various lookups */
31static bool _findMonitorByXY(const RArea *cur, void *vdata);
32static bool _findMonitorBottomEdge(const RArea *cur, void *vdata);
33static bool _findMonitorTopEdge(const RArea *cur, void *vdata);
34static bool _findMonitorLeftEdge(const RArea *cur, void *vdata);
35static bool _findMonitorRightEdge(const RArea *cur, void *vdata);
36
37
38
39
40/************************
41 *
42 * First, some funcs for creating and destroying RLayout's in various
43 * ways.
44 *
45 ************************/
46
47
48/**
49 * Create an RLayout for a given set of monitors.
50 *
51 * This stashes up the list of monitors, and precalculates the
52 * horizontal/vertical stripes that compose it.
53 */
54RLayout *
56{
57 RLayout *layout = malloc(sizeof(RLayout));
58 if(layout == NULL) {
59 abort();
60 }
61
62 layout->monitors = monitors;
63 layout->horiz = RAreaListHorizontalUnion(monitors);
64 layout->vert = RAreaListVerticalUnion(monitors);
65 layout->names = NULL;
66
67 return layout;
68}
69
70
71/**
72 * Create a copy of an RLayout with given amounts cropped off the sides.
73 * This is used anywhere we need to pretend our display area is smaller
74 * than it actually is (e.g., via the BorderBottom/Top/Left/Right config
75 * params)
76 */
77RLayout *
80{
84 if(cropped_monitors == NULL) {
85 return NULL; // nothing to crop, same layout as passed
86 }
87
89}
90
91
92/**
93 * Clean up and free any RLayout.names there might be in an RLayout.
94 */
95static void
97{
98 if(self == NULL) {
99 return;
100 }
101 if(self->names != NULL) {
102 free(self->names);
103 self->names = NULL;
104 }
105}
106
107
108/**
109 * Clean up and free an RLayout.
110 */
111void
113{
114 if(self == NULL) {
115 return;
116 }
117
118 RAreaListFree(self->monitors);
119 RAreaListFree(self->horiz);
120 RAreaListFree(self->vert);
122 free(self);
123}
124
125
126/**
127 * Set the names for our monitors in an RLayout. This is only used for
128 * the RLayout that describes our complete monitor layout, which fills in
129 * the RANDR names for each output.
130 */
131RLayout *
133{
135 self->names = names;
136 return self;
137}
138
139
140
141/************************
142 *
143 * Next, a few util funcs for dealing with RArea's that are outside our
144 * RLayout, but we want to find the nearest way to move them inside, then
145 * return a list of which RArea's they'd be intersecting with.
146 *
147 ************************/
148
149
150/**
151 * Given an RArea that doesn't reside in any of the areas in our RLayout,
152 * create a list of maximally-tall RArea slices out of our layout where
153 * it would wind up if we brought it onto the nearest screen edge. This
154 * yields a RAreaList as tall as the slice[es] the window would touch if
155 * we moved it in.
156 *
157 * If we had the move the window horizontally (it was off-screen to the
158 * right or left), it results in a 1-pixel-wide slice of the right- or
159 * left-most self->vert.
160 *
161 * If we had to move it vertically (it was off to the top or bottom), it
162 * winds up being whatever horizontal intersection with self->vert would
163 * result from the window's x and width, with the full height of the
164 * involved slices.
165 *
166 * This is the vertical-stripe-returning counterpart of
167 * _RLayoutRecenterHorizontally().
168 *
169 * This is called only by \_RLayoutVerticalIntersect() when given an RArea
170 * that doesn't already intersect the RLayout. Will probably not tell
171 * you something useful if given a far_area that already _does_ intersect
172 * self.
173 *
174 * \param self Our current monitor layout
175 * \param far_area The area to act on
176 */
177static RAreaList *
179{
180 RArea big = RAreaListBigArea(self->monitors), tmp;
181
182 // We assume far_area is outside of self. So it's in one of the
183 // three labelled areas:
184 //
185 // |_V_| ___ tmp.top
186 // | | |
187 // L| |R |
188 // |___| ___ tmp.bottom
189 // | V |
190 //
191 // So we'll create an RArea that's the y and height of big (a giant
192 // rectangle covering all the monitors), so that its intersection
193 // with self->vert will always cover a full vertical stripe. Then
194 // we'll set its x/width so that it's shifted to be at least
195 // minimally inside big somehow.
196
197 // Where did it wind up?
198 if((far_area->x >= big.x && far_area->x <= RAreaX2(&big))
199 || (RAreaX2(far_area) >= big.x && RAreaX2(far_area) <= RAreaX2(&big))) {
200 // In one of the V areas. It's already in a horizontal position
201 // that would fit, so we just keep x/width.
202 tmp = RAreaNew(far_area->x, big.y,
203 far_area->width, big.height);
204 }
205 else if(RAreaX2(far_area) < big.x) {
206 // Off to the left side in L, so move it over just far enough
207 // that 1 pixel of it protrudes into the left side.
208 tmp = RAreaNew(big.x - far_area->width + 1, big.y,
209 far_area->width, big.height);
210 }
211 else {
212 // Off to the right side in R, so move it over just far enough
213 // that 1 pixel of it protrudes into the right side.
214 tmp = RAreaNew(RAreaX2(&big), big.y,
215 far_area->width, big.height);
216 }
217
218 // Then intersect that (full height, at least 1 pixel horizontally
219 // somewhere) with our collection of vertical stripes, to yield an
220 // answer. If the window was off to the left or right, this will
221 // yield a 1-pixel-wide slice of either the left- or right-most
222 // ->vert of our layout. If it were off the top of bottom, though,
223 // it'll yield some slice of 1 (or more) of our ->vert's, as wide as
224 // the window itself was.
225 return RAreaListIntersect(self->vert, &tmp);
226
227 // n.b.; _RLayoutRecenterHorizontally() is the counterpart to this
228 // with horizontal slices. The comments in the two have been written
229 // independently with somewhat different explanatory styles, so if
230 // the description here was confusing, try reading the other one and
231 // transposing.
232}
233
234
235/**
236 * Given an RArea that doesn't reside in any of the areas in our RLayout,
237 * create a list of maximally-wide RArea slices out of our layout where
238 * it would wind up if we brought it onto the nearest screen edge. This
239 * yields a RAreaList as wide as the slice[es] the window would touch if
240 * we moved it in.
241 *
242 * If we had the move the window vertically (it was off-screen to the top
243 * or bottom), it results in a 1-pixel-wide slice of the top- or
244 * bottom-most self->horiz.
245 *
246 * If we had to move it horizontally (it was off to the left or right),
247 * it winds up being whatever vertical intersection with self->horiz
248 * would result from the window's y and height, with the full width of
249 * the involved slices.
250 *
251 * This is the horizontal-stripe-returning counterpart of
252 * _RLayoutRecenterVertically().
253 *
254 * This is called only by \_RLayoutVerticalIntersect() when given an RArea
255 * that doesn't already intersect the RLayout. Will probably not tell
256 * you something useful if given a far_area that already _does_ intersect
257 * self.
258 *
259 * \param self Our current monitor layout
260 * \param far_area The area to act on
261 */
262static RAreaList *
264{
265 RArea big = RAreaListBigArea(self->monitors), tmp;
266
267 // far_area is outside self, so it's in one of the 3 labelled areas:
268 //
269 // ___T___
270 // | |
271 // H| |H
272 // _|___|_
273 // B
274 //
275 // We create an RArea that's the x and width of big, so it always
276 // covers the entire width of any member of ->horiz. Then we move
277 // the far_area in to the nearest edge to figure the y/height to set.
278
279 if((far_area->y >= big.y && far_area->y <= RAreaY2(&big))
280 || (RAreaY2(far_area) >= big.y && RAreaY2(far_area) <= RAreaY2(&big))) {
281 // In one of the H areas. Already in a valid place vertically,
282 // so make a horizontal strip that position/tall.
283 tmp = RAreaNew(big.x, far_area->y,
284 big.width, far_area->height);
285 }
286 else if(RAreaY2(far_area) < big.y) {
287 // Off the top (T); move it down just far enough that it's bottom
288 // protrudes 1 pixel into the top.
289 tmp = RAreaNew(big.x, big.y - far_area->height + 1,
290 big.width, far_area->height);
291 }
292 else {
293 // Off the bottom (B); move it up just enough that it's top
294 // protrudes 1 pixel into the bottom.
295 tmp = RAreaNew(big.x, RAreaY2(&big),
296 big.width, far_area->height);
297 }
298
299 // And intersect that RArea with self->horiz. This results in a
300 // full-width overlap with 1 pixel at the bottom of the bottom-most,
301 // 1 pixel at the top of the top-most, or 1..(far_area->height)
302 // overlap somewhere. In that last case (far_area was in H), the
303 // intersection may yield multiple areas.
304 return RAreaListIntersect(self->horiz, &tmp);
305
306 // n.b.; _RLayoutRecenterVertically() is the counterpart to this with
307 // vertical slices. The comments in the two have been written
308 // independently with somewhat different explanatory styles, so if
309 // the description here was confusing, try reading the other one and
310 // transposing.
311}
312
313
314
315/************************
316 *
317 * Some wrappers called when we need to Insersect an RArea with our
318 * RLayout, but also handle the case (using the above funcs) when the
319 * RArea doesn't Intersect our layout by finding the nearest border we
320 * could shuffle it over.
321 *
322 ************************/
323
324
325/**
326 * Find which vertical regions of our monitor layout a given RArea (often
327 * a window) is in. If it's completely off the screen, we move it until
328 * it's just over the nearest edge, and return the vertical stripe(s) it
329 * would be in then.
330 *
331 * This function is used only by RLayoutFindTopBottomEdges()
332 */
333static RAreaList *
335{
336 RAreaList *mit = RAreaListIntersect(self->vert, area);
337
338 if(mit->len == 0) {
339 // Not on screen. Move it to just over the nearest edge so it
340 // is, and give the slices it's in then.
343 }
344 return mit;
345}
346
347
348/**
349 * Find which horizontal regions of our monitor layout a given RArea
350 * (often a window) is in. If it's completely off the screen, we move it
351 * until it's just over the nearest edge, and return the horizontal
352 * stripe(s) it would be in then.
353 *
354 * This function is used only by RLayoutFindLeftRightEdges()
355 */
356static RAreaList *
358{
359 RAreaList *mit = RAreaListIntersect(self->horiz, area);
360
361 if(mit->len == 0) {
362 // Not on screen. Move it to just over the nearest edge so it
363 // is, and give the slices it's in then.
366 }
367
368 return mit;
369}
370
371
372
373/************************
374 *
375 * Some funcs using the above (layers of) utils to find info about which
376 * stripes of the RLayout an Area appears in. These are used mostly as
377 * backend utils for figuring various f.*zoom's.
378 *
379 ************************/
380
381
382/**
383 * Figure the position (or nearest practical position) of an area in our
384 * screen layout, and return info about the bottom/top stripes it fits
385 * into.
386 *
387 * Note that the return values (params) are slightly counterintuitive;
388 * top tells you where the top of the lowest stripe that area intersects
389 * with is, and bottom tells you the bottom of the highest.
390 *
391 * This is used as a backend piece of various calculations trying to be
392 * sure something winds up on-screen and when figuring out how to zoom
393 * it.
394 *
395 * \param[in] self The monitor layout to work from
396 * \param[in] area The area to be fit into the monitors
397 * \param[out] top The top of the lowest stripe area fits into.
398 * \param[out] bottom The bottom of the highest stripe area fits into.
399 */
400void
401RLayoutFindTopBottomEdges(const RLayout *self, const RArea *area, int *top,
402 int *bottom)
403{
405
406 if(top != NULL) {
407 *top = RAreaListMaxY(mit);
408 }
409
410 if(bottom != NULL) {
411 *bottom = RAreaListMinY2(mit);
412 }
413
415}
416
417
418/**
419 * Find the bottom of the top stripe of self that area fits into. A
420 * shortcut to get only the second return value of
421 * RLayoutFindTopBottomEdges().
422 */
423int
425{
426 int min_y2;
427 RLayoutFindTopBottomEdges(self, area, NULL, &min_y2);
428 return min_y2;
429}
430
431
432/**
433 * Find the top of the bottom stripe of self that area fits into. A
434 * shortcut to get only the first return value of
435 * RLayoutFindTopBottomEdges().
436 */
437int
439{
440 int max_y;
441 RLayoutFindTopBottomEdges(self, area, &max_y, NULL);
442 return max_y;
443}
444
445
446/**
447 * Figure the position (or nearest practical position) of an area in our
448 * screen layout, and return info about the left/rightmost stripes it fits
449 * into.
450 *
451 * As with RLayoutFindTopBottomEdges(), the return values (params) are
452 * slightly counterintuitive. left tells you where the left-side of the
453 * right-most stripe that area intersects with is, and right tells you
454 * the right side of the left-most.
455 *
456 * This is used as a backend piece of various calculations trying to be
457 * sure something winds up on-screen and when figuring out how to zoom
458 * it.
459 *
460 * \param[in] self The monitor layout to work from
461 * \param[in] area The area to be fit into the monitors
462 * \param[out] left The left edge of the right-most stripe area fits into.
463 * \param[out] right The right edge of the left-most stripe area fits into.
464 */
465void
466RLayoutFindLeftRightEdges(const RLayout *self, const RArea *area, int *left,
467 int *right)
468{
470
471 if(left != NULL) {
472 *left = RAreaListMaxX(mit);
473 }
474
475 if(right != NULL) {
476 *right = RAreaListMinX2(mit);
477 }
478
480}
481
482
483/**
484 * Find the left edge of the right-most stripe of self that area fits
485 * into. A shortcut to get only the first return value of
486 * RLayoutFindLeftRightEdges().
487 */
488int
490{
491 int max_x;
492 RLayoutFindLeftRightEdges(self, area, &max_x, NULL);
493 return max_x;
494}
495
496
497/**
498 * Find the right edge of the left-most stripe of self that area fits
499 * into. A shortcut to get only the second return value of
500 * RLayoutFindLeftRightEdges().
501 */
502int
504{
505 int min_x2;
506 RLayoutFindLeftRightEdges(self, area, NULL, &min_x2);
507 return min_x2;
508}
509
510
511
512/************************
513 *
514 * Lookups to find areas in an RLayout by various means.
515 *
516 ************************/
517
518
519/// Internal structure for callback in RLayoutGetAreaAtXY().
521 const RArea *area;
522 int x, y;
523};
524
525/// Callback util for RLayoutGetAreaAtXY().
526static bool
528{
529 struct monitor_finder_xy *data = (struct monitor_finder_xy *)vdata;
530
531 if(RAreaContainsXY(cur, data->x, data->y)) {
532 data->area = cur;
533 return true;
534 }
535 return false;
536}
537
538/**
539 * Find the RArea in a RLayout that a given coordinate falls into. In
540 * practice, the RArea's in self are the monitors of the desktop, so this
541 * answers "Which monitor is this position on?"
542 */
543RArea
545{
546 struct monitor_finder_xy data = { .area = NULL, .x = x, .y = y };
547
549
550 return data.area == NULL ? self->monitors->areas[0] : *data.area;
551}
552
553
554/**
555 * Return the index'th RArea in an RLayout, or RAreaInvalid() with an out
556 * of range index.
557 */
558RArea
560{
561 if(index >= self->monitors->len || index < 0) {
562 return RAreaInvalid();
563 }
564
565 return self->monitors->areas[index];
566}
567
568
569/**
570 * Return the RArea in self with the name given by the string of length
571 * len at name. This is only used in RLayoutXParseGeometry() to parse a
572 * fragment of a larger string, hence the need for len. It's used to
573 * find the monitor with a given name (RANDR output name).
574 */
575RArea
576RLayoutGetAreaByName(const RLayout *self, const char *name, int len)
577{
578 if(self->names != NULL) {
579 if(len < 0) {
580 len = strlen(name);
581 }
582
583 for(int i = 0; i < self->monitors->len
584 && self->names[i] != NULL; i++) {
585 if(strncmp(self->names[i], name, len) == 0) {
586 return self->monitors->areas[i];
587 }
588 }
589 }
590
591 return RAreaInvalid();
592}
593
594
595
596/************************
597 *
598 * Now some utils for finding various edges of the monitors a given RArea
599 * intersects with.
600 *
601 ************************/
602
603
604/// Internal struct for use in FindMonitor*Edge() callbacks.
606 const RArea *area;
607 union {
608 int max_x;
609 int max_y;
612 } u;
613 bool found;
614};
615
616/// Callback util for RLayoutFindMonitorBottomEdge()
617static bool
619{
621
622 // Does the area we're looking for intersect this piece of the
623 // RLayout, is the bottom of the area shown on it, and is the bottom
624 // of this piece the highest we've yet found that satisfies those
625 // conditions?
626 if(RAreaIsIntersect(cur, data->area)
627 && RAreaY2(cur) > RAreaY2(data->area)
628 && (!data->found || RAreaY2(cur) < data->u.min_y2)) {
629 data->u.min_y2 = RAreaY2(cur);
630 data->found = true;
631 }
632 return false;
633}
634
635/**
636 * Find the bottom edge of the top-most monitor that contains the most of
637 * a given RArea. Generally, the area would be a window.
638 *
639 * That is, we find the monitor whose bottom is the highest up, but that
640 * still shows the bottom edge of the window, and return that monitor's
641 * bottom. If the bottom of the window is off all the monitors, that's
642 * just the highest-ending monitor that contains the window.
643 */
644int
646{
647 struct monitor_edge_finder data = { .area = area };
648
650
651 return data.found ? data.u.min_y2 : RLayoutFindBottomEdge(self, area);
652}
653
654
655/// Callback util for RLayoutFindMonitorTopEdge()
656static bool
658{
660
661 // Does the area we're looking for intersect this piece of the
662 // RLayout, is the top of the area shown on it, and is the top
663 // of this piece the lowest we've yet found that satisfies those
664 // conditions?
665 if(RAreaIsIntersect(cur, data->area)
666 && cur->y < data->area->y
667 && (!data->found || cur->y > data->u.max_y)) {
668 data->u.max_y = cur->y;
669 data->found = true;
670 }
671 return false;
672}
673
674/**
675 * Find the top edge of the bottom-most monitor that contains the most of
676 * a given RArea. Generally, the area would be a window.
677 *
678 * That is, we find the monitor whose top is the lowest down, but that
679 * still shows the top edge of the window, and return that monitor's top.
680 * If the top of the window is off all the monitors, that's just the
681 * lowest-ending monitor that contains part of the window.
682 */
683int
685{
686 struct monitor_edge_finder data = { .area = area };
687
689
690 return data.found ? data.u.max_y : RLayoutFindTopEdge(self, area);
691}
692
693
694/// Callback util for RLayoutFindMonitorLeftEdge()
695static bool
697{
699
700 // Does the area we're looking for intersect this piece of the
701 // RLayout, is the left of the area shown on it, and is the left of
702 // this piece the right-most we've yet found that satisfies those
703 // conditions?
704 if(RAreaIsIntersect(cur, data->area)
705 && cur->x < data->area->x
706 && (!data->found || cur->x > data->u.max_x)) {
707 data->u.max_x = cur->x;
708 data->found = true;
709 }
710 return false;
711}
712
713/**
714 * Find the left edge of the right-most monitor that contains the most of
715 * a given RArea. Generally, the area would be a window.
716 *
717 * That is, we find the monitor whose left is the furthest right, but
718 * that still shows the left edge of the window, and return that
719 * monitor's left. If the left edge of the window is off all the
720 * monitors, that's just the right-most-ending monitor that contains the
721 * window.
722 */
723int
725{
726 struct monitor_edge_finder data = { .area = area };
727
729
730 return data.found ? data.u.max_x : RLayoutFindLeftEdge(self, area);
731}
732
733
734/// Callback util for RLayoutFindMonitorRightEdge()
735static bool
737{
739
740 // Does the area we're looking for intersect this piece of the
741 // RLayout, is the right of the area shown on it, and is the right of
742 // this piece the left-most we've yet found that satisfies those
743 // conditions?
744 if(RAreaIsIntersect(cur, data->area)
745 && RAreaX2(cur) > RAreaX2(data->area)
746 && (!data->found || RAreaX2(cur) < data->u.min_x2)) {
747 data->u.min_x2 = RAreaX2(cur);
748 data->found = true;
749 }
750 return false;
751}
752
753/**
754 * Find the right edge of the left-most monitor that contains the most of
755 * a given RArea. Generally, the area would be a window.
756 *
757 * That is, we find the monitor whose right is the furthest left, but
758 * that still shows the right edge of the window, and return that
759 * monitor's right. If the right edge of the window is off all the
760 * monitors, that's just the left-most-ending monitor that contains the
761 * window.
762 */
763int
765{
766 struct monitor_edge_finder data = { .area = area };
767
769
770 return data.found ? data.u.min_x2 : RLayoutFindRightEdge(self, area);
771}
772
773
774
775/************************
776 *
777 * Backend funcs called by the f.*zoom handlers to figure the area we
778 * should zoom into.
779 *
780 ************************/
781
782
783/**
784 * Figure the best way to stretch an area across the full horizontal
785 * width of an RLayout. This is the backend for the f.xhorizoom ctwm
786 * function, zooming a window to the full width of all monitors.
787 */
788RArea
790{
791 int max_x, min_x2;
792
794
795 return RAreaNew(max_x, area->y, min_x2 - max_x + 1, area->height);
796
797 /**
798 * This yields an area:
799 * ~~~
800 * TL W
801 * *-----*
802 * | |
803 * H| |
804 * | |
805 * *-----*
806 * ~~~
807 *
808 * The precise construction of the area can be tricky.
809 *
810 * In the simplest case, the area is entirely in one horizontal
811 * stripe to start with. In that case, max_x is the left side of
812 * that box, min_x2 is the right side, so the resulting area starts
813 * at (left margin, area y), with the height of y and the width of
814 * the whole stripe. Easy.
815 *
816 * When it spans multiple, it's more convoluted. Let's consider an
817 * example layout (of horizontal stripes, so that top stripe may be
818 * across 2 monitors) to make it a little clearer:
819 *
820 * ~~~
821 * *--------------------------*
822 * | |......2.....|
823 * | | <-----.
824 * | 1 ========= | .
825 * *-------------*-=========--*-* >-- 2 horiz stripes
826 * | ========= | '
827 * | / | <---'
828 * area --+-' |
829 * *--------------*
830 * ~~~
831 *
832 * So in this case, we're trying to stretch area out as far
833 * horizontal as it can go, crossing monitors if possible.
834 *
835 * So, the top-left corner of our box (TL) has the X coordinate of
836 * the right-most strip we started with (the lower), and the Y
837 * coordinate of the top of the area, yielding point (1) above (not
838 * the asterisk; specifically where (1) sits).
839 *
840 * The width W is the difference between the right of the
841 * left-most-ending (in this case, the top) stripe, and the left of
842 * the right-most-starting (the bottom) (plus 1 because math).
843 * That's the width of the intersecting horizontal area (2) above.
844 *
845 * And the height H is just the height of the original area. And so,
846 * our resulting area is the height of that original area (in ='s),
847 * and stretched to the left and right until it runs into one or the
848 * other monitor edge (1 space to the left, 2 to the right, in our
849 * diagram).
850 */
851}
852
853
854/**
855 * Figure the best way to stretch an area across the full vertical height
856 * of an RLayout. This is the backend for the f.xzoom ctwm function,
857 * zooming a window to the full height of all monitors.
858 */
859RArea
861{
862 int max_y, min_y2;
863
865
866 return RAreaNew(area->x, max_y, area->width, min_y2 - max_y + 1);
867
868 // X-ref long comment above in RLayoutFullHoriz() for worked example.
869 // This is just rotated 90 degrees, but the logic works out about the
870 // same.
871}
872
873
874/**
875 * Figure the best way to stretch an area across the largest horizontal
876 * and vertical space it can from its current position. Essentially,
877 * stretch it in all directions until it hits the edge of our available
878 * space.
879 *
880 * This is the backend for the f.xfullzoom function.
881 */
882RArea
884{
886
887 // Get the boxes for full horizontal and vertical zooms, using the
888 // above functions.
891
892 // Now stretch each of those in the other direction...
895
896 // And return whichever was bigger.
897 return RAreaArea(&full1) > RAreaArea(&full2) ? full1 : full2;
898}
899
900
901
902/**
903 * Figure the best way to stretch an area horizontally without crossing
904 * monitors.
905 *
906 * This is the backend for the f.horizoom ctwm function.
907 */
908RArea
910{
911 // Cheat by using RLayoutFull1() to find the RArea for the monitor
912 // it's most on.
914 int max_y, min_y2;
915
916 // We're stretching horizontally, so the x and width of target (that
917 // monitor) are already right. But we have to figure the y and
918 // height...
919
920 // Generally, the y is the window's original y, unless we had to move
921 // it down to get onto the target monitor. XXX Wait, what if we
922 // moved it _up_?
923 max_y = max(area->y, target.y);
924 target.y = max_y;
925
926 // The bottom would be the bottom of the area, clipped to the bottom
927 // of the monitor. So the height is the diff.
929 target.height = min_y2 - max_y + 1;
930
931 return target;
932}
933
934
935/**
936 * Figure the best way to stretch an area vertically without crossing
937 * monitors.
938 *
939 * This is the backend for the f.zoom ctwm function.
940 */
941RArea
943{
944 // Let RLayoutFull1() find the right monitor.
946 int max_x, min_x2;
947
948 // Stretching vertically, so the y/height of the monitor are already
949 // right.
950
951 // x is where the window was, unless we had to move it right to get
952 // onto the monitor. XXX What if we moved it left?
953 max_x = max(area->x, target.x);
954 target.x = max_x;
955
956 // Right side is where it was, unless we have to clip to the monitor.
958 target.width = min_x2 - max_x + 1;
959
960 return target;
961}
962
963
964/**
965 * Figure the best way to resize an area to fill one monitor.
966 *
967 * This is the backend for the f.fullzoom ctwm function.
968 *
969 * \param self Monitor layout
970 * \param area Area (window) to zoom out
971 */
972RArea
974{
977 // Start with a list of all the monitors the window is on now.
978
979 if(mit->len == 0) {
980 // Not on any screens. Find the "nearest" place it would wind
981 // up.
984 }
985
986 // Of the monitors it's on, find the one that it's "most" on, and
987 // return the RArea of it.
990 return target;
991}
992
993
994
995/************************
996 *
997 * Finally, some small misc utils.
998 *
999 ************************/
1000
1001
1002/**
1003 * Generate maximal spanning RArea.
1004 *
1005 * This is a trivial wrapper of RAreaListBigArea() to hide knowledge of
1006 * RLayout internals. Currently only used once; maybe should just be
1007 * deref'd there...
1008 */
1009RArea
1011{
1012 return RAreaListBigArea(self->monitors);
1013}
1014
1015
1016/**
1017 * How many monitors does a given RLayout contain?
1018 */
1019int
1021{
1022 return self->monitors->len;
1023}
1024
1025
1026/**
1027 * Pretty-print an RLayout.
1028 *
1029 * Used for dev/debug.
1030 */
1031void
1033{
1034 fprintf(stderr, "[monitors=");
1035 RAreaListPrint(self->monitors);
1036 fprintf(stderr, "\n horiz=");
1037 RAreaListPrint(self->horiz);
1038 fprintf(stderr, "\n vert=");
1039 RAreaListPrint(self->vert);
1040 fprintf(stderr, "]\n");
1041}
static int PlaceX
Definition add_window.c:82
int y
Definition menus.c:70
int x
Definition menus.c:69
static int len
Definition parse.c:75
char ** names
Definition parse_be.c:2018
RArea RAreaInvalid(void)
Return a facially-invalid RArea.
Definition r_area.c:49
RArea RAreaNew(int x, int y, int width, int height)
Construct an RArea from given components.
Definition r_area.c:19
int RAreaArea(const RArea *self)
Return the area of an RArea.
Definition r_area.c:93
bool RAreaIsIntersect(const RArea *self, const RArea *other)
Do two areas intersect?
Definition r_area.c:127
int RAreaY2(const RArea *self)
Return the bottom edge of an RArea.
Definition r_area.c:83
int RAreaX2(const RArea *self)
Return the right edge of an RArea.
Definition r_area.c:73
bool RAreaContainsXY(const RArea *self, int x, int y)
Is a given coordinate inside a RArea?
Definition r_area.c:159
RArea RAreaListBestTarget(const RAreaList *self, const RArea *area)
Find the RArea in an RAreaList that has the largest intersection with a given RArea.
int RAreaListMinY2(const RAreaList *self)
Find the y coordinate of the bottom edge of the top-most RArea in an RAreaList.
RAreaList * RAreaListVerticalUnion(const RAreaList *self)
Create an RAreaList whose RArea's are the vertical union of our RArea's.
void RAreaListFree(RAreaList *self)
Clean up and free an RAreaList.
RArea RAreaListBigArea(const RAreaList *self)
Create a maximal RArea describing the union of an RAreaList.
int RAreaListMaxY(const RAreaList *self)
Find the y coordinate of the bottom-most RArea in an RAreaList.
void RAreaListPrint(const RAreaList *self)
Pretty-print an RAreaList.
RAreaList * RAreaListIntersect(const RAreaList *self, const RArea *area)
Create an RAreaList of all the areas in an RAreaList that a given RArea intersects with.
int RAreaListMaxX(const RAreaList *self)
Find the x coordinate of the right-most RArea in an RAreaList.
RAreaList * RAreaListHorizontalUnion(const RAreaList *self)
Create an RAreaList whose RArea's are the horizontal union of our RArea's.
void RAreaListForeach(const RAreaList *self, bool(*func)(const RArea *cur_area, void *data), void *data)
Run a function over each RArea in an RAreaList until one returns true, allowing them a place to stash...
RAreaList * RAreaListCopyCropped(const RAreaList *self, int left_margin, int right_margin, int top_margin, int bottom_margin)
Create a copy of an RAreaList with given amounts cropped off the sides.
Definition r_area_list.c:93
int RAreaListMinX2(const RAreaList *self)
Find the x coordinate of the right edge of the left-most RArea in an RAreaList.
int RLayoutNumMonitors(const RLayout *self)
How many monitors does a given RLayout contain?
Definition r_layout.c:1020
void RLayoutFree(RLayout *self)
Clean up and free an RLayout.
Definition r_layout.c:112
RLayout * RLayoutSetMonitorsNames(RLayout *self, char **names)
Set the names for our monitors in an RLayout.
Definition r_layout.c:132
RArea RLayoutFullVert1(const RLayout *self, const RArea *area)
Figure the best way to stretch an area vertically without crossing monitors.
Definition r_layout.c:942
static bool _findMonitorTopEdge(const RArea *cur, void *vdata)
Callback util for RLayoutFindMonitorTopEdge()
Definition r_layout.c:657
static RAreaList * _RLayoutHorizontalIntersect(const RLayout *self, const RArea *area)
Find which horizontal regions of our monitor layout a given RArea (often a window) is in.
Definition r_layout.c:357
int RLayoutFindBottomEdge(const RLayout *self, const RArea *area)
Find the bottom of the top stripe of self that area fits into.
Definition r_layout.c:424
static RAreaList * _RLayoutRecenterHorizontally(const RLayout *self, const RArea *far_area)
Given an RArea that doesn't reside in any of the areas in our RLayout, create a list of maximally-wid...
Definition r_layout.c:263
RArea RLayoutGetAreaByName(const RLayout *self, const char *name, int len)
Return the RArea in self with the name given by the string of length len at name.
Definition r_layout.c:576
RArea RLayoutGetAreaAtXY(const RLayout *self, int x, int y)
Find the RArea in a RLayout that a given coordinate falls into.
Definition r_layout.c:544
void RLayoutFindTopBottomEdges(const RLayout *self, const RArea *area, int *top, int *bottom)
Figure the position (or nearest practical position) of an area in our screen layout,...
Definition r_layout.c:401
void RLayoutPrint(const RLayout *self)
Pretty-print an RLayout.
Definition r_layout.c:1032
int RLayoutFindRightEdge(const RLayout *self, const RArea *area)
Find the right edge of the left-most stripe of self that area fits into.
Definition r_layout.c:503
RArea RLayoutFullHoriz1(const RLayout *self, const RArea *area)
Figure the best way to stretch an area horizontally without crossing monitors.
Definition r_layout.c:909
int RLayoutFindMonitorTopEdge(const RLayout *self, const RArea *area)
Find the top edge of the bottom-most monitor that contains the most of a given RArea.
Definition r_layout.c:684
int RLayoutFindMonitorRightEdge(const RLayout *self, const RArea *area)
Find the right edge of the left-most monitor that contains the most of a given RArea.
Definition r_layout.c:764
RArea RLayoutBigArea(const RLayout *self)
Generate maximal spanning RArea.
Definition r_layout.c:1010
int RLayoutFindLeftEdge(const RLayout *self, const RArea *area)
Find the left edge of the right-most stripe of self that area fits into.
Definition r_layout.c:489
int RLayoutFindMonitorBottomEdge(const RLayout *self, const RArea *area)
Find the bottom edge of the top-most monitor that contains the most of a given RArea.
Definition r_layout.c:645
RArea RLayoutGetAreaIndex(const RLayout *self, int index)
Return the index'th RArea in an RLayout, or RAreaInvalid() with an out of range index.
Definition r_layout.c:559
RLayout * RLayoutNew(RAreaList *monitors)
Create an RLayout for a given set of monitors.
Definition r_layout.c:55
RArea RLayoutFull1(const RLayout *self, const RArea *area)
Figure the best way to resize an area to fill one monitor.
Definition r_layout.c:973
int RLayoutFindTopEdge(const RLayout *self, const RArea *area)
Find the top of the bottom stripe of self that area fits into.
Definition r_layout.c:438
static RAreaList * _RLayoutRecenterVertically(const RLayout *self, const RArea *far_area)
Given an RArea that doesn't reside in any of the areas in our RLayout, create a list of maximally-tal...
Definition r_layout.c:178
static void _RLayoutFreeNames(RLayout *self)
Clean up and free any RLayout.names there might be in an RLayout.
Definition r_layout.c:96
RArea RLayoutFull(const RLayout *self, const RArea *area)
Figure the best way to stretch an area across the largest horizontal and vertical space it can from i...
Definition r_layout.c:883
void RLayoutFindLeftRightEdges(const RLayout *self, const RArea *area, int *left, int *right)
Figure the position (or nearest practical position) of an area in our screen layout,...
Definition r_layout.c:466
static bool _findMonitorRightEdge(const RArea *cur, void *vdata)
Callback util for RLayoutFindMonitorRightEdge()
Definition r_layout.c:736
static bool _findMonitorByXY(const RArea *cur, void *vdata)
Callback util for RLayoutGetAreaAtXY().
Definition r_layout.c:527
RArea RLayoutFullHoriz(const RLayout *self, const RArea *area)
Figure the best way to stretch an area across the full horizontal width of an RLayout.
Definition r_layout.c:789
static bool _findMonitorBottomEdge(const RArea *cur, void *vdata)
Callback util for RLayoutFindMonitorBottomEdge()
Definition r_layout.c:618
static RAreaList * _RLayoutVerticalIntersect(const RLayout *self, const RArea *area)
Find which vertical regions of our monitor layout a given RArea (often a window) is in.
Definition r_layout.c:334
RArea RLayoutFullVert(const RLayout *self, const RArea *area)
Figure the best way to stretch an area across the full vertical height of an RLayout.
Definition r_layout.c:860
RLayout * RLayoutCopyCropped(const RLayout *self, int left_margin, int right_margin, int top_margin, int bottom_margin)
Create a copy of an RLayout with given amounts cropped off the sides.
Definition r_layout.c:78
int RLayoutFindMonitorLeftEdge(const RLayout *self, const RArea *area)
Find the left edge of the right-most monitor that contains the most of a given RArea.
Definition r_layout.c:724
static bool _findMonitorLeftEdge(const RArea *cur, void *vdata)
Callback util for RLayoutFindMonitorLeftEdge()
Definition r_layout.c:696
A set of RArea's.
Definition r_structs.h:30
A particular extent of space.
Definition r_structs.h:16
int y
Y position.
Definition r_structs.h:18
int width
X dimension.
Definition r_structs.h:19
int height
Y dimension.
Definition r_structs.h:20
int x
X position.
Definition r_structs.h:17
The layout of our display.
Definition r_structs.h:45
Internal struct for use in FindMonitor*Edge() callbacks.
Definition r_layout.c:605
const RArea * area
Definition r_layout.c:606
union monitor_edge_finder::@2 u
Internal structure for callback in RLayoutGetAreaAtXY().
Definition r_layout.c:520
const RArea * area
Definition r_layout.c:521
static int min(int a, int b)
Definition util.h:30
static int max(int a, int b)
Definition util.h:25