1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 
3 /* Simple box operations */
4 
5 /*
6  * Copyright (C) 2005, 2006 Elijah Newren
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301, USA.
22  */
23 
24 #ifndef META_BOXES_H
25 #define META_BOXES_H
26 
27 #include <glib.h>
28 #include "common.h"
29 
30 typedef enum
31 {
32   META_EDGE_WINDOW,
33   META_EDGE_XINERAMA,
34   META_EDGE_SCREEN
35 } MetaEdgeType;
36 
37 typedef struct _MetaRectangle MetaRectangle;
38 struct _MetaRectangle
39 {
40   int x;
41   int y;
42   int width;
43   int height;
44 };
45 
46 typedef struct _MetaStrut MetaStrut;
47 struct _MetaStrut
48 {
49   MetaRectangle rect;
50   MetaSide side;
51   MetaEdgeType edge;
52 };
53 
54 #define BOX_LEFT(box)    ((box).x)                /* Leftmost pixel of rect */
55 #define BOX_RIGHT(box)   ((box).x + (box).width)  /* One pixel past right   */
56 #define BOX_TOP(box)     ((box).y)                /* Topmost pixel of rect  */
57 #define BOX_BOTTOM(box)  ((box).y + (box).height) /* One pixel past bottom  */
58 
59 typedef enum
60 {
61   FIXED_DIRECTION_NONE = 0,
62   FIXED_DIRECTION_X    = 1 << 0,
63   FIXED_DIRECTION_Y    = 1 << 1,
64 } FixedDirections;
65 
66 typedef struct _MetaEdge MetaEdge;
67 struct _MetaEdge
68 {
69   MetaRectangle rect;      /* width or height should be 1 */
70   MetaSide side_type;
71   MetaEdgeType  edge_type;
72 };
73 
74 /* Output functions -- note that the output buffer had better be big enough:
75  *   rect_to_string:   RECT_LENGTH
76  *   region_to_string: (RECT_LENGTH+strlen(separator_string)) *
77  *                     g_list_length (region)
78  *   edge_to_string:   EDGE_LENGTH
79  *   edge_list_to_...: (EDGE_LENGTH+strlen(separator_string)) *
80  *                     g_list_length (edge_list)
81  */
82 #define RECT_LENGTH 27
83 #define EDGE_LENGTH 37
84 char* meta_rectangle_to_string        (const MetaRectangle *rect,
85                                        char                *output);
86 char* meta_rectangle_region_to_string (GList               *region,
87                                        const char          *separator_string,
88                                        char                *output);
89 char* meta_rectangle_edge_to_string   (const MetaEdge      *edge,
90                                        char                *output);
91 char* meta_rectangle_edge_list_to_string (
92                                        GList               *edge_list,
93                                        const char          *separator_string,
94                                        char                *output);
95 
96 /* Function to make initializing a rect with a single line of code easy */
97 MetaRectangle                 meta_rect (int x, int y, int width, int height);
98 
99 /* Basic comparison functions */
100 int      meta_rectangle_area            (const MetaRectangle *rect);
101 gboolean meta_rectangle_intersect       (const MetaRectangle *src1,
102                                          const MetaRectangle *src2,
103                                          MetaRectangle       *dest);
104 gboolean meta_rectangle_equal           (const MetaRectangle *src1,
105                                          const MetaRectangle *src2);
106 
107 /* Find the bounding box of the union of two rectangles */
108 void     meta_rectangle_union           (const MetaRectangle *rect1,
109                                          const MetaRectangle *rect2,
110                                          MetaRectangle       *dest);
111 
112 /* overlap is similar to intersect but doesn't provide location of
113  * intersection information.
114  */
115 gboolean meta_rectangle_overlap         (const MetaRectangle *rect1,
116                                          const MetaRectangle *rect2);
117 
118 /* vert_overlap means ignore the horizontal location and ask if the
119  * vertical parts overlap.  An alternate way to think of it is "Does there
120  * exist a way to shift either rect horizontally so that the two rects
121  * overlap?"  horiz_overlap is similar.
122  */
123 gboolean meta_rectangle_vert_overlap    (const MetaRectangle *rect1,
124                                          const MetaRectangle *rect2);
125 gboolean meta_rectangle_horiz_overlap   (const MetaRectangle *rect1,
126                                          const MetaRectangle *rect2);
127 
128 /* could_fit_rect determines whether "outer_rect" is big enough to contain
129  * inner_rect.  contains_rect checks whether it actually contains it.
130  */
131 gboolean meta_rectangle_could_fit_rect  (const MetaRectangle *outer_rect,
132                                          const MetaRectangle *inner_rect);
133 gboolean meta_rectangle_contains_rect   (const MetaRectangle *outer_rect,
134                                          const MetaRectangle *inner_rect);
135 
136 /* Resize old_rect to the given new_width and new_height, but store the
137  * result in rect.  NOTE THAT THIS IS RESIZE ONLY SO IT CANNOT BE USED FOR
138  * A MOVERESIZE OPERATION (that simplies the routine a little bit as it
139  * means there's no difference between NorthWestGravity and StaticGravity.
140  * Also, I lied a little bit--technically, you could use it in a MoveResize
141  * operation if you muck with old_rect just right).
142  */
143 void meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect,
144                                          MetaRectangle       *rect,
145                                          int                  gravity,
146                                          int                  new_width,
147                                          int                  new_height);
148 
149 /* find a list of rectangles with the property that a window is contained
150  * in the given region if and only if it is contained in one of the
151  * rectangles in the list.
152  *
153  * In this case, the region is given by taking basic_rect, removing from
154  * it the intersections with all the rectangles in the all_struts list,
155  * then expanding all the rectangles in the resulting list by the given
156  * amounts on each side.
157  *
158  * See boxes.c for more details.
159  */
160 GList*   meta_rectangle_get_minimal_spanning_set_for_region (
161                                          const MetaRectangle *basic_rect,
162                                          const GSList        *all_struts,
163                                          gboolean             skip_middle_struts);
164 
165 /* Expand all rectangles in region by the given amount on each side */
166 GList*   meta_rectangle_expand_region   (GList               *region,
167                                          const int            left_expand,
168                                          const int            right_expand,
169                                          const int            top_expand,
170                                          const int            bottom_expand);
171 /* Same as for meta_rectangle_expand_region except that rectangles not at
172  * least min_x or min_y in size are not expanded in that direction
173  */
174 GList*   meta_rectangle_expand_region_conditionally (
175                                          GList                *region,
176                                          const int            left_expand,
177                                          const int            right_expand,
178                                          const int            top_expand,
179                                          const int            bottom_expand,
180                                          const int            min_x,
181                                          const int            min_y);
182 
183 /* Expand rect in direction to the size of expand_to, and then clip out any
184  * overlapping struts oriented orthognal to the expansion direction.  (Think
185  * horizontal or vertical maximization)
186  */
187 void     meta_rectangle_expand_to_avoiding_struts (
188                                          MetaRectangle       *rect,
189                                          const MetaRectangle *expand_to,
190                                          const MetaDirection  direction,
191                                          const GSList        *all_struts);
192 
193 /* could_fit_in_region determines whether one of the spanning_rects is
194  * big enough to contain rect.  contained_in_region checks whether one
195  * actually contains it.
196  */
197 gboolean meta_rectangle_could_fit_in_region (
198                                          const GList         *spanning_rects,
199                                          const MetaRectangle *rect);
200 gboolean meta_rectangle_contained_in_region (
201                                          const GList         *spanning_rects,
202                                          const MetaRectangle *rect);
203 gboolean meta_rectangle_overlaps_with_region (
204                                          const GList         *spanning_rects,
205                                          const MetaRectangle *rect);
206 
207 /* Make the rectangle small enough to fit into one of the spanning_rects,
208  * but make it no smaller than min_size.
209  */
210 void     meta_rectangle_clamp_to_fit_into_region (
211                                          const GList         *spanning_rects,
212                                          FixedDirections      fixed_directions,
213                                          MetaRectangle       *rect,
214                                          const MetaRectangle *min_size);
215 
216 /* Clip the rectangle so that it fits into one of the spanning_rects, assuming
217  * it overlaps with at least one of them
218  */
219 void     meta_rectangle_clip_to_region  (const GList         *spanning_rects,
220                                          FixedDirections      fixed_directions,
221                                          MetaRectangle       *rect);
222 
223 /* Shove the rectangle into one of the spanning_rects, assuming it fits in
224  * one of them.
225  */
226 void     meta_rectangle_shove_into_region(
227                                          const GList         *spanning_rects,
228                                          FixedDirections      fixed_directions,
229                                          MetaRectangle       *rect);
230 
231 /* Finds the point on the line connecting (x1,y1) to (x2,y2) which is closest
232  * to (px, py).  Useful for finding an optimal rectangle size when given a
233  * range between two sizes that are all candidates.
234  */
235 void meta_rectangle_find_linepoint_closest_to_point (double x1,    double y1,
236                                                      double x2,    double y2,
237                                                      double px,    double py,
238                                                      double *valx, double *valy);
239 
240 /***************************************************************************/
241 /*                                                                         */
242 /* Switching gears to code for edges instead of just rectangles            */
243 /*                                                                         */
244 /***************************************************************************/
245 
246 /* Return whether an edge overlaps or is adjacent to the rectangle in the
247  * nonzero-width dimension of the edge.
248  */
249 gboolean meta_rectangle_edge_aligns (const MetaRectangle *rect,
250                                      const MetaEdge      *edge);
251 
252 /* Compare two edges, so that sorting functions can put a list of edges in
253  * canonical order.
254  */
255 gint   meta_rectangle_edge_cmp (gconstpointer a, gconstpointer b);
256 
257 /* Compare two edges, so that sorting functions can put a list of edges in
258  * order.  This function doesn't separate left edges first, then right edges,
259  * etc., but rather compares only upon location.
260  */
261 gint   meta_rectangle_edge_cmp_ignore_type (gconstpointer a, gconstpointer b);
262 
263 /* Removes an parts of edges in the given list that intersect any box in the
264  * given rectangle list.  Returns the result.
265  */
266 GList* meta_rectangle_remove_intersections_with_boxes_from_edges (
267                                            GList *edges,
268                                            const GSList *rectangles);
269 
270 /* Finds all the edges of an onscreen region, returning a GList* of
271  * MetaEdgeRect's.
272  */
273 GList* meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
274                                            const GSList        *all_struts);
275 
276 /* Finds edges between adjacent xineramas which are not covered by the given
277  * struts.
278  */
279 GList* meta_rectangle_find_nonintersected_xinerama_edges (
280                                            const MetaRectangle *screen_rect,
281 					   const GList         *xinerama_rects,
282                                            const GSList        *all_struts);
283 
284 #endif /* META_BOXES_H */
285