mirror of
https://github.com/brl/mutter.git
synced 2025-06-13 16:59:30 +00:00
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:

committed by
Elijah Newren

parent
cfb3bd081a
commit
a7201d27d1
@ -5,6 +5,7 @@ Makefile
|
||||
metacity
|
||||
metacity-theme-viewer
|
||||
metacity-dialog
|
||||
testboxes
|
||||
testgradient
|
||||
inlinepixbufs.h
|
||||
metacity.desktop
|
||||
|
@ -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@
|
||||
|
||||
|
@ -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
1745
src/boxes.c
Normal file
File diff suppressed because it is too large
Load Diff
239
src/boxes.h
Normal file
239
src/boxes.h
Normal 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 */
|
24
src/common.h
24
src/common.h
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
2445
src/constraints.c
2445
src/constraints.c
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
40
src/core.c
40
src/core.c
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
143
src/display.c
143
src/display.c
@ -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,
|
||||
|
@ -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
1278
src/edge-resistance.c
Normal file
File diff suppressed because it is too large
Load Diff
46
src/edge-resistance.h
Normal file
46
src/edge-resistance.h
Normal 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 */
|
||||
|
@ -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)
|
||||
|
30
src/frames.c
30
src/frames.c
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
111
src/place.c
111
src/place.c
@ -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;
|
||||
|
182
src/screen.c
182
src/screen.c
@ -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(¤t->rect, &input->rect)) ||
|
||||
(direction == META_SCREEN_LEFT &&
|
||||
input->rect.x == current->rect.x + current->rect.width &&
|
||||
meta_rectangle_vert_overlap(¤t->rect, &input->rect)) ||
|
||||
(direction == META_SCREEN_UP &&
|
||||
input->rect.y == current->rect.y + current->rect.height &&
|
||||
meta_rectangle_horiz_overlap(¤t->rect, &input->rect)) ||
|
||||
(direction == META_SCREEN_DOWN &&
|
||||
current->rect.y == input->rect.y + input->rect.height &&
|
||||
meta_rectangle_horiz_overlap(¤t->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);
|
||||
|
13
src/screen.h
13
src/screen.h
@ -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,
|
||||
|
@ -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
|
||||
{
|
||||
|
17
src/stack.c
17
src/stack.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
1400
src/testboxes.c
Normal file
File diff suppressed because it is too large
Load Diff
42
src/util.c
42
src/util.c
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
1083
src/window.c
1083
src/window.c
File diff suppressed because it is too large
Load Diff
59
src/window.h
59
src/window.h
@ -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);
|
||||
|
||||
|
259
src/workspace.c
259
src/workspace.c
@ -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
|
||||
|
@ -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,
|
||||
|
Reference in New Issue
Block a user