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