mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 15:40:41 -05: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:
parent
cfb3bd081a
commit
a7201d27d1
@ -15,6 +15,7 @@ ltconfig
|
||||
ltmain.sh
|
||||
stamp-h
|
||||
stamp-h.in
|
||||
stamp-h1
|
||||
stamp.h
|
||||
version.h
|
||||
config.h.in
|
||||
|
111
ChangeLog
111
ChangeLog
@ -1,3 +1,114 @@
|
||||
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()
|
||||
|
||||
2005-11-14 Elijah Newren <newren@gmail.com>
|
||||
|
||||
* configure.in: post-release version bump to 2.13.2
|
||||
|
283
doc/how-constraints-works.txt
Normal file
283
doc/how-constraints-works.txt
Normal file
@ -0,0 +1,283 @@
|
||||
File contents:
|
||||
Basic Ideas
|
||||
Important points to remember
|
||||
Explanation of fields in the ConstraintInfo struct
|
||||
Gory details of resize_gravity vs. fixed_directions
|
||||
|
||||
IMPORTANT NOTE: There's a big comment at the top of constraints.c
|
||||
explaining how to add extra constraints or tweak others. Read it. I put
|
||||
that information there because it may be enough information by itself for
|
||||
people to hack on constraints.c. I won't duplicate that information in
|
||||
this file; this file is for deeper details.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
Basic Ideas
|
||||
---------------------------------------------------------------------------
|
||||
There are a couple basic ideas behind how this constraints.c code works and
|
||||
why it works that way:
|
||||
|
||||
1) Split the low-level error-prone operations into a special file
|
||||
2) Add robustness by prioritizing constraints
|
||||
3) Make use of a minimal spanning set of rectangles for the
|
||||
"onscreen region" (screen minus struts).
|
||||
4) Constraints can be user-action vs app-action oriented
|
||||
5) Avoid over-complification ;-)
|
||||
|
||||
Some more details explaining these basic ideas:
|
||||
|
||||
1) Split tedious operations out
|
||||
|
||||
boxes.[ch] have been added which contain many common, tedious, and
|
||||
error-prone operations. I find that this separation helps a lot for
|
||||
managing the complexity and ensuring that things work correctly.
|
||||
Also, note that testboxes.c thoroughly tests all functionality in
|
||||
boxes.[ch] and a testboxes program is automatically compiled.
|
||||
|
||||
Note that functions have also been added to this file to handle some
|
||||
of the tedium necessary for edge resistance as well.
|
||||
|
||||
2) Prioritize constraints
|
||||
|
||||
In the old code, if each and every constraint could not be
|
||||
simultaneously satisfied, then it would result in some
|
||||
difficult-to-predict set of constraints being violated. This was
|
||||
because constraints were applied in order, with the possibility for
|
||||
each making changes that violated previous constraints, with no
|
||||
checking done at the end.
|
||||
|
||||
Now, all constraints have an associated priority, defined in the
|
||||
ConstraintPriority enum near the top of constraints.c. The
|
||||
constraints are all applied, and then are all checked; if not all are
|
||||
satisfied then the least important constraints are dropped and the
|
||||
process is repeated. This ensures that the most important constraints
|
||||
are satisfied.
|
||||
|
||||
A special note to make here is that if any one given constraint is
|
||||
impossible to satisfy even individually (e.g. if minimum size hints
|
||||
specify a larger window than the screen size, making the
|
||||
fully-onscreen constraint impossible to satisfy) then we treat the
|
||||
constraint as being satisfied. This sounds counter-intuitive, but the
|
||||
idea is that we want to satisfy as many constraints as possible and if
|
||||
we treat it as a violation then all constraints with a lesser priority
|
||||
also get dropped along with the impossible to satisfy one.
|
||||
|
||||
3) Using maximal/spanning rectangles
|
||||
|
||||
The constraints rely heavily on something I call spanning rectangles
|
||||
(which Soeren referred to as maximal rectangles, a name which I think
|
||||
I like better but I don't want to go change all the code now). These
|
||||
spanning rectangles have the property that a window will fit on the
|
||||
screen if and only if it fits within at least one of the rectangles.
|
||||
Soeren had an alternative way of describing these rectangles, namely
|
||||
that they were rectangles with the property that if you made any of
|
||||
them larger in any direction, they would overlap with struts or be
|
||||
offscreen (with the implicit assumption that there are enough of these
|
||||
rectangles that combined they cover all relevant parts of the screen).
|
||||
Note that, by necessity, these spanning/maximal rectangles will often
|
||||
overlap each other.
|
||||
|
||||
Such a list makes it relatively easy to define operations like
|
||||
window-is-onscreen or clamp-window-to-region or
|
||||
shove-window-into-region. Since we have a on-single-xinerama
|
||||
constraint in addition to the onscreen constraint(s), we cache
|
||||
number_xineramas + 1 of these lists in the workspace. These lists
|
||||
then only need to be updated whenever the workarea is (e.g. when strut
|
||||
list change or screen or xinerama size changes).
|
||||
|
||||
4) Constraints can be user-action vs app-action oriented
|
||||
|
||||
Such differentiation requires special care for the constraints to be
|
||||
consistent; e.g. if the user does something and one constraint
|
||||
applies, then the app does something you have to be careful that the
|
||||
constraint on the app action doesn't result in some jarring motion.
|
||||
|
||||
In particular, the constraints currently allow offscreen movement or
|
||||
resizing for user actions only. The way consistency is handled is
|
||||
that at the end of the constraints, update_onscreen_requirements()
|
||||
checks to see if the window is offscreen or split across xineramas and
|
||||
updates window->require_fully_onscreen and
|
||||
window->require_on_single_xinerama appropriately.
|
||||
|
||||
5) Avoid over-complification
|
||||
|
||||
The previous code tried to reform the constraints into terms of a
|
||||
single variable. This made the code rather difficult to
|
||||
understand. ("This is a rather complicated fix for an obscure bug
|
||||
that happened when resizing a window and encountering a constraint
|
||||
such as the top edge of the screen.") It also failed, even on the
|
||||
very example for which it used as justification for the complexity
|
||||
(bug 312104 -- when keyboard resizing the top of the window,
|
||||
Metacity extends the bottom once the titlebar hits the top panel),
|
||||
though the reason why it failed is somewhat mysterious as it should
|
||||
have worked. Further, it didn't really reform the constraints in
|
||||
terms of a single variable -- there was both an x_move_delta and an
|
||||
x_resize_delta, and the existence of both caused bug 109553
|
||||
(gravity with simultaneous move and resize doesn't work)
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
Important points to remember
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
- Inner vs Outer window
|
||||
|
||||
Note that because of how configure requests work and
|
||||
meta_window_move_resize_internal() and friends are set up, that the
|
||||
rectangles passed to meta_window_constrain() are with respect to inner
|
||||
window positions instead of outer window positions (meaning that window
|
||||
manager decorations are not included in the position/size). For the
|
||||
constraints that need to be enforced with respect to outer window
|
||||
positions, you'll need to make use of the extend_by_frame() and
|
||||
unextend_by_frame() functions.
|
||||
|
||||
- meta_window_move_resize_internal() accepts a really hairy set of
|
||||
inputs. See the huge comment at the beginning of that function.
|
||||
constraints gets screwed up if that function can't sanitize the input,
|
||||
so be very careful about that. It used to be pretty busted.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
Explanation of fields in the ConstraintInfo strut
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
As of the time of this writing, ConstraintInfo had the following fields:
|
||||
orig
|
||||
current
|
||||
fgeom
|
||||
action_type
|
||||
is_user_action
|
||||
resize_gravity
|
||||
fixed_directions
|
||||
work_area_xinerama
|
||||
entire_xinerama
|
||||
usable_screen_region
|
||||
usable_xinerama_region
|
||||
|
||||
A brief description of each and/or pointers to more information are found
|
||||
below:
|
||||
orig
|
||||
The previous position and size of the window, ignoring any window
|
||||
decorations
|
||||
current
|
||||
The requested position and size of the window, ignoring any window
|
||||
decorations. This rectangle gets modified by the various constraints
|
||||
to specify the allowed position closest to the requested position.
|
||||
fgeom
|
||||
The geometry of the window frame (i.e. "decorations"), if it exists.
|
||||
Otherwise, it's a dummy 0-size frame for convenience (i.e. this pointer
|
||||
is guaranteed to be non-NULL so you don't have to do the stupid check).
|
||||
action_type
|
||||
Whether the action being constrained is a move, resize, or a combined
|
||||
move and resize. Some constraints can run faster with this information
|
||||
(e.g. constraining size increment hints or min size hints don't need to
|
||||
do anything for pure move operations). This may also be used for
|
||||
providing slightly different behavior (e.g. clip-to-region instead of
|
||||
shove-into-region for resize vs. moving operations), but doesn't
|
||||
currently have a lot of use for this.
|
||||
is_user_action
|
||||
Used to determine whether the action being constrained is a user
|
||||
action. If so, certain parts of the constraint may be relaxed. Note
|
||||
that this requires care to get right; see item 4 of the basic ideas
|
||||
section for more details.
|
||||
resize_gravity
|
||||
The gravity used in the resize operation, used in order to make sure
|
||||
windows are resized correctly if constraints specify that their size
|
||||
must be modified. Explained further in the resize_gravity
|
||||
vs. fixed_directions section.
|
||||
fixed_directions
|
||||
There may be multiple solutions to shoving a window back onscreen.
|
||||
Typically, the shortest distance used is the solution picked, but if
|
||||
e.g. an application only moved its window in a single direction, it's
|
||||
more desirable that the window is shoved back in that direction than in
|
||||
a different one. fixed_directions facilitates that. Explained further
|
||||
in the resize_gravity vs. fixed_directions section.
|
||||
work_area_xinerama
|
||||
This region is defined in the workspace and just cached here for
|
||||
convenience. It is basically the area obtained by taking the current
|
||||
xinerama, treating all partial struts as full struts, and then
|
||||
subtracting all struts from the current xinerama region. Useful
|
||||
e.g. for enforcing maximization constraints.
|
||||
entire_xinerama
|
||||
Just a cache of the rectangle corresponding to the entire current
|
||||
xinerama, including struts. Useful e.g. for enforcing fullscreen
|
||||
constraints.
|
||||
usable_screen_region
|
||||
The set of maximal/spanning rectangles for the entire screen; this
|
||||
region doesn't overlap with any struts and helps to enforce
|
||||
e.g. onscreen constraints.
|
||||
usable_xinerama_region
|
||||
The set of maximal/spanning rectangles for the current xinerama; this
|
||||
region doesn't overlap with any struts on the xinerama and helps to
|
||||
enforce e.g. the on-single-xinerama constraint.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
Gory details of resize_gravity vs. fixed_directions
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Note that although resize_gravity and fixed_directions look similar, they
|
||||
are used for different purposes:
|
||||
|
||||
- resize_gravity is only for resize operations and is used for
|
||||
constraints unrelated to keeping a window within a certain region
|
||||
- fixed_directions is for both move and resize operations and is
|
||||
specifically for keeping a window within a specified region.
|
||||
|
||||
Examples of where each are used:
|
||||
|
||||
- If a window is simultaneously moved and resized to the southeast corner
|
||||
with SouthEastGravity, but it turns out that the window was sized to
|
||||
something smaller than the minimum size hint, then the size_hints
|
||||
constraint should resize the window using the resize_gravity to ensure
|
||||
that the southeast corner doesn't move.
|
||||
- If an application resizes itself so that it grows downward only (which
|
||||
I note could be using any of three different gravities, most likely
|
||||
NorthWest), and happens to put the southeast part of the window under a
|
||||
partial strut, then the window needs to be forced back on screen.
|
||||
(Yes, shoved onscreen and not clipped; see bug 136307). It may be the
|
||||
case that moving the window to the left results in less movement of the
|
||||
window than moving the window up, which, in the absence of fixed
|
||||
directions would cause us to chose moving to the left. But since the
|
||||
user knows that only the height of the window is changing, they would
|
||||
find moving to the left weird (especially if this were a dialog that
|
||||
had been centered on its parent). It'd be better to shove the window
|
||||
upwards so we make sure to keep the left and right sides fixed in this
|
||||
case. Note that moving the window upwards (or leftwards) is probably
|
||||
totally against the gravity in this case; but that's okay because
|
||||
gravity typically assumes there's more than enough onscreen space for
|
||||
the resize and we only override the gravity when that assumption is
|
||||
wrong.
|
||||
|
||||
For the paranoid, a fixed directions might give an impossible to fulfill
|
||||
constraint (I don't think that's true currently in the code, but I haven't
|
||||
thought it through in a while). If this ever becomes a problem, it should
|
||||
be relatively simple to throw out the fixed directions when this happens
|
||||
and rerun the constraint. Of course, it might be better to rethink things
|
||||
to just avoid such a problem.
|
||||
|
||||
The nitty gritty of what gets fixed:
|
||||
User move:
|
||||
in x direction - y direction fixed
|
||||
in y direction - x direction fixed
|
||||
in both dirs. - neither direction fixed
|
||||
User resize: (note that for clipping, only 1 side ever changed)
|
||||
in x direction - y direction fixed (technically opposite x side fixed too)
|
||||
in y direction - x direction fixed (technically opposite y side fixed too)
|
||||
in both dirs. - neither direction fixed
|
||||
App move:
|
||||
in x direction - y direction fixed
|
||||
in y direction - x direction fixed
|
||||
in both dirs. - neither direction fixed
|
||||
App resize
|
||||
in x direction - y direction fixed
|
||||
in y direction - x direction fixed
|
||||
in 2 parallel directions (center side gravity) - other dir. fixed
|
||||
in 2 orthogonal directions (corner gravity) - neither dir. fixed
|
||||
in 3 or 4 directions (a center-like gravity) - neither dir. fixed
|
||||
Move & resize
|
||||
Treat like resize case though this will usually mean all four sides
|
||||
change and result in neither direction being fixed
|
||||
Note that in all cases, if neither direction moves it is likely do to a
|
||||
change in struts and thus neither direction should be fixed despite the
|
||||
lack of movement.
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
2435
src/constraints.c
2435
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);
|
||||
|
||||
|
121
src/display.c
121
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,25 +1685,38 @@ 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;
|
||||
|
||||
if (op != META_GRAB_OP_NONE)
|
||||
meta_display_begin_grab_op (display,
|
||||
window->screen,
|
||||
window,
|
||||
@ -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)
|
||||
|
10
src/frames.c
10
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,6 +1442,15 @@ meta_frames_button_press_event (GtkWidget *widget,
|
||||
break;
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -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,39 +2012,27 @@ 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
@ -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;
|
||||
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;
|
||||
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;
|
||||
|
174
src/screen.c
174
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)))
|
||||
if (meta_rectangle_contains_rect (&screen->xinerama_infos[i].rect,
|
||||
&pointer_position))
|
||||
{
|
||||
screen->last_xinerama_index = i;
|
||||
break;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
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
|
||||
|
1025
src/window.c
1025
src/window.c
File diff suppressed because it is too large
Load Diff
55
src/window.h
55
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 (MetaWindow *window,
|
||||
MetaMaximizeFlags directions);
|
||||
void meta_window_maximize_internal (MetaWindow *window,
|
||||
MetaMaximizeFlags directions,
|
||||
MetaRectangle *saved_rect);
|
||||
void meta_window_unmaximize (MetaWindow *window);
|
||||
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);
|
||||
|
||||
|
249
src/workspace.c
249
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,15 +504,16 @@ 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,
|
||||
g_free (workspace->work_area_xinerama);
|
||||
workspace->work_area_xinerama = g_new (MetaRectangle,
|
||||
workspace->screen->n_xinerama_infos);
|
||||
|
||||
i = 0;
|
||||
@ -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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
|
Loading…
Reference in New Issue
Block a user