Merge of all the changes on the constraints_experiments branch. This is

2005-11-18  Elijah Newren  <newren@gmail.com>

	Merge of all the changes on the constraints_experiments branch.
	This is just a summary, to get the full ChangeLog of those
	changes (approx. 2000 lines):
	  cvs -q -z3 update -Pd -r constraints_experiments
	  cvs -q -z3 diff -pu -r CONSTRAINTS_EXPERIMENTS_BRANCHPOINT ChangeLog

	Bugs fixed:
	  unfiled - constraints.c is overly complicated[1]
	  unfiled - constraints.c is not robust when all constraints
	            cannot simultaneously be met (constraints need to be
	            prioritized)
	  unfiled - keep-titlebar-onscreen constraint is decoration
	            unaware (since get_outermost_onscreen_positions()
	            forgets to include decorations)
	  unfiled - keyboard snap-moving and snap-resizing snap to hidden
	            edges
	   109553 - gravity w/ simultaneous move & resize doesn't work
	   113601 - maximize vertical and horizontal should toggle and be
	            constrained
	   122196 - windows show up under vertical panels
	   122670 - jerky/random resizing of window via keyboard[2]
	   124582 - keyboard and mouse snap-resizing and snap-moving
	            erroneously moves the window multidimensionally
	   136307 - don't allow apps to resize themselves off the screen
	            (*cough* filechooser *cough*)
	   142016, 143784 - windows should not span multiple xineramas
	            unless placed there by the user
	   143145 - clamp new windows to screensize and force them
	            onscreen, if they'll fit
	   144126 - Handle pathological strut lists sanely[3]
	   149867 - fixed aspect ratio windows are difficult to resize[4]
	   152898 - make screen edges consistent; allow easy slamming of
	            windows into the left, right, and bottom edges of the
	            screen too.
	   154706 - bouncing weirdness at screen edge with keyboard moving
	            or resizing
	   156699 - avoid struts when placing windows, if possible (nasty
	            a11y blocker)
	   302456 - dragging offscreen too restrictive
	   304857 - wireframe moving off the top of the screen is misleading
	   308521 - make uni-directional resizing easier with
	            alt-middle-drag and prevent the occasional super
	            annoying resize-the-wrong-side(s) behavior
	   312007 - snap-resize moves windows with a minimum size
	            constraint
	   312104 - resizing the top of a window can cause the bottom to
	            grow
	   319351 - don't instantly snap on mouse-move-snapping, remove
	            braindeadedness of having order of releasing shift and
	            releasing button press matter so much

	   [1] fixed in my opinion, anyway.
	   [2] Actually, it's not totally fixed--it's just annoying
	       instead of almost completely unusable.  Matthias had a
	       suggestion that may fix the remainder of the problems (see
	       http://tinyurl.com/bwzuu).
	   [3] This bug was originally about not-quite-so-pathological
	       cases but was left open for the worse cases. The code from
	       the branch handles the remainder of the cases mentioned in
	       this bug.
	   [4] Actually, although it's far better there's still some minor
	       issues left: a slight drift that's only noticeable after
	       lots of resizing, and potential problems with partially
	       onscreen constraints due to not clearing any
	       fixed_directions flags (aspect ratio windows get resized in
	       both directions and thus aren't fixed in one of them)

	New feature:
	    81704 - edge resistance for user move and resize operations;
	            in particular 3 different kinds of resistance are
	            implemented:
             	 Pixel-Distance: window movement is resisted when it
	     	   aligns with an edge unless the movement is greater than
	     	   a threshold number of pixels
             	 Timeout: window movement past an edge is prevented until
	     	   a certain amount of time has elapsed during the
	     	   operation since the first request to move it past that
	     	   edge
             	 Keyboard-Buildup: when moving or resizing with the
	     	   keyboard, once a window is aligned with a certain edge
	     	   it cannot move past until the correct direction has
	     	   been pressed enough times (e.g. 2 or 3 times)

	Major changes:
	  - constraints.c has been rewritten; very few lines of code from
	    the old version remain.  There is a comment near the top of
	    the function explaining the basics of how the new framework
	    works.  A more detailed explanation can be found in
	    doc/how-constraints-works.txt
	  - edge-resistance.[ch] are new files implementing edge-resistance.
	  - boxes.[ch] are new files containing low-level error-prone
	    functions used heavily in constraints.c and edge-resistance.c,
	    among various places throughout the code.  testboxes.c
	    contains a thorough testsuite for the boxes.[ch] functions
	    compiled into a program, testboxes.
	  - meta_window_move_resize_internal() *must* be told the gravity
	    of the associated operation (if it's just a move operation,
	    the gravity will be ignored, but for resize and move+resize
	    the correct value is needed)
	  - the craziness of different values that
	    meta_window_move_resize_internal() accepts has been documented
	    in a large comment at the beginning of the function.  It may
	    be possible to clean this up some, but until then things will
	    remain as they were before--caller beware.
	  - screen and xinerama usable areas (i.e. places not covered by
	    e.g. panels) are cached in the workspace now, as are the
	    screen and xinerama edges.  These get updated with the
	    workarea in src/workspace.c:ensure_work_areas_validated()
This commit is contained in:
Elijah Newren
2005-11-19 14:58:50 +00:00
committed by Elijah Newren
parent cfb3bd081a
commit a7201d27d1
35 changed files with 7358 additions and 2738 deletions

View File

@ -5,6 +5,7 @@ Makefile
metacity
metacity-theme-viewer
metacity-dialog
testboxes
testgradient
inlinepixbufs.h
metacity.desktop

View File

@ -13,6 +13,8 @@ metacity_SOURCES= \
async-getprop.h \
bell.h \
bell.c \
boxes.h \
boxes.c \
common.h \
compositor.c \
compositor.h \
@ -25,6 +27,8 @@ metacity_SOURCES= \
display.h \
draw-workspace.c \
draw-workspace.h \
edge-resistance.c \
edge-resistance.h \
effects.c \
effects.h \
errors.c \
@ -133,11 +137,13 @@ metacity_LDADD=@METACITY_LIBS@ $(EFENCE)
metacity_theme_viewer_LDADD= @METACITY_LIBS@ libmetacity-private.la
metacity_dialog_LDADD=@METACITY_LIBS@
testboxes_SOURCES=util.h util.c boxes.h boxes.c testboxes.c
testgradient_SOURCES=gradient.h gradient.c testgradient.c
testasyncgetprop_SOURCES=async-getprop.h async-getprop.c testasyncgetprop.c
noinst_PROGRAMS=testgradient testasyncgetprop
noinst_PROGRAMS=testboxes testgradient testasyncgetprop
testboxes_LDADD= @METACITY_LIBS@
testgradient_LDADD= @METACITY_LIBS@
testasyncgetprop_LDADD= @METACITY_LIBS@

View File

@ -30,8 +30,8 @@ meta_bell_flash_screen (MetaDisplay *display,
MetaScreen *screen)
{
Window root = screen->xroot;
int width = screen->width;
int height = screen->height;
int width = screen->rect.width;
int height = screen->rect.height;
if (screen->flash_window == None)
{

1745
src/boxes.c Normal file

File diff suppressed because it is too large Load Diff

239
src/boxes.h Normal file
View File

@ -0,0 +1,239 @@
/* Simple box operations */
/*
* Copyright (C) 2005 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;
};
#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_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);
GList* meta_rectangle_expand_region (GList *region,
const int left_expand,
const int right_expand,
const int top_expand,
const int bottom_expand);
/* 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);
/* 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 */
/* */
/***************************************************************************/
/* 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);
/* 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 */

View File

@ -2,6 +2,7 @@
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2005 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
@ -64,7 +65,8 @@ typedef enum
META_MENU_OP_MOVE_LEFT = 1 << 13,
META_MENU_OP_MOVE_RIGHT = 1 << 14,
META_MENU_OP_MOVE_UP = 1 << 15,
META_MENU_OP_MOVE_DOWN = 1 << 16
META_MENU_OP_MOVE_DOWN = 1 << 16,
META_MENU_OP_RECOVER = 1 << 17
} MetaMenuOp;
typedef struct _MetaWindowMenu MetaWindowMenu;
@ -184,6 +186,22 @@ typedef enum
META_VIRTUAL_MOD5_MASK = 1 << 14
} MetaVirtualModifier;
/* Relative directions or sides seem to come up all over the place... */
/* FIXME: Replace
* place.[ch]:MetaWindowEdgePosition,
* screen.[ch]:MetaScreenDirection,
* workspace.[ch]:MetaMotionDirection,
* with the use of MetaDirection.
*/
typedef enum
{
META_DIRECTION_LEFT = 1 << 0,
META_DIRECTION_RIGHT = 1 << 1,
META_DIRECTION_TOP = 1 << 2,
META_DIRECTION_BOTTOM = 1 << 3,
META_DIRECTION_UP = 1 << 2, /* Alternate name for TOP */
META_DIRECTION_DOWN = 1 << 3 /* Alternate name for BOTTOM */
} MetaDirection;
/* Function a window button can have. Note, you can't add stuff here
* without extending the theme format to draw a new function and
@ -226,7 +244,3 @@ struct _MetaButtonLayout
(ycoord) < ((rect).y + (rect).height))
#endif

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
/*
* Copyright (C) 2002 Red Hat, Inc.
* Copyright (C) 2005 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
@ -28,32 +29,18 @@
typedef enum
{
META_RESIZE_LEFT_OR_TOP,
META_RESIZE_CENTER,
META_RESIZE_RIGHT_OR_BOTTOM
} MetaResizeDirection;
META_IS_CONFIGURE_REQUEST = 1 << 0,
META_DO_GRAVITY_ADJUST = 1 << 1,
META_IS_USER_ACTION = 1 << 2,
META_IS_MOVE_ACTION = 1 << 3,
META_IS_RESIZE_ACTION = 1 << 4
} MetaMoveResizeFlags;
void meta_window_constrain (MetaWindow *window,
MetaFrameGeometry *fgeom,
MetaFrameGeometry *orig_fgeom,
MetaMoveResizeFlags flags,
int resize_gravity,
const MetaRectangle *orig,
int x_move_delta,
int y_move_delta,
MetaResizeDirection x_direction,
int x_delta,
MetaResizeDirection y_direction,
int y_delta,
MetaRectangle *new);
MetaResizeDirection meta_x_direction_from_gravity (int gravity);
MetaResizeDirection meta_y_direction_from_gravity (int gravity);
#endif /* META_CONSTRAINTS_H */

View File

@ -3,7 +3,7 @@
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004 Elijah Newren
* Copyright (C) 2004, 2005 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
@ -48,6 +48,23 @@ meta_core_get_client_size (Display *xdisplay,
*height = window->rect.height;
}
gboolean
meta_core_titlebar_is_onscreen (Display *xdisplay,
Window frame_xwindow)
{
MetaDisplay *display;
MetaWindow *window;
display = meta_display_for_x_display (xdisplay);
window = meta_display_lookup_x_window (display, frame_xwindow);
if (window == NULL || window->frame == NULL)
meta_bug ("No such frame window 0x%lx!\n", frame_xwindow);
return meta_window_titlebar_is_onscreen (window);
}
Window
meta_core_get_client_xwindow (Display *xdisplay,
Window frame_xwindow)
@ -371,7 +388,8 @@ meta_core_maximize (Display *xdisplay,
if (window == NULL || window->frame == NULL)
meta_bug ("No such frame window 0x%lx!\n", frame_xwindow);
meta_window_maximize (window);
meta_window_maximize (window,
META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
}
void
@ -387,10 +405,12 @@ meta_core_toggle_maximize (Display *xdisplay,
if (window == NULL || window->frame == NULL)
meta_bug ("No such frame window 0x%lx!\n", frame_xwindow);
if (window->maximized)
meta_window_unmaximize (window);
if (META_WINDOW_MAXIMIZED (window))
meta_window_unmaximize (window,
META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
else
meta_window_maximize (window);
meta_window_maximize (window,
META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
}
void
@ -406,7 +426,8 @@ meta_core_unmaximize (Display *xdisplay,
if (window == NULL || window->frame == NULL)
meta_bug ("No such frame window 0x%lx!\n", frame_xwindow);
meta_window_unmaximize (window);
meta_window_unmaximize (window,
META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
}
void
@ -691,6 +712,9 @@ meta_core_get_menu_accelerator (MetaMenuOp menu_op,
case META_MENU_OP_MOVE_DOWN:
name = META_KEYBINDING_MOVE_WORKSPACE_DOWN;
break;
case META_MENU_OP_RECOVER:
/* No keybinding for this one */
break;
}
if (name)
@ -852,9 +876,9 @@ meta_core_get_screen_size (Display *xdisplay,
meta_bug ("No such frame window 0x%lx!\n", frame_on_screen);
if (width)
*width = window->screen->width;
*width = window->screen->rect.width;
if (height)
*height = window->screen->height;
*height = window->screen->rect.height;
}
void

View File

@ -2,6 +2,7 @@
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2005 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
@ -31,6 +32,9 @@ void meta_core_get_client_size (Display *xdisplay,
int *width,
int *height);
gboolean meta_core_titlebar_is_onscreen (Display *xdisplay,
Window frame_xwindow);
Window meta_core_get_client_xwindow (Display *xdisplay,
Window frame_xwindow);

View File

@ -519,6 +519,8 @@ meta_display_open (const char *name)
display->grab_screen = NULL;
display->grab_resize_popup = NULL;
display->grab_edge_resistance_data = NULL;
#ifdef HAVE_XSYNC
{
int major, minor;
@ -1336,6 +1338,15 @@ handle_net_moveresize_window (MetaDisplay* display,
if (window)
{
/* FIXME!!!! I'm pretty sure this is wrong except _maybe_ for the
* resize-only case; see comment at beginning of
* meta_window_move_resize_internal(). Basically, this should act
* like a configure request--meaning that it should count as an app
* specified change instead of a user one, and the position needs to
* be fixed up with adjust_for_gravity(). In particular,
* meta_window_resize_with_gravity(), meta_window_resize(), and
* meta_window_move_resize() should probably NOT be called.
*/
meta_window_get_gravity_position (window, &x, &y);
width = window->rect.width;
height = window->rect.height;
@ -1391,10 +1402,14 @@ handle_net_restack_window (MetaDisplay* display,
if (window)
{
/*
* The EWMH includes a sibling for the restack request, but we
* don't currently support these types of raises.
/* FIXME: The EWMH includes a sibling for the restack request, but we
* (stupidly) don't currently support these types of raises.
*
* Also, unconditionally following these is REALLY stupid--we should
* combine this code with the stuff in
* meta_window_configure_request() which is smart about whether to
* follow the request or do something else (though not smart enough
* and is also too stupid to handle the sibling stuff).
*/
switch (event->xclient.data.l[2])
{
@ -1670,36 +1685,49 @@ event_callback (XEvent *event,
{
if (window->has_resize_func)
{
gboolean north;
gboolean west;
gboolean north, south;
gboolean west, east;
int root_x, root_y;
MetaGrabOp op;
meta_window_get_position (window, &root_x, &root_y);
west = event->xbutton.x_root < (root_x + window->rect.width / 2);
north = event->xbutton.y_root < (root_y + window->rect.height / 2);
west = event->xbutton.x_root < (root_x + 1 * window->rect.width / 3);
east = event->xbutton.x_root > (root_x + 2 * window->rect.width / 3);
north = event->xbutton.y_root < (root_y + 1 * window->rect.height / 3);
south = event->xbutton.y_root > (root_y + 2 * window->rect.height / 3);
if (west && north)
if (north && west)
op = META_GRAB_OP_RESIZING_NW;
else if (west)
op = META_GRAB_OP_RESIZING_SW;
else if (north)
else if (north && east)
op = META_GRAB_OP_RESIZING_NE;
else
else if (south && west)
op = META_GRAB_OP_RESIZING_SW;
else if (south && east)
op = META_GRAB_OP_RESIZING_SE;
else if (north)
op = META_GRAB_OP_RESIZING_N;
else if (west)
op = META_GRAB_OP_RESIZING_W;
else if (east)
op = META_GRAB_OP_RESIZING_E;
else if (south)
op = META_GRAB_OP_RESIZING_S;
else /* Middle region is no-op to avoid user triggering wrong action */
op = META_GRAB_OP_NONE;
meta_display_begin_grab_op (display,
window->screen,
window,
op,
TRUE,
event->xbutton.serial,
event->xbutton.button,
0,
event->xbutton.time,
event->xbutton.x_root,
event->xbutton.y_root);
if (op != META_GRAB_OP_NONE)
meta_display_begin_grab_op (display,
window->screen,
window,
op,
TRUE,
event->xbutton.serial,
event->xbutton.button,
0,
event->xbutton.time,
event->xbutton.x_root,
event->xbutton.y_root);
}
}
else if (event->xbutton.button == 3)
@ -3244,6 +3272,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
display->grab_old_window_stacking = NULL;
#ifdef HAVE_XSYNC
display->grab_sync_request_alarm = None;
display->grab_last_user_action_was_snap = FALSE;
#endif
display->grab_was_cancelled = FALSE;
@ -3335,6 +3364,18 @@ meta_display_begin_grab_op (MetaDisplay *display,
g_assert (display->grab_window != NULL || display->grab_screen != NULL);
g_assert (display->grab_op != META_GRAB_OP_NONE);
/* If this is a move or resize, cache the window edges for
* resistance/snapping
*/
if (meta_grab_op_is_resizing (display->grab_op) ||
meta_grab_op_is_moving (display->grab_op))
{
meta_topic (META_DEBUG_WINDOW_OPS,
"Computing edges to resist-movement or snap-to for %s.\n",
window->desc);
meta_display_compute_resistance_and_snapping_edges (display);
}
/* Save the old stacking */
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
{
@ -3408,6 +3449,15 @@ meta_display_end_grab_op (MetaDisplay *display,
display->ungrab_should_not_cause_focus_window = display->grab_xwindow;
}
/* If this was a move or resize clear out the edge cache */
if (meta_grab_op_is_resizing (display->grab_op) ||
meta_grab_op_is_moving (display->grab_op))
{
meta_topic (META_DEBUG_WINDOW_OPS,
"Clearing out the edges for resistance/snapping");
meta_display_cleanup_edges (display);
}
if (display->grab_old_window_stacking != NULL)
{
meta_topic (META_DEBUG_WINDOW_OPS,
@ -4276,53 +4326,6 @@ meta_resize_gravity_from_grab_op (MetaGrabOp op)
return gravity;
}
gboolean
meta_rectangle_intersect (MetaRectangle *src1,
MetaRectangle *src2,
MetaRectangle *dest)
{
int dest_x, dest_y;
int dest_w, dest_h;
int return_val;
g_return_val_if_fail (src1 != NULL, FALSE);
g_return_val_if_fail (src2 != NULL, FALSE);
g_return_val_if_fail (dest != NULL, FALSE);
return_val = FALSE;
dest_x = MAX (src1->x, src2->x);
dest_y = MAX (src1->y, src2->y);
dest_w = MIN (src1->x + src1->width, src2->x + src2->width) - dest_x;
dest_h = MIN (src1->y + src1->height, src2->y + src2->height) - dest_y;
if (dest_w > 0 && dest_h > 0)
{
dest->x = dest_x;
dest->y = dest_y;
dest->width = dest_w;
dest->height = dest_h;
return_val = TRUE;
}
else
{
dest->width = 0;
dest->height = 0;
}
return return_val;
}
gboolean
meta_rectangle_equal (const MetaRectangle *src1,
const MetaRectangle *src2)
{
return ((src1->x == src2->x) &&
(src1->y == src2->y) &&
(src1->width == src2->width) &&
(src1->height == src2->height));
}
static MetaScreen*
find_screen_for_selection (MetaDisplay *display,
Window owner,

View File

@ -33,6 +33,7 @@
#include <X11/Xlib.h>
#include "eventqueue.h"
#include "common.h"
#include "boxes.h"
#ifdef HAVE_STARTUP_NOTIFICATION
#include <libsn/sn.h>
@ -44,17 +45,6 @@
#define meta_XFree(p) do { if ((p)) XFree ((p)); } while (0)
/* this doesn't really belong here, oh well. */
typedef struct _MetaRectangle MetaRectangle;
struct _MetaRectangle
{
int x;
int y;
int width;
int height;
};
typedef struct MetaCompositor MetaCompositor;
typedef struct _MetaDisplay MetaDisplay;
typedef struct _MetaFrame MetaFrame;
@ -68,6 +58,8 @@ typedef struct _MetaWorkspace MetaWorkspace;
typedef struct _MetaWindowPropHooks MetaWindowPropHooks;
typedef struct _MetaGroupPropHooks MetaGroupPropHooks;
typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
typedef void (* MetaWindowPingFunc) (MetaDisplay *display,
Window xwindow,
Time timestamp,
@ -280,6 +272,7 @@ struct _MetaDisplay
int grab_wireframe_last_display_width;
int grab_wireframe_last_display_height;
GList* grab_old_window_stacking;
MetaEdgeResistanceData *grab_edge_resistance_data;
/* we use property updates as sentinels for certain window focus events
* to avoid some race conditions on EnterNotify events
@ -350,6 +343,7 @@ struct _MetaDisplay
int render_error_base;
#endif
#ifdef HAVE_XSYNC
unsigned int grab_last_user_action_was_snap;
unsigned int have_xsync : 1;
#define META_DISPLAY_HAS_XSYNC(display) ((display)->have_xsync)
#else
@ -459,6 +453,10 @@ void meta_display_grab_focus_window_button (MetaDisplay *display,
void meta_display_ungrab_focus_window_button (MetaDisplay *display,
MetaWindow *window);
/* Next two functions are defined in edge-resistance.c */
void meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display);
void meta_display_cleanup_edges (MetaDisplay *display);
/* make a request to ensure the event serial has changed */
void meta_display_increment_event_serial (MetaDisplay *display);
@ -490,8 +488,6 @@ typedef enum
{
META_TAB_LIST_NORMAL,
META_TAB_LIST_DOCKS
} MetaTabList;
GList* meta_display_get_tab_list (MetaDisplay *display,
@ -516,12 +512,6 @@ int meta_resize_gravity_from_grab_op (MetaGrabOp op);
gboolean meta_grab_op_is_moving (MetaGrabOp op);
gboolean meta_grab_op_is_resizing (MetaGrabOp op);
gboolean meta_rectangle_intersect (MetaRectangle *src1,
MetaRectangle *src2,
MetaRectangle *dest);
gboolean meta_rectangle_equal (const MetaRectangle *src1,
const MetaRectangle *src2);
void meta_display_devirtualize_modifiers (MetaDisplay *display,
MetaVirtualModifier modifiers,
unsigned int *mask);

1278
src/edge-resistance.c Normal file

File diff suppressed because it is too large Load Diff

46
src/edge-resistance.h Normal file
View File

@ -0,0 +1,46 @@
/* Edge resistance for move/resize operations */
/*
* Copyright (C) 2005 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_EDGE_RESISTANCE_H
#define META_EDGE_RESISTANCE_H
#include "window.h"
void meta_window_edge_resistance_for_move (MetaWindow *window,
int old_x,
int old_y,
int *new_x,
int *new_y,
GSourceFunc timeout_func,
gboolean snap,
gboolean is_keyboard_op);
void meta_window_edge_resistance_for_resize (MetaWindow *window,
int old_width,
int old_height,
int *new_width,
int *new_height,
int gravity,
GSourceFunc timeout_func,
gboolean snap,
gboolean is_keyboard_op);
#endif /* META_EDGE_RESISTANCE_H */

View File

@ -3,6 +3,7 @@
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2003, 2004 Red Hat, Inc.
* Copyright (C) 2005 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
@ -264,7 +265,10 @@ meta_frame_get_flags (MetaFrame *frame)
if (frame->window->on_all_workspaces)
flags |= META_FRAME_STUCK;
if (frame->window->maximized)
/* FIXME: Should we have some kind of UI for windows that are just vertically
* maximized or just horizontally maximized?
*/
if (META_WINDOW_MAXIMIZED (frame->window))
flags |= META_FRAME_MAXIMIZED;
if (frame->window->fullscreen)

View File

@ -3,6 +3,7 @@
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2003 Red Hat, Inc.
* Copyright (C) 2005 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
@ -1441,16 +1442,25 @@ meta_frames_button_press_event (GtkWidget *widget,
break;
}
meta_core_begin_grab_op (gdk_display,
frame->xwindow,
op,
TRUE,
meta_ui_get_last_event_serial (gdk_display),
event->button,
0,
event->time,
event->x_root,
event->y_root);
if (!meta_core_titlebar_is_onscreen (gdk_display,
frame->xwindow))
meta_core_show_window_menu (gdk_display,
frame->xwindow,
event->x_root,
event->y_root,
event->button,
event->time);
else
meta_core_begin_grab_op (gdk_display,
frame->xwindow,
op,
TRUE,
meta_ui_get_last_event_serial (gdk_display),
event->button,
0,
event->time,
event->x_root,
event->y_root);
}
else if (control == META_FRAME_CONTROL_TITLE &&
event->button == 1)

View File

@ -26,6 +26,7 @@
#include "keybindings.h"
#include "workspace.h"
#include "errors.h"
#include "edge-resistance.h"
#include "ui.h"
#include "frame.h"
#include "place.h"
@ -1690,8 +1691,6 @@ process_keyboard_move_grab (MetaDisplay *display,
int x, y;
int incr;
gboolean smart_snap;
int edge;
int candidate_position;
handled = FALSE;
@ -1719,7 +1718,7 @@ process_keyboard_move_grab (MetaDisplay *display,
#define NORMAL_INCREMENT 10
if (smart_snap)
incr = 0;
incr = 1;
else if (event->xkey.state & ControlMask)
incr = SMALL_INCREMENT;
else
@ -1754,18 +1753,6 @@ process_keyboard_move_grab (MetaDisplay *display,
case XK_Up:
case XK_KP_Up:
y -= incr;
edge = meta_window_find_next_horizontal_edge (window,
META_WINDOW_EDGE_TOP,
FALSE);
if (window->frame)
candidate_position = edge + window->frame->child_y;
else
candidate_position = edge;
if (smart_snap || ((candidate_position > y) && ABS (candidate_position - y) < incr))
y = candidate_position;
handled = TRUE;
break;
case XK_KP_End:
@ -1773,18 +1760,6 @@ process_keyboard_move_grab (MetaDisplay *display,
case XK_Down:
case XK_KP_Down:
y += incr;
edge = meta_window_find_next_horizontal_edge (window,
META_WINDOW_EDGE_BOTTOM,
TRUE);
if (window->frame)
candidate_position = edge - window->frame->bottom_height - window->rect.height;
else
candidate_position = edge - window->rect.height;
if (smart_snap || ((candidate_position < y) && ABS (candidate_position - y) < incr))
y = candidate_position;
handled = TRUE;
break;
}
@ -1796,19 +1771,6 @@ process_keyboard_move_grab (MetaDisplay *display,
case XK_Left:
case XK_KP_Left:
x -= incr;
edge = meta_window_find_next_vertical_edge (window,
META_WINDOW_EDGE_LEFT,
FALSE);
if (window->frame)
candidate_position = edge + window->frame->child_x;
else
candidate_position = edge;
if (smart_snap ||
((candidate_position > x) && ABS (candidate_position - x) < incr))
x = candidate_position;
handled = TRUE;
break;
case XK_KP_Prior:
@ -1816,27 +1778,34 @@ process_keyboard_move_grab (MetaDisplay *display,
case XK_Right:
case XK_KP_Right:
x += incr;
edge = meta_window_find_next_vertical_edge (window,
META_WINDOW_EDGE_RIGHT,
TRUE);
if (window->frame)
candidate_position = edge - window->frame->right_width - window->rect.width;
else
candidate_position = edge - window->rect.width;
if (smart_snap || ((candidate_position < x) && ABS (candidate_position - x) < incr))
x = candidate_position;
handled = TRUE;
break;
}
if (handled)
{
MetaRectangle old_rect;
meta_topic (META_DEBUG_KEYBINDINGS,
"Computed new window location %d,%d due to keypress\n",
x, y);
if (display->grab_wireframe_active)
old_rect = display->grab_wireframe_rect;
else
{
old_rect = window->rect;
meta_window_get_position (window, &old_rect.x, &old_rect.y);
}
meta_window_edge_resistance_for_move (window,
old_rect.x,
old_rect.y,
&x,
&y,
NULL,
smart_snap,
TRUE);
if (display->grab_wireframe_active)
{
meta_window_update_wireframe (window, x, y,
@ -1986,13 +1955,9 @@ process_keyboard_resize_grab (MetaDisplay *display,
gboolean handled;
int height_inc;
int width_inc;
int x, y;
int orig_x, orig_y;
int width, height;
gboolean smart_snap;
int edge;
int gravity;
int candidate_position;
handled = FALSE;
@ -2029,21 +1994,15 @@ process_keyboard_resize_grab (MetaDisplay *display,
if (display->grab_wireframe_active)
{
orig_x = display->grab_wireframe_rect.x;
orig_y = display->grab_wireframe_rect.y;
width = display->grab_wireframe_rect.width;
height = display->grab_wireframe_rect.height;
}
else
{
meta_window_get_position (window, &orig_x, &orig_y);
width = window->rect.width;
height = window->rect.height;
}
x = orig_x;
y = orig_y;
gravity = meta_resize_gravity_from_grab_op (display->grab_op);
smart_snap = (event->xkey.state & ShiftMask) != 0;
@ -2053,40 +2012,28 @@ process_keyboard_resize_grab (MetaDisplay *display,
if (smart_snap)
{
height_inc = 0;
width_inc = 0;
height_inc = 1;
width_inc = 1;
}
else if (event->xkey.state & ControlMask)
{
if (window->size_hints.width_inc > 1)
width_inc = window->size_hints.width_inc;
else
width_inc = SMALL_INCREMENT;
if (window->size_hints.height_inc > 1)
height_inc = window->size_hints.height_inc;
else
height_inc = SMALL_INCREMENT;
width_inc = SMALL_INCREMENT;
height_inc = SMALL_INCREMENT;
}
else
{
if (window->size_hints.width_inc > 1)
width_inc = window->size_hints.width_inc;
else
width_inc = NORMAL_INCREMENT;
if (window->size_hints.height_inc > 1)
height_inc = window->size_hints.height_inc;
else
height_inc = NORMAL_INCREMENT;
width_inc = NORMAL_INCREMENT;
height_inc = NORMAL_INCREMENT;
}
/* When moving by increments, we still snap to edges if the move
* to the edge is smaller than the increment. This is because
* Shift + arrow to snap is sort of a hidden feature. This way
* people using just arrows shouldn't get too frustrated.
/* If this is a resize increment window, make the amount we resize
* the window by match that amount (well, unless snap resizing...)
*/
if (window->size_hints.width_inc > 1)
width_inc = window->size_hints.width_inc;
if (window->size_hints.height_inc > 1)
height_inc = window->size_hints.height_inc;
switch (keysym)
{
case XK_Up:
@ -2097,49 +2044,14 @@ process_keyboard_resize_grab (MetaDisplay *display,
case NorthWestGravity:
case NorthEastGravity:
/* Move bottom edge up */
edge = meta_window_find_next_horizontal_edge (window,
META_WINDOW_EDGE_BOTTOM,
FALSE);
if (window->frame)
candidate_position = edge - window->frame->bottom_height;
else
candidate_position = edge;
if (smart_snap ||
((candidate_position > (y + (height - height_inc))) &&
ABS (candidate_position - (y + (height - height_inc))) < height_inc))
{
if (candidate_position - y > 0)
height = candidate_position - y;
}
else if (height - height_inc > 0)
{
height -= height_inc;
}
handled = TRUE;
height -= height_inc;
break;
case SouthGravity:
case SouthWestGravity:
case SouthEastGravity:
/* Move top edge up */
y -= height_inc;
edge = meta_window_find_next_horizontal_edge (window,
META_WINDOW_EDGE_TOP,
FALSE);
if (window->frame)
candidate_position = edge + window->frame->child_y;
else
candidate_position = edge;
if (smart_snap || ((candidate_position > y) && ABS (candidate_position - y) < height_inc))
y = candidate_position;
height += (orig_y - y);
height += height_inc;
break;
case EastGravity:
@ -2161,49 +2073,13 @@ process_keyboard_resize_grab (MetaDisplay *display,
case NorthEastGravity:
/* Move bottom edge down */
height += height_inc;
edge = meta_window_find_next_horizontal_edge (window,
META_WINDOW_EDGE_BOTTOM,
TRUE);
if (window->frame)
candidate_position = edge - window->frame->bottom_height;
else
candidate_position = edge;
if (smart_snap || ((candidate_position < (y+height)) &&
ABS (candidate_position - (y+height)) < height_inc))
height = candidate_position - y;
break;
case SouthGravity:
case SouthWestGravity:
case SouthEastGravity:
/* Move top edge down */
edge = meta_window_find_next_horizontal_edge (window,
META_WINDOW_EDGE_TOP,
TRUE);
if (window->frame)
candidate_position = edge + window->frame->child_y;
else
candidate_position = edge;
if (smart_snap ||
((candidate_position < (y + height_inc)) &&
ABS (candidate_position - (y + height_inc)) < height_inc))
{
if (height - (candidate_position - orig_y) > 0)
{
y = candidate_position;
height -= (y - orig_y);
}
}
else if (height - ((y + height_inc) - orig_y) > 0)
{
y += height_inc;
height -= (y - orig_y);
}
height -= height_inc;
break;
case EastGravity:
@ -2223,50 +2099,15 @@ process_keyboard_resize_grab (MetaDisplay *display,
case EastGravity:
case SouthEastGravity:
case NorthEastGravity:
x -= width_inc;
/* Move left edge left */
edge = meta_window_find_next_vertical_edge (window,
META_WINDOW_EDGE_LEFT,
FALSE);
if (window->frame)
candidate_position = edge + window->frame->child_x;
else
candidate_position = edge;
if (smart_snap || ((candidate_position > x) && ABS (candidate_position - x) < width_inc))
x = candidate_position;
width += (orig_x - x);
width += width_inc;
break;
case WestGravity:
case SouthWestGravity:
case NorthWestGravity:
/* Move right edge left */
edge = meta_window_find_next_vertical_edge (window,
META_WINDOW_EDGE_RIGHT,
FALSE);
if (window->frame)
candidate_position = edge - window->frame->right_width;
else
candidate_position = edge;
if (smart_snap ||
((candidate_position > (x + (width - width_inc))) &&
ABS (candidate_position - (x + (width - width_inc))) < width_inc))
{
if (candidate_position - x > 0)
width = candidate_position - x;
}
else if (width - width_inc > 0)
{
width -= width_inc;
}
handled = TRUE;
width -= width_inc;
break;
case NorthGravity:
@ -2287,30 +2128,7 @@ process_keyboard_resize_grab (MetaDisplay *display,
case SouthEastGravity:
case NorthEastGravity:
/* Move left edge right */
edge = meta_window_find_next_vertical_edge (window,
META_WINDOW_EDGE_LEFT,
TRUE);
if (window->frame)
candidate_position = edge + window->frame->child_x;
else
candidate_position = edge;
if (smart_snap ||
((candidate_position < (x + width_inc)) &&
ABS (candidate_position - (x + width_inc)) < width_inc))
{
if (width - (candidate_position - orig_x) > 0)
{
x = candidate_position;
width -= (x - orig_x);
}
}
else if (width - ((x + width_inc) - orig_x) > 0)
{
x += width_inc;
width -= (x - orig_x);
}
width -= width_inc;
break;
case WestGravity:
@ -2318,21 +2136,6 @@ process_keyboard_resize_grab (MetaDisplay *display,
case NorthWestGravity:
/* Move right edge right */
width += width_inc;
edge = meta_window_find_next_vertical_edge (window,
META_WINDOW_EDGE_RIGHT,
TRUE);
if (window->frame)
candidate_position = edge - window->frame->right_width;
else
candidate_position = edge;
if (smart_snap || ((candidate_position > (x+width)) &&
ABS (candidate_position - (x+width)) < width_inc))
width = candidate_position - x;
handled = TRUE;
break;
case NorthGravity:
@ -2357,17 +2160,53 @@ process_keyboard_resize_grab (MetaDisplay *display,
if (handled)
{
MetaRectangle old_rect;
meta_topic (META_DEBUG_KEYBINDINGS,
"Computed new window location %d,%d %dx%d due to keypress\n",
x, y, width, height);
"Computed new window size due to keypress: "
"%dx%d, gravity %s\n",
width, height, meta_gravity_to_string (gravity));
if (display->grab_wireframe_active)
old_rect = display->grab_wireframe_rect;
else
old_rect = window->rect; /* Don't actually care about x,y */
/* Do any edge resistance/snapping */
meta_window_edge_resistance_for_resize (window,
old_rect.width,
old_rect.height,
&width,
&height,
gravity,
NULL,
smart_snap,
TRUE);
if (display->grab_wireframe_active)
{
meta_window_update_wireframe (window, x, y, width, height);
MetaRectangle new_position;
meta_rectangle_resize_with_gravity (&display->grab_wireframe_rect,
&new_position,
gravity,
width,
height);
meta_window_update_wireframe (window,
new_position.x,
new_position.y,
new_position.width,
new_position.height);
}
else
{
meta_window_move_resize (window, TRUE, x, y, width, height);
/* We don't need to update unless the specified width and height
* are actually different from what we had before.
*/
if (window->rect.width != width || window->rect.height != height)
meta_window_resize_with_gravity (window,
TRUE,
width,
height,
gravity);
}
meta_window_update_keyboard_resize (window, FALSE);
}
@ -2782,10 +2621,12 @@ handle_maximize_vert (MetaDisplay *display,
XEvent *event,
MetaKeyBinding *binding)
{
if (window)
if (window && window->has_resize_func)
{
if (window->has_resize_func)
meta_window_fill_vertical (window);
if (window->maximized_vertically)
meta_window_unmaximize (window, META_MAXIMIZE_VERTICAL);
else
meta_window_maximize (window, META_MAXIMIZE_VERTICAL);
}
}
@ -2796,10 +2637,12 @@ handle_maximize_horiz (MetaDisplay *display,
XEvent *event,
MetaKeyBinding *binding)
{
if (window)
if (window && window->has_resize_func)
{
if (window->has_resize_func)
meta_window_fill_horizontal (window);
if (window->maximized_horizontally)
meta_window_unmaximize (window, META_MAXIMIZE_HORIZONTAL);
else
meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL);
}
}
@ -3230,10 +3073,14 @@ handle_toggle_maximize (MetaDisplay *display,
{
if (window)
{
if (window->maximized)
meta_window_unmaximize (window);
if (META_WINDOW_MAXIMIZED (window))
meta_window_unmaximize (window,
META_MAXIMIZE_HORIZONTAL |
META_MAXIMIZE_VERTICAL);
else if (window->has_maximize_func)
meta_window_maximize (window);
meta_window_maximize (window,
META_MAXIMIZE_HORIZONTAL |
META_MAXIMIZE_VERTICAL);
}
}
@ -3247,7 +3094,9 @@ handle_maximize (MetaDisplay *display,
if (window)
{
if (window->has_maximize_func)
meta_window_maximize (window);
meta_window_maximize (window,
META_MAXIMIZE_HORIZONTAL |
META_MAXIMIZE_VERTICAL);
}
}
@ -3260,8 +3109,10 @@ handle_unmaximize (MetaDisplay *display,
{
if (window)
{
if (window->maximized)
meta_window_unmaximize (window);
if (window->maximized_vertically || window->maximized_horizontally)
meta_window_unmaximize (window,
META_MAXIMIZE_HORIZONTAL |
META_MAXIMIZE_VERTICAL);
}
}

View File

@ -3,6 +3,7 @@
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2004 Rob Adams
* Copyright (C) 2005 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
@ -60,6 +61,7 @@ static MenuItem menuitems[] = {
{ META_MENU_OP_UNABOVE, NULL, TRUE, N_("On _Top") },
{ META_MENU_OP_MOVE, NULL, FALSE, N_("_Move") },
{ META_MENU_OP_RESIZE, NULL, FALSE, N_("_Resize") },
{ META_MENU_OP_RECOVER, NULL, FALSE, N_("Move Titlebar On_screen") },
{ 0, NULL, FALSE, NULL }, /* separator */
{ META_MENU_OP_DELETE, METACITY_STOCK_DELETE, FALSE, N_("_Close") },
{ META_MENU_OP_WORKSPACES, NULL, FALSE, NULL }, /* separator */

View File

@ -529,16 +529,6 @@ center_tile_rect_in_area (MetaRectangle *rect,
rect->y = work_area->y + fluff;
}
static gboolean
rect_fits_in_work_area (MetaRectangle *work_area,
MetaRectangle *rect)
{
return ((rect->x >= work_area->x) &&
(rect->y >= work_area->y) &&
(rect->x + rect->width <= work_area->x + work_area->width) &&
(rect->y + rect->height <= work_area->y + work_area->height));
}
/* Find the leftmost, then topmost, empty area on the workspace
* that can contain the new window.
*
@ -597,13 +587,15 @@ find_first_fit (MetaWindow *window,
for (i = 0; i < n_xineramas; i++)
{
#ifdef WITH_VERBOSE_MODE
char xinerama_location_string[RECT_LENGTH];
meta_rectangle_to_string (&window->screen->xinerama_infos[xineramas_list[i]].rect,
xinerama_location_string);
meta_topic (META_DEBUG_XINERAMA,
"Natural xinerama %d is %d,%d %dx%d\n",
"Natural xinerama %d is %s\n",
i,
window->screen->xinerama_infos[xineramas_list[i]].x_origin,
window->screen->xinerama_infos[xineramas_list[i]].y_origin,
window->screen->xinerama_infos[xineramas_list[i]].width,
window->screen->xinerama_infos[xineramas_list[i]].height);
xinerama_location_string);
#endif
}
/* try each xinerama in the natural ordering in turn */
@ -614,7 +606,7 @@ find_first_fit (MetaWindow *window,
center_tile_rect_in_area (&rect, &work_area);
if (rect_fits_in_work_area (&work_area, &rect) &&
if (meta_rectangle_contains_rect (&work_area, &rect) &&
!rectangle_overlaps_some_window (&rect, windows))
{
*new_x = rect.x;
@ -642,7 +634,7 @@ find_first_fit (MetaWindow *window,
rect.x = outer_rect.x;
rect.y = outer_rect.y + outer_rect.height;
if (rect_fits_in_work_area (&work_area, &rect) &&
if (meta_rectangle_contains_rect (&work_area, &rect) &&
!rectangle_overlaps_some_window (&rect, below_sorted))
{
*new_x = rect.x;
@ -673,7 +665,7 @@ find_first_fit (MetaWindow *window,
rect.x = outer_rect.x + outer_rect.width;
rect.y = outer_rect.y;
if (rect_fits_in_work_area (&work_area, &rect) &&
if (meta_rectangle_contains_rect (&work_area, &rect) &&
!rectangle_overlaps_some_window (&rect, right_sorted))
{
*new_x = rect.x;
@ -817,7 +809,6 @@ meta_window_place (MetaWindow *window,
if (parent)
{
int w;
MetaRectangle area;
meta_window_get_position (parent, &x, &y);
w = parent->rect.width;
@ -836,6 +827,16 @@ meta_window_place (MetaWindow *window,
if (fgeom)
y += fgeom->top_height;
#if 0
/* FIXME: If no one has complained about this within a couple
* months, it means that the constraints.c rewrite fixed this
* correctly and this hack is no longer necessary. Feel free to
* submit a patch removing this #ifdef'd out code. (Comment
* written on 2005-10-28).
*/
MetaRectangle area;
/* clip to xinerama of parent*/
meta_window_get_work_area_current_xinerama (parent, &area);
@ -845,6 +846,7 @@ meta_window_place (MetaWindow *window,
y = area.y + area.height - window->rect.height;
if (x < area.x) x = area.x;
if (y < area.y) y = area.y;
#endif
meta_topic (META_DEBUG_PLACEMENT, "Centered window %s over transient parent\n",
window->desc);
@ -867,20 +869,20 @@ meta_window_place (MetaWindow *window,
window->type == META_WINDOW_MODAL_DIALOG ||
window->type == META_WINDOW_SPLASHSCREEN)
{
/* Center on screen */
/* Center on current xinerama (i.e. on current monitor) */
int w, h;
/* Warning, this function is a round trip! */
xi = meta_screen_get_current_xinerama (window->screen);
w = xi->width;
h = xi->height;
w = xi->rect.width;
h = xi->rect.height;
x = (w - window->rect.width) / 2;
y = (h - window->rect.height) / 2;
x += xi->x_origin;
y += xi->y_origin;
x += xi->rect.x;
y += xi->rect.y;
meta_topic (META_DEBUG_PLACEMENT, "Centered window %s on screen %d xinerama %d\n",
window->desc, window->screen->number, xi->number);
@ -919,8 +921,8 @@ meta_window_place (MetaWindow *window,
xi = meta_screen_get_current_xinerama (window->screen);
/* "Origin" placement algorithm */
x = xi->x_origin;
y = xi->y_origin;
x = xi->rect.x;
y = xi->rect.y;
if (find_first_fit (window, fgeom, windows,
xineramas_list, n_xineramas,
@ -986,11 +988,11 @@ meta_window_place (MetaWindow *window,
&workarea);
meta_window_get_outer_rect (window, &outer);
if (outer.width >= workarea.width &&
outer.height >= workarea.height)
{
window->maximize_after_placement = TRUE;
}
if (outer.width >= workarea.width)
window->maximize_horizontally_after_placement = TRUE;
if (outer.height >= workarea.height)
window->maximize_vertically_after_placement = TRUE;
}
done_check_denied_focus:
@ -1022,8 +1024,8 @@ meta_window_place (MetaWindow *window,
focus_window_list = g_list_prepend (NULL, focus_window);
/* Reset x and y ("origin" placement algorithm) */
x = xi->x_origin;
y = xi->y_origin;
x = xi->rect.x;
y = xi->rect.y;
found_fit = find_first_fit (window, fgeom, focus_window_list,
xineramas_list, n_xineramas,
@ -1094,33 +1096,6 @@ get_windows_showing_on_same_screen (MetaWindow *window,
return windows;
}
static gboolean
rects_overlap_vertically (const MetaRectangle *a,
const MetaRectangle *b)
{
/* if they don't overlap, then either a is above b
* or b is above a
*/
if ((a->y + a->height) < b->y)
return FALSE;
else if ((b->y + b->height) < a->y)
return FALSE;
else
return TRUE;
}
static gboolean
rects_overlap_horizontally (const MetaRectangle *a,
const MetaRectangle *b)
{
if ((a->x + a->width) < b->x)
return FALSE;
else if ((b->x + b->width) < a->x)
return FALSE;
else
return TRUE;
}
static void
get_vertical_edges (MetaWindow *window,
int **edges_p,
@ -1149,13 +1124,13 @@ get_vertical_edges (MetaWindow *window,
g_array_append_val (edges, edge);
edge = 0;
g_array_append_val (edges, edge);
g_array_append_val (edges, window->screen->width);
g_array_append_val (edges, window->screen->rect.width);
/* Now get the xinerama screen edges */
for (i = 0; i < window->screen->n_xinerama_infos - 1; i++)
{
edge = window->screen->xinerama_infos[i].x_origin +
window->screen->xinerama_infos[i].width;
edge = window->screen->xinerama_infos[i].rect.x +
window->screen->xinerama_infos[i].rect.width;
g_array_append_val (edges, edge);
}
@ -1185,7 +1160,7 @@ get_vertical_edges (MetaWindow *window,
meta_window_get_outer_rect (w, &w_rect);
if (rects_overlap_vertically (&rect, &w_rect))
if (meta_rectangle_vert_overlap (&rect, &w_rect))
{
g_array_append_val (edges, w_rect.x);
edge = w_rect.x + w_rect.width;
@ -1231,13 +1206,13 @@ get_horizontal_edges (MetaWindow *window,
g_array_append_val (edges, edge);
edge = 0;
g_array_append_val (edges, edge);
g_array_append_val (edges, window->screen->height);
g_array_append_val (edges, window->screen->rect.height);
/* Now get the xinerama screen edges */
for (i = 0; i < window->screen->n_xinerama_infos - 1; i++)
{
edge = window->screen->xinerama_infos[i].y_origin +
window->screen->xinerama_infos[i].height;
edge = window->screen->xinerama_infos[i].rect.y +
window->screen->xinerama_infos[i].rect.height;
g_array_append_val (edges, edge);
}
@ -1266,7 +1241,7 @@ get_horizontal_edges (MetaWindow *window,
meta_window_get_outer_rect (w, &w_rect);
if (rects_overlap_horizontally (&rect, &w_rect))
if (meta_rectangle_horiz_overlap (&rect, &w_rect))
{
g_array_append_val (edges, w_rect.y);
edge = w_rect.y + w_rect.height;

View File

@ -6,7 +6,7 @@
* Some ICCCM manager selection code derived from fvwm2,
* Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004 Elijah Newren
* Copyright (C) 2004, 2005 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
@ -221,18 +221,18 @@ reload_xinerama_infos (MetaScreen *screen)
while (i < n_infos)
{
screen->xinerama_infos[i].number = infos[i].screen_number;
screen->xinerama_infos[i].x_origin = infos[i].x_org;
screen->xinerama_infos[i].y_origin = infos[i].y_org;
screen->xinerama_infos[i].width = infos[i].width;
screen->xinerama_infos[i].height = infos[i].height;
screen->xinerama_infos[i].rect.x = infos[i].x_org;
screen->xinerama_infos[i].rect.y = infos[i].y_org;
screen->xinerama_infos[i].rect.width = infos[i].width;
screen->xinerama_infos[i].rect.height = infos[i].height;
meta_topic (META_DEBUG_XINERAMA,
"Xinerama %d is %d,%d %d x %d\n",
screen->xinerama_infos[i].number,
screen->xinerama_infos[i].x_origin,
screen->xinerama_infos[i].y_origin,
screen->xinerama_infos[i].width,
screen->xinerama_infos[i].height);
screen->xinerama_infos[i].rect.x,
screen->xinerama_infos[i].rect.y,
screen->xinerama_infos[i].rect.width,
screen->xinerama_infos[i].rect.height);
++i;
}
@ -282,18 +282,18 @@ reload_xinerama_infos (MetaScreen *screen)
while (i < n_monitors)
{
screen->xinerama_infos[i].number = i;
screen->xinerama_infos[i].x_origin = monitors[i].x;
screen->xinerama_infos[i].y_origin = monitors[i].y;
screen->xinerama_infos[i].width = monitors[i].width;
screen->xinerama_infos[i].height = monitors[i].height;
screen->xinerama_infos[i].rect.x = monitors[i].x;
screen->xinerama_infos[i].rect.y = monitors[i].y;
screen->xinerama_infos[i].rect.width = monitors[i].width;
screen->xinerama_infos[i].rect.height = monitors[i].height;
meta_topic (META_DEBUG_XINERAMA,
"Xinerama %d is %d,%d %d x %d\n",
screen->xinerama_infos[i].number,
screen->xinerama_infos[i].x_origin,
screen->xinerama_infos[i].y_origin,
screen->xinerama_infos[i].width,
screen->xinerama_infos[i].height);
screen->xinerama_infos[i].rect.x,
screen->xinerama_infos[i].rect.y,
screen->xinerama_infos[i].rect.width,
screen->xinerama_infos[i].rect.height);
++i;
}
@ -325,16 +325,13 @@ reload_xinerama_infos (MetaScreen *screen)
screen->n_xinerama_infos = 2;
screen->xinerama_infos[0].number = 0;
screen->xinerama_infos[0].x_origin = 0;
screen->xinerama_infos[0].y_origin = 0;
screen->xinerama_infos[0].width = screen->width / 2;
screen->xinerama_infos[0].height = screen->height;
screen->xinerama_infos[0].rect = screen->rect;
screen->xinerama_infos[0].rect.width = screen->rect.width / 2;
screen->xinerama_infos[1].number = 1;
screen->xinerama_infos[1].x_origin = screen->width / 2;
screen->xinerama_infos[1].y_origin = 0;
screen->xinerama_infos[1].width = screen->width / 2 + screen->width % 2;
screen->xinerama_infos[1].height = screen->height;
screen->xinerama_infos[1].rect = screen->rect;
screen->xinerama_infos[1].rect.x = screen->rect.width / 2;
screen->xinerama_infos[1].rect.width = screen->rect.width / 2;
}
else
{
@ -345,10 +342,7 @@ reload_xinerama_infos (MetaScreen *screen)
screen->n_xinerama_infos = 1;
screen->xinerama_infos[0].number = 0;
screen->xinerama_infos[0].x_origin = 0;
screen->xinerama_infos[0].y_origin = 0;
screen->xinerama_infos[0].width = screen->width;
screen->xinerama_infos[0].height = screen->height;
screen->xinerama_infos[0].rect = screen->rect;
}
}
@ -520,8 +514,9 @@ meta_screen_new (MetaDisplay *display,
screen->screen_name = get_screen_name (display, number);
screen->xscreen = ScreenOfDisplay (xdisplay, number);
screen->xroot = xroot;
screen->width = WidthOfScreen (screen->xscreen);
screen->height = HeightOfScreen (screen->xscreen);
screen->rect.x = screen->rect.y = 0;
screen->rect.width = WidthOfScreen (screen->xscreen);
screen->rect.height = HeightOfScreen (screen->xscreen);
screen->current_cursor = -1; /* invalid/unset */
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
@ -1015,8 +1010,8 @@ set_desktop_geometry_hint (MetaScreen *screen)
if (screen->closing > 0)
return;
data[0] = screen->width;
data[1] = screen->height;
data[0] = screen->rect.width;
data[1] = screen->rect.height;
meta_verbose ("Setting _NET_DESKTOP_GEOMETRY to %ld, %ld\n", data[0], data[1]);
@ -1212,10 +1207,7 @@ meta_screen_ensure_tab_popup (MetaScreen *screen,
if (!window->minimized || !meta_window_get_icon_geometry (window, &r))
meta_window_get_outer_rect (window, &r);
entries[i].x = r.x;
entries[i].y = r.y;
entries[i].width = r.width;
entries[i].height = r.height;
entries[i].rect = r;
/* Find inside of highlight rectangle to be used
* when window is outlined for tabbing.
@ -1229,19 +1221,19 @@ meta_screen_ensure_tab_popup (MetaScreen *screen,
int south = window->frame->rect.height - window->frame->child_y -
window->rect.height;
int east = window->frame->child_x;
entries[i].inner_x = east;
entries[i].inner_y = south;
entries[i].inner_width = window->rect.width;
entries[i].inner_height = window->frame->rect.height - south * 2;
entries[i].inner_rect.x = east;
entries[i].inner_rect.y = south;
entries[i].inner_rect.width = window->rect.width;
entries[i].inner_rect.height = window->frame->rect.height - south * 2;
}
else
{
/* Use an arbitrary border size */
#define OUTLINE_WIDTH 5
entries[i].inner_x = OUTLINE_WIDTH;
entries[i].inner_y = OUTLINE_WIDTH;
entries[i].inner_width = window->rect.width - OUTLINE_WIDTH * 2;
entries[i].inner_height = window->rect.height - OUTLINE_WIDTH * 2;
entries[i].inner_rect.x = OUTLINE_WIDTH;
entries[i].inner_rect.y = OUTLINE_WIDTH;
entries[i].inner_rect.width = window->rect.width - OUTLINE_WIDTH * 2;
entries[i].inner_rect.height = window->rect.height - OUTLINE_WIDTH * 2;
}
++i;
@ -1376,26 +1368,20 @@ meta_screen_get_xinerama_for_rect (MetaScreen *screen,
best_xinerama = 0;
xinerama_score = 0;
i = 0;
while (i < screen->n_xinerama_infos)
for (i = 0; i < screen->n_xinerama_infos; i++)
{
MetaRectangle dest, screen_info;
screen_info.x = screen->xinerama_infos[i].x_origin;
screen_info.y = screen->xinerama_infos[i].y_origin;
screen_info.width = screen->xinerama_infos[i].width;
screen_info.height = screen->xinerama_infos[i].height;
if (meta_rectangle_intersect (&screen_info, rect, &dest))
MetaRectangle dest;
if (meta_rectangle_intersect (&screen->xinerama_infos[i].rect,
rect,
&dest))
{
if (dest.width * dest.height > xinerama_score)
int cur = meta_rectangle_area (&dest);
if (cur > xinerama_score)
{
xinerama_score = dest.width * dest.height;
xinerama_score = cur;
best_xinerama = i;
}
}
++i;
}
return &screen->xinerama_infos[best_xinerama];
@ -1425,22 +1411,18 @@ meta_screen_get_xinerama_neighbor (MetaScreen *screen,
{
current = screen->xinerama_infos + i;
if (((direction == META_SCREEN_RIGHT) &&
(current->x_origin == input->x_origin + input->width) &&
(current->y_origin >= input->y_origin) &&
(current->y_origin <= input->y_origin+input->height)) ||
((direction == META_SCREEN_LEFT) &&
(input->x_origin == current->x_origin + current->width) &&
(current->y_origin >= input->y_origin) &&
(current->y_origin <= input->y_origin + input->height)) ||
((direction == META_SCREEN_UP) &&
(input->y_origin == current->y_origin + current->height) &&
(current->x_origin >= input->x_origin) &&
(current->x_origin <= input->x_origin + input->width)) ||
((direction == META_SCREEN_DOWN) &&
(current->y_origin == input->y_origin + input->height) &&
(current->x_origin >= input->x_origin) &&
(current->x_origin <= input->x_origin + input->width)))
if ((direction == META_SCREEN_RIGHT &&
current->rect.x == input->rect.x + input->rect.width &&
meta_rectangle_vert_overlap(&current->rect, &input->rect)) ||
(direction == META_SCREEN_LEFT &&
input->rect.x == current->rect.x + current->rect.width &&
meta_rectangle_vert_overlap(&current->rect, &input->rect)) ||
(direction == META_SCREEN_UP &&
input->rect.y == current->rect.y + current->rect.height &&
meta_rectangle_horiz_overlap(&current->rect, &input->rect)) ||
(direction == META_SCREEN_DOWN &&
current->rect.y == input->rect.y + input->rect.height &&
meta_rectangle_horiz_overlap(&current->rect, &input->rect)))
{
return current;
}
@ -1544,24 +1526,6 @@ meta_screen_get_natural_xinerama_list (MetaScreen *screen,
g_queue_free (xinerama_queue);
}
gboolean
meta_screen_rect_intersects_xinerama (MetaScreen *screen,
MetaRectangle *rect,
int which_xinerama)
{
MetaRectangle dest, screen_rect;
screen_rect.x = screen->xinerama_infos[which_xinerama].x_origin;
screen_rect.y = screen->xinerama_infos[which_xinerama].y_origin;
screen_rect.width = screen->xinerama_infos[which_xinerama].width;
screen_rect.height = screen->xinerama_infos[which_xinerama].height;
if (meta_rectangle_intersect (&screen_rect, rect, &dest))
return TRUE;
return FALSE;
}
const MetaXineramaScreenInfo*
meta_screen_get_current_xinerama (MetaScreen *screen)
{
@ -1574,39 +1538,33 @@ meta_screen_get_current_xinerama (MetaScreen *screen)
if (screen->display->xinerama_cache_invalidated)
{
Window root_return, child_return;
int root_x_return, root_y_return;
int win_x_return, win_y_return;
unsigned int mask_return;
int i;
MetaRectangle pointer_position;
screen->display->xinerama_cache_invalidated = FALSE;
pointer_position.width = pointer_position.height = 1;
XQueryPointer (screen->display->xdisplay,
screen->xroot,
&root_return,
&child_return,
&root_x_return,
&root_y_return,
&pointer_position.x,
&pointer_position.y,
&win_x_return,
&win_y_return,
&mask_return);
screen->last_xinerama_index = 0;
i = 0;
while (i < screen->n_xinerama_infos)
for (i = 0; i < screen->n_xinerama_infos; i++)
{
if ((root_x_return >= screen->xinerama_infos[i].x_origin &&
root_x_return < (screen->xinerama_infos[i].x_origin +
screen->xinerama_infos[i].width) &&
root_y_return >= screen->xinerama_infos[i].y_origin &&
root_y_return < (screen->xinerama_infos[i].y_origin +
screen->xinerama_infos[i].height)))
{
screen->last_xinerama_index = i;
break;
}
++i;
if (meta_rectangle_contains_rect (&screen->xinerama_infos[i].rect,
&pointer_position))
{
screen->last_xinerama_index = i;
break;
}
}
meta_topic (META_DEBUG_XINERAMA,
@ -2201,8 +2159,8 @@ meta_screen_resize (MetaScreen *screen,
int width,
int height)
{
screen->width = width;
screen->height = height;
screen->rect.width = width;
screen->rect.height = height;
reload_xinerama_infos (screen);
set_desktop_geometry_hint (screen);

View File

@ -3,7 +3,7 @@
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004 Elijah Newren
* Copyright (C) 2004, 2005 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
@ -33,10 +33,7 @@ typedef struct _MetaXineramaScreenInfo MetaXineramaScreenInfo;
struct _MetaXineramaScreenInfo
{
int number;
int x_origin;
int y_origin;
int width;
int height;
MetaRectangle rect;
};
typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window,
@ -69,8 +66,7 @@ struct _MetaScreen
Window xroot;
int default_depth;
Visual *default_xvisual;
int width;
int height;
MetaRectangle rect; /* Size of screen; rect.x & rect.y are always 0 */
MetaUI *ui;
MetaTabPopup *tab_popup;
@ -158,9 +154,6 @@ const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_rect (MetaScreen
const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_window (MetaScreen *screen,
MetaWindow *window);
gboolean meta_screen_rect_intersects_xinerama (MetaScreen *screen,
MetaRectangle *window,
int which_xinerama);
const MetaXineramaScreenInfo* meta_screen_get_xinerama_neighbor (MetaScreen *screen,
int which_xinerama,

View File

@ -3,7 +3,7 @@
/*
* Copyright (C) 2001 Havoc Pennington (some code in here from
* libgnomeui, (C) Tom Tromey, Carsten Schaar)
* Copyright (C) 2004 Elijah Newren
* Copyright (C) 2004, 2005 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
@ -728,47 +728,6 @@ window_type_from_string (const char *str)
return META_WINDOW_NORMAL;
}
static const char*
window_gravity_to_string (int gravity)
{
switch (gravity)
{
case NorthWestGravity:
return "NorthWestGravity";
break;
case NorthGravity:
return "NorthGravity";
break;
case NorthEastGravity:
return "NorthEastGravity";
break;
case WestGravity:
return "WestGravity";
break;
case CenterGravity:
return "CenterGravity";
break;
case EastGravity:
return "EastGravity";
break;
case SouthWestGravity:
return "SouthWestGravity";
break;
case SouthGravity:
return "SouthGravity";
break;
case SouthEastGravity:
return "SouthEastGravity";
break;
case StaticGravity:
return "StaticGravity";
break;
default:
return "NorthWestGravity";
break;
}
}
static int
window_gravity_from_string (const char *str)
{
@ -995,7 +954,7 @@ save_state (void)
fputs (" <minimized/>\n", outfile);
/* Maximized */
if (window->maximized)
if (META_WINDOW_MAXIMIZED (window))
{
fprintf (outfile,
" <maximized saved_x=\"%d\" saved_y=\"%d\" saved_width=\"%d\" saved_height=\"%d\"/>\n",
@ -1021,7 +980,7 @@ save_state (void)
fprintf (outfile,
" <geometry x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" gravity=\"%s\"/>\n",
x, y, w, h,
window_gravity_to_string (window->size_hints.win_gravity));
meta_gravity_to_string (window->size_hints.win_gravity));
}
fputs (" </window>\n", outfile);
@ -1480,7 +1439,7 @@ start_element_handler (GMarkupParseContext *context,
pd->info->rect.y,
pd->info->rect.width,
pd->info->rect.height,
window_gravity_to_string (pd->info->gravity));
meta_gravity_to_string (pd->info->gravity));
}
else
{

View File

@ -201,8 +201,7 @@ window_is_fullscreen_size (MetaWindow *window)
{
int i;
if (window->rect.width >= window->screen->width &&
window->rect.height >= window->screen->height)
if (meta_rectangle_could_fit_rect (&window->rect, &window->screen->rect))
{
/* we use the work area since windows that try to
* position at 0,0 will get pushed down by menu panel
@ -210,26 +209,20 @@ window_is_fullscreen_size (MetaWindow *window)
MetaRectangle workarea;
meta_window_get_work_area_current_xinerama (window, &workarea);
if (window->rect.x <= workarea.x &&
window->rect.y <= workarea.y &&
window->rect.x + window->rect.width >= workarea.x + workarea.width &&
window->rect.y + window->rect.height >= workarea.y + workarea.height)
if (meta_rectangle_contains_rect (&window->rect, &workarea))
return TRUE;
}
i = 0;
while (i < window->screen->n_xinerama_infos)
{
if (window->rect.width >= window->screen->xinerama_infos[i].width &&
window->rect.height >= window->screen->xinerama_infos[i].height)
if (meta_rectangle_could_fit_rect (&window->rect,
&window->screen->xinerama_infos[i].rect))
{
MetaRectangle workarea;
meta_window_get_work_area_current_xinerama (window, &workarea);
if (window->rect.x <= workarea.x &&
window->rect.y <= workarea.y &&
window->rect.x + window->rect.width >= workarea.x + workarea.width &&
window->rect.y + window->rect.height >= workarea.y + workarea.height)
if (meta_rectangle_contains_rect (&window->rect, &workarea))
return TRUE;
}

View File

@ -241,15 +241,15 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries,
if (outline)
{
te->rect.x = entries[i].x;
te->rect.y = entries[i].y;
te->rect.width = entries[i].width;
te->rect.height = entries[i].height;
te->rect.x = entries[i].rect.x;
te->rect.y = entries[i].rect.y;
te->rect.width = entries[i].rect.width;
te->rect.height = entries[i].rect.height;
te->inner_rect.x = entries[i].inner_x;
te->inner_rect.y = entries[i].inner_y;
te->inner_rect.width = entries[i].inner_width;
te->inner_rect.height = entries[i].inner_height;
te->inner_rect.x = entries[i].inner_rect.x;
te->inner_rect.y = entries[i].inner_rect.y;
te->inner_rect.width = entries[i].inner_rect.width;
te->inner_rect.height = entries[i].inner_rect.height;
}
tab_entries = g_list_prepend (tab_entries, te);
@ -739,7 +739,8 @@ selectable_workspace_new (MetaWorkspace *workspace)
widget = g_object_new (meta_select_workspace_get_type (), NULL);
screen_aspect = (double) workspace->screen->height / (double) workspace->screen->width;
screen_aspect = (double) workspace->screen->rect.height /
(double) workspace->screen->rect.width;
/* account for select rect */
gtk_widget_set_size_request (widget,
@ -893,8 +894,8 @@ meta_select_workspace_expose_event (GtkWidget *widget,
SELECT_OUTLINE_WIDTH,
widget->allocation.width - SELECT_OUTLINE_WIDTH * 2,
widget->allocation.height - SELECT_OUTLINE_WIDTH * 2,
workspace->screen->width,
workspace->screen->height,
workspace->screen->rect.width,
workspace->screen->rect.height,
NULL,
(workspace->screen->active_workspace == workspace),
windows,

View File

@ -2,6 +2,7 @@
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2005 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
@ -24,6 +25,7 @@
/* Don't include gtk.h or gdk.h here */
#include "common.h"
#include "boxes.h"
#include <X11/Xlib.h>
#include <glib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
@ -37,8 +39,8 @@ struct _MetaTabEntry
MetaTabEntryKey key;
const char *title;
GdkPixbuf *icon;
int x, y, width, height;
int inner_x, inner_y, inner_width, inner_height;
MetaRectangle rect;
MetaRectangle inner_rect;
guint blank : 1;
guint hidden : 1;
guint demands_attention : 1;

1400
src/testboxes.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -29,6 +29,7 @@
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <X11/Xutil.h> /* Just for the definition of the various gravities */
#ifdef HAVE_BACKTRACE
#include <execinfo.h>
@ -464,3 +465,44 @@ meta_unsigned_long_hash (gconstpointer v)
return val;
#endif
}
const char*
meta_gravity_to_string (int gravity)
{
switch (gravity)
{
case NorthWestGravity:
return "NorthWestGravity";
break;
case NorthGravity:
return "NorthGravity";
break;
case NorthEastGravity:
return "NorthEastGravity";
break;
case WestGravity:
return "WestGravity";
break;
case CenterGravity:
return "CenterGravity";
break;
case EastGravity:
return "EastGravity";
break;
case SouthWestGravity:
return "SouthWestGravity";
break;
case SouthGravity:
return "SouthGravity";
break;
case SouthEastGravity:
return "SouthEastGravity";
break;
case StaticGravity:
return "StaticGravity";
break;
default:
return "NorthWestGravity";
break;
}
}

View File

@ -85,6 +85,8 @@ guint meta_unsigned_long_hash (gconstpointer v);
void meta_print_backtrace (void);
const char* meta_gravity_to_string (int gravity);
#include <libintl.h>
#define _(x) dgettext (GETTEXT_PACKAGE, x)
#define N_(x) x

File diff suppressed because it is too large Load Diff

View File

@ -52,6 +52,12 @@ typedef enum
META_WINDOW_SPLASHSCREEN
} MetaWindowType;
typedef enum
{
META_MAXIMIZE_HORIZONTAL = 1 << 0,
META_MAXIMIZE_VERTICAL = 1 << 1
} MetaMaximizeFlags;
struct _MetaStruts
{
/* struts */
@ -108,8 +114,10 @@ struct _MetaWindow
Time initial_timestamp;
/* Whether we're maximized */
guint maximized : 1;
guint maximize_after_placement : 1;
guint maximized_horizontally : 1;
guint maximized_vertically : 1;
guint maximize_horizontally_after_placement : 1;
guint maximize_vertically_after_placement : 1;
/* Whether we're shaded */
guint shaded : 1;
@ -117,6 +125,12 @@ struct _MetaWindow
/* Whether we're fullscreen */
guint fullscreen : 1;
/* Whether we're trying to constrain the window to be fully onscreen */
guint require_fully_onscreen : 1;
/* Whether we're trying to constrain the window to be on a single xinerama */
guint require_on_single_xinerama : 1;
/* Whether we're sticky in the multi-workspace sense
* (vs. the not-scroll-with-viewport sense, we don't
* have no stupid viewports)
@ -287,25 +301,29 @@ struct _MetaWindow
/* The size we set the window to last (i.e. what we believe
* to be its actual size on the server). The x, y are
* the actual server-side x,y so are relative to the frame
* or the root window as appropriate.
* (meaning that they just hold the frame width and height)
* or the root window (meaning they specify the location
* of the top left of the inner window) as appropriate.
*/
MetaRectangle rect;
/* The geometry to restore when we unmaximize.
* The position is in root window coords, even if
* there's a frame, which contrasts with window->rect
* above.
/* The geometry to restore when we unmaximize. The position is in
* root window coords, even if there's a frame, which contrasts with
* window->rect above. Note that this gives the position and size
* of the client window (i.e. ignoring the frame).
*/
MetaRectangle saved_rect;
/* This is the geometry the window had after the last user-initiated
* move/resize operations. We use this whenever we are moving the
* implicitly (for example, if we move to avoid a panel, we
* can snap back to this position if the panel moves again)
* implicitly (for example, if we move to avoid a panel, we can snap
* back to this position if the panel moves again). Note that this
* gives the position and size of the client window (i.e. ignoring
* the frame).
*
* Position valid if user_has_moved, size valid if user_has_resized
*
* Position always in root coords, unlike window->rect
* Position always in root coords, unlike window->rect.
*/
MetaRectangle user_rect;
@ -330,8 +348,10 @@ struct _MetaWindow
* the dynamic window state such as "maximized", not just the
* window's type
*/
#define META_WINDOW_MAXIMIZED(w) ((w)->maximized_horizontally && \
(w)->maximized_vertically)
#define META_WINDOW_ALLOWS_MOVE(w) ((w)->has_move_func && !(w)->fullscreen)
#define META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS(w) ((w)->has_resize_func && !(w)->maximized && !(w)->fullscreen && !(w)->shaded)
#define META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS(w) ((w)->has_resize_func && !META_WINDOW_MAXIMIZED (w) && !(w)->fullscreen && !(w)->shaded)
#define META_WINDOW_ALLOWS_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) && \
(((w)->size_hints.min_width < (w)->size_hints.max_width) || \
((w)->size_hints.min_height < (w)->size_hints.max_height)))
@ -350,10 +370,13 @@ void meta_window_calc_showing (MetaWindow *window);
void meta_window_queue_calc_showing (MetaWindow *window);
void meta_window_minimize (MetaWindow *window);
void meta_window_unminimize (MetaWindow *window);
void meta_window_maximize (MetaWindow *window);
void meta_window_maximize_internal (MetaWindow *window,
MetaRectangle *saved_rect);
void meta_window_unmaximize (MetaWindow *window);
void meta_window_maximize (MetaWindow *window,
MetaMaximizeFlags directions);
void meta_window_maximize_internal (MetaWindow *window,
MetaMaximizeFlags directions,
MetaRectangle *saved_rect);
void meta_window_unmaximize (MetaWindow *window,
MetaMaximizeFlags directions);
void meta_window_make_above (MetaWindow *window);
void meta_window_unmake_above (MetaWindow *window);
void meta_window_shade (MetaWindow *window);
@ -390,9 +413,6 @@ void meta_window_resize_with_gravity (MetaWindow *window,
int gravity);
void meta_window_fill_horizontal (MetaWindow *window);
void meta_window_fill_vertical (MetaWindow *window);
/* Return whether the window would be showing if we were on its workspace */
gboolean meta_window_showing_on_its_workspace (MetaWindow *window);
@ -477,6 +497,9 @@ void meta_window_show_menu (MetaWindow *window,
int button,
Time timestamp);
gboolean meta_window_titlebar_is_onscreen (MetaWindow *window);
void meta_window_shove_titlebar_onscreen (MetaWindow *window);
void meta_window_set_gravity (MetaWindow *window,
int gravity);

View File

@ -57,17 +57,19 @@ meta_workspace_new (MetaScreen *screen)
workspace->mru_list = NULL;
meta_screen_foreach_window (screen, maybe_add_to_list, &workspace->mru_list);
workspace->work_areas = NULL;
workspace->work_areas_invalid = TRUE;
workspace->all_work_areas.x = 0;
workspace->all_work_areas.y = 0;
workspace->all_work_areas.width = 0;
workspace->all_work_areas.height = 0;
workspace->work_area_xinerama = NULL;
workspace->work_area_screen.x = 0;
workspace->work_area_screen.y = 0;
workspace->work_area_screen.width = 0;
workspace->work_area_screen.height = 0;
workspace->left_struts = NULL;
workspace->right_struts = NULL;
workspace->top_struts = NULL;
workspace->bottom_struts = NULL;
workspace->screen_region = NULL;
workspace->xinerama_region = NULL;
workspace->screen_edges = NULL;
workspace->xinerama_edges = NULL;
workspace->all_struts = NULL;
workspace->showing_desktop = FALSE;
@ -79,6 +81,7 @@ meta_workspace_free (MetaWorkspace *workspace)
{
GList *tmp;
MetaScreen *screen;
int i;
g_return_if_fail (workspace != workspace->screen->active_workspace);
@ -107,13 +110,17 @@ meta_workspace_free (MetaWorkspace *workspace)
workspace->screen->workspaces =
g_list_remove (workspace->screen->workspaces, workspace);
g_free (workspace->work_areas);
g_free (workspace->work_area_xinerama);
g_list_free (workspace->mru_list);
g_slist_free (workspace->left_struts);
g_slist_free (workspace->right_struts);
g_slist_free (workspace->top_struts);
g_slist_free (workspace->bottom_struts);
g_slist_free (workspace->all_struts);
for (i = 0; i < screen->n_xinerama_infos; i++)
meta_rectangle_free_list_and_elements (workspace->xinerama_region[i]);
g_free (workspace->xinerama_region);
meta_rectangle_free_list_and_elements (workspace->screen_region);
meta_rectangle_free_list_and_elements (workspace->screen_edges);
meta_rectangle_free_list_and_elements (workspace->xinerama_edges);
g_free (workspace);
@ -429,6 +436,7 @@ meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
{
GList *tmp;
GList *windows;
int i;
if (workspace->work_areas_invalid)
{
@ -442,17 +450,22 @@ meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
"Invalidating work area for workspace %d\n",
meta_workspace_index (workspace));
g_free (workspace->work_areas);
workspace->work_areas = NULL;
g_free (workspace->work_area_xinerama);
workspace->work_area_xinerama = NULL;
g_slist_free (workspace->left_struts);
workspace->left_struts = NULL;
g_slist_free (workspace->right_struts);
workspace->right_struts = NULL;
g_slist_free (workspace->top_struts);
workspace->top_struts = NULL;
g_slist_free (workspace->bottom_struts);
workspace->bottom_struts = NULL;
g_slist_free (workspace->all_struts);
workspace->all_struts = NULL;
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
meta_rectangle_free_list_and_elements (workspace->xinerama_region[i]);
g_free (workspace->xinerama_region);
meta_rectangle_free_list_and_elements (workspace->screen_region);
meta_rectangle_free_list_and_elements (workspace->screen_edges);
meta_rectangle_free_list_and_elements (workspace->xinerama_edges);
workspace->xinerama_region = NULL;
workspace->screen_region = NULL;
workspace->screen_edges = NULL;
workspace->xinerama_edges = NULL;
workspace->work_areas_invalid = TRUE;
@ -491,16 +504,17 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
if (!workspace->work_areas_invalid)
return;
g_assert (workspace->top_struts == NULL);
g_assert (workspace->bottom_struts == NULL);
g_assert (workspace->left_struts == NULL);
g_assert (workspace->right_struts == NULL);
g_assert (workspace->all_struts == NULL);
g_assert (workspace->xinerama_region == NULL);
g_assert (workspace->screen_region == NULL);
g_assert (workspace->screen_edges == NULL);
g_assert (workspace->xinerama_edges == NULL);
windows = meta_workspace_list_windows (workspace);
g_free (workspace->work_areas);
workspace->work_areas = g_new (MetaRectangle,
workspace->screen->n_xinerama_infos);
g_free (workspace->work_area_xinerama);
workspace->work_area_xinerama = g_new (MetaRectangle,
workspace->screen->n_xinerama_infos);
i = 0;
while (i < workspace->screen->n_xinerama_infos)
@ -528,67 +542,63 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
if ((i == 0) && (w->struts->left.width > 0))
{
workspace->left_struts = g_slist_prepend (workspace->left_struts,
&w->struts->left);
workspace->all_struts = g_slist_prepend (workspace->all_struts,
&w->struts->left);
}
if (meta_screen_rect_intersects_xinerama (w->screen,
&w->struts->left,
i))
if (meta_rectangle_overlap (&w->screen->xinerama_infos[i].rect,
&w->struts->left))
{
left_strut = MAX (left_strut,
w->struts->left.width -
workspace->screen->xinerama_infos[i].x_origin);
workspace->screen->xinerama_infos[i].rect.x);
all_left_strut = MAX (all_left_strut, w->struts->left.width);
}
if ((i == 0) && (w->struts->right.width > 0))
{
workspace->right_struts = g_slist_prepend (workspace->right_struts,
&w->struts->right);
workspace->all_struts = g_slist_prepend (workspace->all_struts,
&w->struts->right);
}
if (meta_screen_rect_intersects_xinerama (w->screen,
&w->struts->right,
i))
if (meta_rectangle_overlap (&w->screen->xinerama_infos[i].rect,
&w->struts->right))
{
right_strut = MAX (right_strut, w->struts->right.width -
workspace->screen->width +
workspace->screen->xinerama_infos[i].width +
workspace->screen->xinerama_infos[i].x_origin);
workspace->screen->rect.width +
workspace->screen->xinerama_infos[i].rect.width +
workspace->screen->xinerama_infos[i].rect.x);
all_right_strut = MAX (all_right_strut, w->struts->right.width);
}
if ((i == 0) && (w->struts->top.height > 0))
{
workspace->top_struts = g_slist_prepend (workspace->top_struts,
workspace->all_struts = g_slist_prepend (workspace->all_struts,
&w->struts->top);
}
if (meta_screen_rect_intersects_xinerama (w->screen,
&w->struts->top,
i))
if (meta_rectangle_overlap (&w->screen->xinerama_infos[i].rect,
&w->struts->top))
{
top_strut = MAX (top_strut,
w->struts->top.height -
workspace->screen->xinerama_infos[i].y_origin);
workspace->screen->xinerama_infos[i].rect.y);
all_top_strut = MAX (all_top_strut, w->struts->top.height);
}
if ((i == 0) && (w->struts->bottom.height > 0))
{
workspace->bottom_struts = g_slist_prepend (workspace->bottom_struts,
&w->struts->bottom);
workspace->all_struts = g_slist_prepend (workspace->all_struts,
&w->struts->bottom);
}
if (meta_screen_rect_intersects_xinerama (w->screen,
&w->struts->bottom,
i))
if (meta_rectangle_overlap (&w->screen->xinerama_infos[i].rect,
&w->struts->bottom))
{
bottom_strut = MAX (bottom_strut, w->struts->bottom.height -
workspace->screen->height +
workspace->screen->xinerama_infos[i].height +
workspace->screen->xinerama_infos[i].y_origin);
workspace->screen->rect.height +
workspace->screen->xinerama_infos[i].rect.height +
workspace->screen->xinerama_infos[i].rect.y);
all_bottom_strut = MAX (all_bottom_strut, w->struts->bottom.height);
}
}
@ -600,36 +610,36 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
#define MIN_SANE_AREA 100
if ((left_strut + right_strut) >
(workspace->screen->xinerama_infos[i].width - MIN_SANE_AREA))
(workspace->screen->xinerama_infos[i].rect.width - MIN_SANE_AREA))
{
meta_topic (META_DEBUG_WORKAREA,
"Making left/right struts %d %d sane xinerama %d\n",
left_strut, right_strut, i);
left_strut = (workspace->screen->xinerama_infos[i].width -
left_strut = (workspace->screen->xinerama_infos[i].rect.width -
MIN_SANE_AREA) / 2;
right_strut = left_strut;
}
if ((top_strut + bottom_strut) >
(workspace->screen->xinerama_infos[i].height - MIN_SANE_AREA))
(workspace->screen->xinerama_infos[i].rect.height - MIN_SANE_AREA))
{
meta_topic (META_DEBUG_WORKAREA,
"Making top/bottom struts %d %d sane xinerama %d\n",
top_strut, bottom_strut, i);
top_strut = (workspace->screen->xinerama_infos[i].height -
top_strut = (workspace->screen->xinerama_infos[i].rect.height -
MIN_SANE_AREA) / 2;
bottom_strut = top_strut;
}
workspace->work_areas[i].x =
left_strut + workspace->screen->xinerama_infos[i].x_origin;
workspace->work_areas[i].y = top_strut +
workspace->screen->xinerama_infos[i].y_origin;
workspace->work_areas[i].width =
workspace->screen->xinerama_infos[i].width -
workspace->work_area_xinerama[i].x =
left_strut + workspace->screen->xinerama_infos[i].rect.x;
workspace->work_area_xinerama[i].y = top_strut +
workspace->screen->xinerama_infos[i].rect.y;
workspace->work_area_xinerama[i].width =
workspace->screen->xinerama_infos[i].rect.width -
left_strut - right_strut;
workspace->work_areas[i].height =
workspace->screen->xinerama_infos[i].height -
workspace->work_area_xinerama[i].height =
workspace->screen->xinerama_infos[i].rect.height -
top_strut - bottom_strut;
meta_topic (META_DEBUG_WORKAREA,
@ -637,10 +647,10 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
"xinerama %d: %d,%d %d x %d\n",
meta_workspace_index (workspace),
i,
workspace->work_areas[i].x,
workspace->work_areas[i].y,
workspace->work_areas[i].width,
workspace->work_areas[i].height);
workspace->work_area_xinerama[i].x,
workspace->work_area_xinerama[i].y,
workspace->work_area_xinerama[i].width,
workspace->work_area_xinerama[i].height);
++i;
}
@ -648,41 +658,91 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
g_list_free (windows);
if ((all_left_strut + all_right_strut) >
(workspace->screen->width - MIN_SANE_AREA))
(workspace->screen->rect.width - MIN_SANE_AREA))
{
meta_topic (META_DEBUG_WORKAREA,
"Making screen-wide left/right struts %d %d sane\n",
all_left_strut, all_right_strut);
all_left_strut = (workspace->screen->width - MIN_SANE_AREA) / 2;
all_left_strut = (workspace->screen->rect.width - MIN_SANE_AREA) / 2;
all_right_strut = all_left_strut;
}
if ((all_top_strut + all_bottom_strut) >
(workspace->screen->height - MIN_SANE_AREA))
(workspace->screen->rect.height - MIN_SANE_AREA))
{
meta_topic (META_DEBUG_WORKAREA,
"Making top/bottom struts %d %d sane\n",
all_top_strut, all_bottom_strut);
all_top_strut = (workspace->screen->height - MIN_SANE_AREA) / 2;
all_top_strut = (workspace->screen->rect.height - MIN_SANE_AREA) / 2;
all_bottom_strut = all_top_strut;
}
workspace->all_work_areas.x = all_left_strut;
workspace->all_work_areas.y = all_top_strut;
workspace->all_work_areas.width =
workspace->screen->width - all_left_strut - all_right_strut;
workspace->all_work_areas.height =
workspace->screen->height - all_top_strut - all_bottom_strut;
workspace->work_area_screen.x = all_left_strut;
workspace->work_area_screen.y = all_top_strut;
workspace->work_area_screen.width =
workspace->screen->rect.width - all_left_strut - all_right_strut;
workspace->work_area_screen.height =
workspace->screen->rect.height - all_top_strut - all_bottom_strut;
/* Now cache the spanning rects for the onscreen and
* on-single-xinerama regions
*/
g_assert (workspace->xinerama_region == NULL);
g_assert (workspace->screen_region == NULL);
workspace->xinerama_region = g_new (GList*,
workspace->screen->n_xinerama_infos);
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
{
workspace->xinerama_region[i] =
meta_rectangle_get_minimal_spanning_set_for_region (
&workspace->screen->xinerama_infos[i].rect,
workspace->all_struts);
}
workspace->screen_region =
meta_rectangle_get_minimal_spanning_set_for_region (
&workspace->screen->rect,
workspace->all_struts);
/* Since get_minimal_spanning_set_for_region() doesn't do the
* MIN_SANE_AREA thing, manually account for it. Note that it's okay if
* get_minimal_spanning_set_for_region() returns a very small region--all
* we really need here is a 1x1 region that corresponds to somewhere on
* the monitor for the partially onscreen constraint. If we don't get
* anything, though, we use work_area_screen just for convenience.
*/
if (workspace->screen_region == NULL)
{
MetaRectangle *nonempty_region;
nonempty_region = g_new (MetaRectangle, 1);
*nonempty_region = workspace->work_area_screen;
workspace->screen_region = g_list_prepend (NULL, nonempty_region);
}
/* Now cache the screen and xinerama edges for edge resistance and snapping */
g_assert (workspace->screen_edges == NULL);
g_assert (workspace->xinerama_edges == NULL);
workspace->screen_edges =
meta_rectangle_find_onscreen_edges (&workspace->screen->rect,
workspace->all_struts);
tmp = NULL;
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
tmp = g_list_prepend (tmp, &workspace->screen->xinerama_infos[i].rect);
workspace->xinerama_edges =
meta_rectangle_find_nonintersected_xinerama_edges (tmp,
workspace->all_struts);
g_list_free (tmp);
/* We're all done, YAAY! Record that everything has been validated. */
workspace->work_areas_invalid = FALSE;
meta_topic (META_DEBUG_WORKAREA,
"Computed work area for workspace %d: %d,%d %d x %d\n",
meta_workspace_index (workspace),
workspace->all_work_areas.x,
workspace->all_work_areas.y,
workspace->all_work_areas.width,
workspace->all_work_areas.height);
workspace->work_area_screen.x,
workspace->work_area_screen.y,
workspace->work_area_screen.width,
workspace->work_area_screen.height);
}
void
@ -695,7 +755,7 @@ meta_workspace_get_work_area_for_xinerama (MetaWorkspace *workspace,
ensure_work_areas_validated (workspace);
g_assert (which_xinerama < workspace->screen->n_xinerama_infos);
*area = workspace->work_areas[which_xinerama];
*area = workspace->work_area_xinerama[which_xinerama];
}
void
@ -704,7 +764,24 @@ meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace,
{
ensure_work_areas_validated (workspace);
*area = workspace->all_work_areas;
*area = workspace->work_area_screen;
}
GList*
meta_workspace_get_onscreen_region (MetaWorkspace *workspace)
{
ensure_work_areas_validated (workspace);
return workspace->screen_region;
}
GList*
meta_workspace_get_onxinerama_region (MetaWorkspace *workspace,
int which_xinerama)
{
ensure_work_areas_validated (workspace);
return workspace->xinerama_region[which_xinerama];
}
#ifdef WITH_VERBOSE_MODE

View File

@ -2,7 +2,7 @@
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2004 Elijah Newren
* Copyright (C) 2004, 2005 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
@ -43,12 +43,13 @@ struct _MetaWorkspace
GList *windows;
GList *mru_list;
MetaRectangle all_work_areas;
MetaRectangle *work_areas;
GSList *left_struts;
GSList *right_struts;
GSList *top_struts;
GSList *bottom_struts;
MetaRectangle work_area_screen;
MetaRectangle *work_area_xinerama;
GList *screen_region;
GList **xinerama_region;
GList *screen_edges;
GList *xinerama_edges;
GSList *all_struts;
guint work_areas_invalid : 1;
guint showing_desktop : 1;
@ -78,6 +79,11 @@ void meta_workspace_get_work_area_for_xinerama (MetaWorkspace *workspace,
MetaRectangle *area);
void meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace,
MetaRectangle *area);
GList* meta_workspace_get_onscreen_region (MetaWorkspace *workspace);
GList* meta_workspace_get_onxinerama_region (MetaWorkspace *workspace,
int which_xinerama);
void meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace,
MetaRectangle *area);
void meta_workspace_focus_default_window (MetaWorkspace *workspace,
MetaWindow *not_this_one,