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