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, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #ifndef META_BOXES_PRIVATE_H
23 #define META_BOXES_PRIVATE_H
24 
25 #include <glib-object.h>
26 
27 #include "backends/meta-backend-types.h"
28 #include "core/util-private.h"
29 #include "meta/boxes.h"
30 #include "meta/common.h"
31 
32 #define BOX_LEFT(box)    ((box).x)                /* Leftmost pixel of rect */
33 #define BOX_RIGHT(box)   ((box).x + (box).width)  /* One pixel past right   */
34 #define BOX_TOP(box)     ((box).y)                /* Topmost pixel of rect  */
35 #define BOX_BOTTOM(box)  ((box).y + (box).height) /* One pixel past bottom  */
36 
37 typedef enum
38 {
39   FIXED_DIRECTION_NONE = 0,
40   FIXED_DIRECTION_X    = 1 << 0,
41   FIXED_DIRECTION_Y    = 1 << 1,
42 } FixedDirections;
43 
44 typedef enum _MetaRoundingStrategy
45 {
46   META_ROUNDING_STRATEGY_SHRINK,
47   META_ROUNDING_STRATEGY_GROW,
48   META_ROUNDING_STRATEGY_ROUND,
49 } MetaRoundingStrategy;
50 
51 /* Output functions -- note that the output buffer had better be big enough:
52  *   rect_to_string:   RECT_LENGTH
53  *   region_to_string: (RECT_LENGTH+strlen(separator_string)) *
54  *                     g_list_length (region)
55  *   edge_to_string:   EDGE_LENGTH
56  *   edge_list_to_...: (EDGE_LENGTH+strlen(separator_string)) *
57  *                     g_list_length (edge_list)
58  */
59 #define RECT_LENGTH 27
60 #define EDGE_LENGTH 37
61 char* meta_rectangle_to_string        (const MetaRectangle *rect,
62                                        char                *output);
63 char* meta_rectangle_region_to_string (GList               *region,
64                                        const char          *separator_string,
65                                        char                *output);
66 char* meta_rectangle_edge_to_string   (const MetaEdge      *edge,
67                                        char                *output);
68 char* meta_rectangle_edge_list_to_string (
69                                        GList               *edge_list,
70                                        const char          *separator_string,
71                                        char                *output);
72 
73 /* Resize old_rect to the given new_width and new_height, but store the
74  * result in rect.  NOTE THAT THIS IS RESIZE ONLY SO IT CANNOT BE USED FOR
75  * A MOVERESIZE OPERATION (that simplifies the routine a little bit as it
76  * means there's no difference between META_GRAVITY_NORTH_WEST and
77  * META_GRAVITY_STATIC. Also, I lied a little bit--technically, you could use
78  * it in a MoveResize operation if you muck with old_rect just right).
79  */
80 META_EXPORT_TEST
81 void meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect,
82                                          MetaRectangle       *rect,
83                                          MetaGravity          gravity,
84                                          int                  new_width,
85                                          int                  new_height);
86 
87 /* find a list of rectangles with the property that a window is contained
88  * in the given region if and only if it is contained in one of the
89  * rectangles in the list.
90  *
91  * In this case, the region is given by taking basic_rect, removing from
92  * it the intersections with all the rectangles in the all_struts list,
93  * then expanding all the rectangles in the resulting list by the given
94  * amounts on each side.
95  *
96  * See boxes.c for more details.
97  */
98 META_EXPORT_TEST
99 GList*   meta_rectangle_get_minimal_spanning_set_for_region (
100                                          const MetaRectangle *basic_rect,
101                                          const GSList        *all_struts);
102 
103 /* Expand all rectangles in region by the given amount on each side */
104 GList*   meta_rectangle_expand_region   (GList               *region,
105                                          const int            left_expand,
106                                          const int            right_expand,
107                                          const int            top_expand,
108                                          const int            bottom_expand);
109 /* Same as for meta_rectangle_expand_region except that rectangles not at
110  * least min_x or min_y in size are not expanded in that direction
111  */
112 GList*   meta_rectangle_expand_region_conditionally (
113                                          GList                *region,
114                                          const int            left_expand,
115                                          const int            right_expand,
116                                          const int            top_expand,
117                                          const int            bottom_expand,
118                                          const int            min_x,
119                                          const int            min_y);
120 
121 /* Expand rect in direction to the size of expand_to, and then clip out any
122  * overlapping struts oriented orthogonal to the expansion direction.  (Think
123  * horizontal or vertical maximization)
124  */
125 META_EXPORT_TEST
126 void     meta_rectangle_expand_to_avoiding_struts (
127                                          MetaRectangle       *rect,
128                                          const MetaRectangle *expand_to,
129                                          const MetaDirection  direction,
130                                          const GSList        *all_struts);
131 
132 /* Free the list created by
133  *   meta_rectangle_get_minimal_spanning_set_for_region()
134  * or
135  *   meta_rectangle_find_onscreen_edges ()
136  * or
137  *   meta_rectangle_find_nonintersected_monitor_edges()
138  */
139 META_EXPORT_TEST
140 void     meta_rectangle_free_list_and_elements (GList *filled_list);
141 
142 /* could_fit_in_region determines whether one of the spanning_rects is
143  * big enough to contain rect.  contained_in_region checks whether one
144  * actually contains it.
145  */
146 META_EXPORT_TEST
147 gboolean meta_rectangle_could_fit_in_region (
148                                          const GList         *spanning_rects,
149                                          const MetaRectangle *rect);
150 
151 META_EXPORT_TEST
152 gboolean meta_rectangle_contained_in_region (
153                                          const GList         *spanning_rects,
154                                          const MetaRectangle *rect);
155 
156 META_EXPORT_TEST
157 gboolean meta_rectangle_overlaps_with_region (
158                                          const GList         *spanning_rects,
159                                          const MetaRectangle *rect);
160 
161 gboolean meta_rectangle_is_adjacent_to_any_in_region (
162                                          const GList   *spanning_rects,
163                                          MetaRectangle *rect);
164 
165 /* Make the rectangle small enough to fit into one of the spanning_rects,
166  * but make it no smaller than min_size.
167  */
168 META_EXPORT_TEST
169 void     meta_rectangle_clamp_to_fit_into_region (
170                                          const GList         *spanning_rects,
171                                          FixedDirections      fixed_directions,
172                                          MetaRectangle       *rect,
173                                          const MetaRectangle *min_size);
174 
175 /* Clip the rectangle so that it fits into one of the spanning_rects, assuming
176  * it overlaps with at least one of them
177  */
178 META_EXPORT_TEST
179 void     meta_rectangle_clip_to_region  (const GList         *spanning_rects,
180                                          FixedDirections      fixed_directions,
181                                          MetaRectangle       *rect);
182 
183 /* Shove the rectangle into one of the spanning_rects, assuming it fits in
184  * one of them.
185  */
186 META_EXPORT_TEST
187 void     meta_rectangle_shove_into_region(
188                                          const GList         *spanning_rects,
189                                          FixedDirections      fixed_directions,
190                                          MetaRectangle       *rect);
191 
192 /* Finds the point on the line connecting (x1,y1) to (x2,y2) which is closest
193  * to (px, py).  Useful for finding an optimal rectangle size when given a
194  * range between two sizes that are all candidates.
195  */
196 META_EXPORT_TEST
197 void meta_rectangle_find_linepoint_closest_to_point (double x1,    double y1,
198                                                      double x2,    double y2,
199                                                      double px,    double py,
200                                                      double *valx, double *valy);
201 
202 /***************************************************************************/
203 /*                                                                         */
204 /* Switching gears to code for edges instead of just rectangles            */
205 /*                                                                         */
206 /***************************************************************************/
207 
208 /* Return whether an edge overlaps or is adjacent to the rectangle in the
209  * nonzero-width dimension of the edge.
210  */
211 META_EXPORT_TEST
212 gboolean meta_rectangle_edge_aligns (const MetaRectangle *rect,
213                                      const MetaEdge      *edge);
214 
215 /* Compare two edges, so that sorting functions can put a list of edges in
216  * canonical order.
217  */
218 META_EXPORT_TEST
219 gint   meta_rectangle_edge_cmp (gconstpointer a, gconstpointer b);
220 
221 /* Compare two edges, so that sorting functions can put a list of edges in
222  * order.  This function doesn't separate left edges first, then right edges,
223  * etc., but rather compares only upon location.
224  */
225 META_EXPORT_TEST
226 gint   meta_rectangle_edge_cmp_ignore_type (gconstpointer a, gconstpointer b);
227 
228 /* Removes an parts of edges in the given list that intersect any box in the
229  * given rectangle list.  Returns the result.
230  */
231 GList* meta_rectangle_remove_intersections_with_boxes_from_edges (
232                                            GList *edges,
233                                            const GSList *rectangles);
234 
235 /* Finds all the edges of an onscreen region, returning a GList* of
236  * MetaEdgeRect's.
237  */
238 META_EXPORT_TEST
239 GList* meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
240                                            const GSList        *all_struts);
241 
242 /* Finds edges between adjacent monitors which are not covered by the given
243  * struts.
244  */
245 META_EXPORT_TEST
246 GList* meta_rectangle_find_nonintersected_monitor_edges (
247                                            const GList         *monitor_rects,
248                                            const GSList        *all_struts);
249 
250 META_EXPORT_TEST
251 gboolean meta_rectangle_is_adjacent_to (MetaRectangle *rect,
252                                         MetaRectangle *other);
253 
254 META_EXPORT_TEST
255 void meta_rectangle_scale_double (const MetaRectangle  *rect,
256                                   double                scale,
257                                   MetaRoundingStrategy  rounding_strategy,
258                                   MetaRectangle        *dest);
259 
260 static inline graphene_rect_t
meta_rectangle_to_graphene_rect(MetaRectangle * rect)261 meta_rectangle_to_graphene_rect (MetaRectangle *rect)
262 {
263   return (graphene_rect_t) {
264     .origin = {
265       .x = rect->x,
266       .y = rect->y
267     },
268     .size = {
269       .width = rect->width,
270       .height = rect->height
271     }
272   };
273 }
274 
275 META_EXPORT_TEST
276 void meta_rectangle_transform (const MetaRectangle  *rect,
277                                MetaMonitorTransform  transform,
278                                int                   width,
279                                int                   height,
280                                MetaRectangle        *dest);
281 
282 void meta_rectangle_from_graphene_rect (const graphene_rect_t *rect,
283                                         MetaRoundingStrategy   rounding_strategy,
284                                         MetaRectangle         *dest);
285 
286 void meta_rectangle_crop_and_scale (const MetaRectangle *rect,
287                                     graphene_rect_t     *src_rect,
288                                     int                  dst_width,
289                                     int                  dst_height,
290                                     MetaRectangle       *dest);
291 
292 #endif /* META_BOXES_PRIVATE_H */
293