/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* Simple box operations */ /* * Copyright (C) 2005, 2006 Elijah Newren * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #ifndef META_BOXES_H #define META_BOXES_H #include #include "common.h" typedef struct _MetaRectangle MetaRectangle; struct _MetaRectangle { int x; int y; int width; int height; }; typedef struct _MetaStrut MetaStrut; struct _MetaStrut { MetaRectangle rect; MetaDirection side; }; #define BOX_LEFT(box) ((box).x) /* Leftmost pixel of rect */ #define BOX_RIGHT(box) ((box).x + (box).width) /* One pixel past right */ #define BOX_TOP(box) ((box).y) /* Topmost pixel of rect */ #define BOX_BOTTOM(box) ((box).y + (box).height) /* One pixel past bottom */ typedef enum { FIXED_DIRECTION_NONE = 0, FIXED_DIRECTION_X = 1 << 0, FIXED_DIRECTION_Y = 1 << 1, } FixedDirections; typedef enum { META_EDGE_WINDOW, META_EDGE_XINERAMA, META_EDGE_SCREEN } MetaEdgeType; typedef struct _MetaEdge MetaEdge; struct _MetaEdge { MetaRectangle rect; /* width or height should be 1 */ MetaDirection side_type; /* should only have 1 of the 4 directions set */ MetaEdgeType edge_type; }; /* Output functions -- note that the output buffer had better be big enough: * rect_to_string: RECT_LENGTH * region_to_string: (RECT_LENGTH+strlen(separator_string)) * * g_list_length (region) * edge_to_string: EDGE_LENGTH * edge_list_to_...: (EDGE_LENGTH+strlen(separator_string)) * * g_list_length (edge_list) */ #define RECT_LENGTH 27 #define EDGE_LENGTH 37 char* meta_rectangle_to_string (const MetaRectangle *rect, char *output); char* meta_rectangle_region_to_string (GList *region, const char *separator_string, char *output); char* meta_rectangle_edge_to_string (const MetaEdge *edge, char *output); char* meta_rectangle_edge_list_to_string ( GList *edge_list, const char *separator_string, char *output); /* Function to make initializing a rect with a single line of code easy */ MetaRectangle meta_rect (int x, int y, int width, int height); /* Basic comparison functions */ int meta_rectangle_area (const MetaRectangle *rect); gboolean meta_rectangle_intersect (const MetaRectangle *src1, const MetaRectangle *src2, MetaRectangle *dest); gboolean meta_rectangle_equal (const MetaRectangle *src1, const MetaRectangle *src2); /* overlap is similar to intersect but doesn't provide location of * intersection information. */ gboolean meta_rectangle_overlap (const MetaRectangle *rect1, const MetaRectangle *rect2); /* vert_overlap means ignore the horizontal location and ask if the * vertical parts overlap. An alternate way to think of it is "Does there * exist a way to shift either rect horizontally so that the two rects * overlap?" horiz_overlap is similar. */ gboolean meta_rectangle_vert_overlap (const MetaRectangle *rect1, const MetaRectangle *rect2); gboolean meta_rectangle_horiz_overlap (const MetaRectangle *rect1, const MetaRectangle *rect2); /* could_fit_rect determines whether "outer_rect" is big enough to contain * inner_rect. contains_rect checks whether it actually contains it. */ gboolean meta_rectangle_could_fit_rect (const MetaRectangle *outer_rect, const MetaRectangle *inner_rect); gboolean meta_rectangle_contains_rect (const MetaRectangle *outer_rect, const MetaRectangle *inner_rect); /* Resize old_rect to the given new_width and new_height, but store the * result in rect. NOTE THAT THIS IS RESIZE ONLY SO IT CANNOT BE USED FOR * A MOVERESIZE OPERATION (that simplies the routine a little bit as it * means there's no difference between NorthWestGravity and StaticGravity. * Also, I lied a little bit--technically, you could use it in a MoveResize * operation if you muck with old_rect just right). */ void meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect, MetaRectangle *rect, int gravity, int new_width, int new_height); /* find a list of rectangles with the property that a window is contained * in the given region if and only if it is contained in one of the * rectangles in the list. * * In this case, the region is given by taking basic_rect, removing from * it the intersections with all the rectangles in the all_struts list, * then expanding all the rectangles in the resulting list by the given * amounts on each side. * * See boxes.c for more details. */ GList* meta_rectangle_get_minimal_spanning_set_for_region ( const MetaRectangle *basic_rect, const GSList *all_struts); /* Expand all rectangles in region by the given amount on each side */ GList* meta_rectangle_expand_region (GList *region, const int left_expand, const int right_expand, const int top_expand, const int bottom_expand); /* Same as for meta_rectangle_expand_region except that rectangles not at * least min_x or min_y in size are not expanded in that direction */ GList* meta_rectangle_expand_region_conditionally ( GList *region, const int left_expand, const int right_expand, const int top_expand, const int bottom_expand, const int min_x, const int min_y); /* Expand rect in direction to the size of expand_to, and then clip out any * overlapping struts oriented orthognal to the expansion direction. (Think * horizontal or vertical maximization) */ void meta_rectangle_expand_to_avoiding_struts ( MetaRectangle *rect, const MetaRectangle *expand_to, const MetaDirection direction, const GSList *all_struts); /* Free the list created by * meta_rectangle_get_minimal_spanning_set_for_region() * or * meta_rectangle_find_onscreen_edges () * or * meta_rectangle_find_nonintersected_xinerama_edges() */ void meta_rectangle_free_list_and_elements (GList *filled_list); /* could_fit_in_region determines whether one of the spanning_rects is * big enough to contain rect. contained_in_region checks whether one * actually contains it. */ gboolean meta_rectangle_could_fit_in_region ( const GList *spanning_rects, const MetaRectangle *rect); gboolean meta_rectangle_contained_in_region ( const GList *spanning_rects, const MetaRectangle *rect); gboolean meta_rectangle_overlaps_with_region ( const GList *spanning_rects, const MetaRectangle *rect); /* Make the rectangle small enough to fit into one of the spanning_rects, * but make it no smaller than min_size. */ void meta_rectangle_clamp_to_fit_into_region ( const GList *spanning_rects, FixedDirections fixed_directions, MetaRectangle *rect, const MetaRectangle *min_size); /* Clip the rectangle so that it fits into one of the spanning_rects, assuming * it overlaps with at least one of them */ void meta_rectangle_clip_to_region (const GList *spanning_rects, FixedDirections fixed_directions, MetaRectangle *rect); /* Shove the rectangle into one of the spanning_rects, assuming it fits in * one of them. */ void meta_rectangle_shove_into_region( const GList *spanning_rects, FixedDirections fixed_directions, MetaRectangle *rect); /* Finds the point on the line connecting (x1,y1) to (x2,y2) which is closest * to (px, py). Useful for finding an optimal rectangle size when given a * range between two sizes that are all candidates. */ void meta_rectangle_find_linepoint_closest_to_point (double x1, double y1, double x2, double y2, double px, double py, double *valx, double *valy); /***************************************************************************/ /* */ /* Switching gears to code for edges instead of just rectangles */ /* */ /***************************************************************************/ /* Return whether an edge overlaps or is adjacent to the rectangle in the * nonzero-width dimension of the edge. */ gboolean meta_rectangle_edge_aligns (const MetaRectangle *rect, const MetaEdge *edge); /* Compare two edges, so that sorting functions can put a list of edges in * canonical order. */ gint meta_rectangle_edge_cmp (gconstpointer a, gconstpointer b); /* Compare two edges, so that sorting functions can put a list of edges in * order. This function doesn't separate left edges first, then right edges, * etc., but rather compares only upon location. */ gint meta_rectangle_edge_cmp_ignore_type (gconstpointer a, gconstpointer b); /* Removes an parts of edges in the given list that intersect any box in the * given rectangle list. Returns the result. */ GList* meta_rectangle_remove_intersections_with_boxes_from_edges ( GList *edges, const GSList *rectangles); /* Finds all the edges of an onscreen region, returning a GList* of * MetaEdgeRect's. */ GList* meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect, const GSList *all_struts); /* Finds edges between adjacent xineramas which are not covered by the given * struts. */ GList* meta_rectangle_find_nonintersected_xinerama_edges ( const GList *xinerama_rects, const GSList *all_struts); #endif /* META_BOXES_H */