08f51fdf94
2007-04-02 Elijah Newren <newren gmail com> Patch from Carlo Wood to fix handling of unidirectional maximization and partial struts. #358311. * src/constraints.c (constrain_maximization): determine target size for unidirectionally maximized windows by determining how far they can be maximized without hitting orthogonal struts. Avoids weird "empty spaces". * src/boxes.[ch] (meta_rectangle_expand_to_avoiding_struts): new function 2007-04-02 Elijah Newren <newren gmail com> Make the strut lists (stored in workspaces) record both the rectangle and the side that the strut is on. Lots of code cleanups relating to struts. * src/boxes.h (struct MetaStrut): new struct for struts * src/window.[ch] (struct MetaStruts, struct MetaWindow, meta_window_update_struts): overhaul to make window's struts remember their side as well as their rectangular location, and just use a list instead of several copies of near-identical code for left/right/top/bottom (allowing us to nuke MetaStruts struct as well) * src/testboxes.c (new_meta_strut, get_strut_list): * src/workspace.c (ensure_work_areas_validated): * src/boxes.c (meta_rectangle_get_minimal_spanning_set_for_region, meta_rectangle_expand_to_avoiding_struts, get_disjoint_strut_rect_list_in_region, fix_up_edges, meta_rectangle_find_onscreen_edges, meta_rectangle_find_nonintersected_xinerama_edges): modify to handle struts being rectangle + side instead of just rectangle * src/workspace.c (ensure_work_areas_validated): simplify strut list creation considerably given MetaWindow change, modify work_area computations to take advantage of region computations being done (makes the code shorter as well as more robust against pathological cases). * src/util.[ch] (meta_free_gslist_and_elements): new convenience function * src/common.h (enum MetaDirection): * src/edge-resistance.c (movement_towards_edge): * src/boxes.c (meta_rectangle_edge_aligns, rectangle_and_edge_intersection, split_edge): Add more MetaDirection fields for convenience * src/boxes.h (enum FixedDirections): * src/constraints.c (setup_constraint_info, place_window_if_needed): add a FIXED_DIRECTION_NONE to the FixedDirections enum to make code more clear svn path=/trunk/; revision=3144
286 lines
12 KiB
C
286 lines
12 KiB
C
/* -*- 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 <glib.h>
|
|
#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 */
|