mirror of
https://github.com/brl/mutter.git
synced 2024-11-24 17:10:40 -05:00
Add a constrain_titlebar_visible constraint; should fix both bug 333328
2006-08-07 Elijah Newren <newren gmail com> Add a constrain_titlebar_visible constraint; should fix both bug 333328 and bug 345522. Not perfect (minor annoying snap pulling windows back onscreen, plus an ugly hack almost as bad as the old one), but tarballs are due in less than half an hour. ;-) * src/boxes.[ch] (meta_rectangle_overlaps_with_region): new function * src/constraints.c (constrain_titlebar_visible): new function, (enum ConstraintPriority, array all_constraints, update_onscreen_requirements): various small changes to accomodate the new function * src/edge-resistance.c: remove the infinite edge resistance, which was a big hack of a way to workaround the lack of a titlebar_visible constraint * src/window.[ch] (MetaWindow): new require_titlebar_visible bitfield, (meta_window_new_with_attrs): initialized here
This commit is contained in:
parent
acc6c97997
commit
57bedc42a4
22
ChangeLog
22
ChangeLog
@ -1,3 +1,25 @@
|
||||
2006-08-07 Elijah Newren <newren gmail com>
|
||||
|
||||
Add a constrain_titlebar_visible constraint; should fix both bug
|
||||
333328 and bug 345522. Not perfect (minor annoying snap pulling
|
||||
windows back onscreen, plus an ugly hack almost as bad as the old
|
||||
one), but tarballs are due in less than half an hour. ;-)
|
||||
|
||||
* src/boxes.[ch] (meta_rectangle_overlaps_with_region):
|
||||
new function
|
||||
|
||||
* src/constraints.c (constrain_titlebar_visible): new function,
|
||||
(enum ConstraintPriority, array all_constraints,
|
||||
update_onscreen_requirements): various small changes to
|
||||
accomodate the new function
|
||||
|
||||
* src/edge-resistance.c: remove the infinite edge resistance,
|
||||
which was a big hack of a way to workaround the lack of a
|
||||
titlebar_visible constraint
|
||||
|
||||
* src/window.[ch] (MetaWindow): new require_titlebar_visible
|
||||
bitfield, (meta_window_new_with_attrs): initialized here
|
||||
|
||||
2006-08-07 Elijah Newren <newren gmail com>
|
||||
|
||||
* src/frames.c (meta_frames_button_press_event): Patch from Chris
|
||||
|
19
src/boxes.c
19
src/boxes.c
@ -705,6 +705,25 @@ meta_rectangle_contained_in_region (const GList *spanning_rects,
|
||||
return contained;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_rectangle_overlaps_with_region (const GList *spanning_rects,
|
||||
const MetaRectangle *rect)
|
||||
{
|
||||
const GList *temp;
|
||||
gboolean overlaps;
|
||||
|
||||
temp = spanning_rects;
|
||||
overlaps = FALSE;
|
||||
while (!overlaps && temp != NULL)
|
||||
{
|
||||
overlaps = overlaps || meta_rectangle_overlap (temp->data, rect);
|
||||
temp = temp->next;
|
||||
}
|
||||
|
||||
return overlaps;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
meta_rectangle_clamp_to_fit_into_region (const GList *spanning_rects,
|
||||
FixedDirections fixed_directions,
|
||||
|
@ -183,6 +183,9 @@ gboolean meta_rectangle_could_fit_in_region (
|
||||
gboolean meta_rectangle_contained_in_region (
|
||||
const GList *spanning_rects,
|
||||
const MetaRectangle *rect);
|
||||
gboolean meta_rectangle_overlaps_with_region (
|
||||
const GList *spanning_rects,
|
||||
const MetaRectangle *rect);
|
||||
|
||||
/* Make the rectangle small enough to fit into one of the spanning_rects,
|
||||
* but make it no smaller than min_size.
|
||||
|
@ -97,6 +97,7 @@ typedef enum
|
||||
PRIORITY_MAXIMIZATION = 2,
|
||||
PRIORITY_FULLSCREEN = 2,
|
||||
PRIORITY_SIZE_HINTS_LIMITS = 3,
|
||||
PRIORITY_TITLEBAR_VISIBLE = 4,
|
||||
PRIORITY_PARTIALLY_VISIBLE_ON_WORKAREA = 4,
|
||||
PRIORITY_MAXIMUM = 4 // Dummy value used for loop end = max(all priorities)
|
||||
} ConstraintPriority;
|
||||
@ -165,6 +166,10 @@ static gboolean constrain_fully_onscreen (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only);
|
||||
static gboolean constrain_titlebar_visible (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only);
|
||||
static gboolean constrain_partially_onscreen (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
@ -209,6 +214,7 @@ static const Constraint all_constraints[] = {
|
||||
{constrain_aspect_ratio, "constrain_aspect_ratio"},
|
||||
{constrain_to_single_xinerama, "constrain_to_single_xinerama"},
|
||||
{constrain_fully_onscreen, "constrain_fully_onscreen"},
|
||||
{constrain_titlebar_visible, "constrain_titlebar_visible"},
|
||||
{constrain_partially_onscreen, "constrain_partially_onscreen"},
|
||||
{NULL, NULL}
|
||||
};
|
||||
@ -536,23 +542,23 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
window->type == META_WINDOW_DOCK)
|
||||
return;
|
||||
|
||||
/* USABILITY NOTE: Naturally, I only want the require_fully_onscreen and
|
||||
* require_on_single_xinerama flags to *become false* due to user
|
||||
* interactions (which is allowed since certain constraints are ignored
|
||||
* for user interactions regardless of the setting of these flags).
|
||||
* However, whether to make these flags *become true* due to just an
|
||||
* application interaction is a little trickier. It's possible that
|
||||
* users may find not doing that strange since two application
|
||||
* interactions that resize in opposite ways don't necessarily end up
|
||||
* cancelling--but it may also be strange for the user to have an
|
||||
* application resize the window so that it's onscreen, the user forgets
|
||||
* about it, and then later the app is able to resize itself off the
|
||||
* screen. Anyway, for now, I'm think the latter is the more problematic
|
||||
* case but this may need to be revisited.
|
||||
/* USABILITY NOTE: Naturally, I only want the require_fully_onscreen,
|
||||
* require_on_single_xinerama, and require_titlebar_visible flags to
|
||||
* *become false* due to user interactions (which is allowed since
|
||||
* certain constraints are ignored for user interactions regardless of
|
||||
* the setting of these flags). However, whether to make these flags
|
||||
* *become true* due to just an application interaction is a little
|
||||
* trickier. It's possible that users may find not doing that strange
|
||||
* since two application interactions that resize in opposite ways don't
|
||||
* necessarily end up cancelling--but it may also be strange for the user
|
||||
* to have an application resize the window so that it's onscreen, the
|
||||
* user forgets about it, and then later the app is able to resize itself
|
||||
* off the screen. Anyway, for now, I think the latter is the more
|
||||
* problematic case but this may need to be revisited.
|
||||
*/
|
||||
|
||||
/* The require onscreen/on-single-xinerama stuff is relative to the
|
||||
* outer window, not the inner
|
||||
/* The require onscreen/on-single-xinerama and titlebar_visible
|
||||
* stuff is relative to the outer window, not the inner
|
||||
*/
|
||||
extend_by_frame (&info->current, info->fgeom);
|
||||
|
||||
@ -582,6 +588,26 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
window->desc,
|
||||
window->require_on_single_xinerama ? "TRUE" : "FALSE");
|
||||
|
||||
/* Update whether we want future constraint runs to require the
|
||||
* titlebar to be visible.
|
||||
*/
|
||||
if (window->frame && window->decorated)
|
||||
{
|
||||
MetaRectangle titlebar_rect;
|
||||
|
||||
titlebar_rect = info->current;
|
||||
titlebar_rect.height = info->fgeom->top_height;
|
||||
old = window->require_titlebar_visible;
|
||||
window->require_titlebar_visible =
|
||||
meta_rectangle_overlaps_with_region (info->usable_screen_region,
|
||||
&titlebar_rect);
|
||||
if (old ^ window->require_titlebar_visible)
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"require_titlebar_visible for %s toggled to %s\n",
|
||||
window->desc,
|
||||
window->require_titlebar_visible ? "TRUE" : "FALSE");
|
||||
}
|
||||
|
||||
/* Don't forget to restore the position of the window */
|
||||
unextend_by_frame (&info->current, info->fgeom);
|
||||
}
|
||||
@ -1053,6 +1079,93 @@ constrain_fully_onscreen (MetaWindow *window,
|
||||
check_only);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
constrain_titlebar_visible (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only)
|
||||
{
|
||||
gboolean unconstrained_user_action;
|
||||
gboolean retval;
|
||||
int bottom_amount;
|
||||
int horiz_amount_offscreen, vert_amount_offscreen;
|
||||
int horiz_amount_onscreen, vert_amount_onscreen;
|
||||
|
||||
if (priority > PRIORITY_TITLEBAR_VISIBLE)
|
||||
return TRUE;
|
||||
|
||||
/* Allow the titlebar beyond the top of the screen only if the user wasn't
|
||||
* clicking on the titlebar to start the move.
|
||||
* FIXME: This is kind of a hack; nearly as ugly as the old infinite edge
|
||||
* resistance.
|
||||
*/
|
||||
unconstrained_user_action =
|
||||
info->is_user_action &&
|
||||
window->display->grab_anchor_root_y >= window->display->grab_initial_window_pos.y;
|
||||
|
||||
/* Exit early if we know the constraint won't apply--note that this constraint
|
||||
* is only meant for normal windows (e.g. we don't want docks to be shoved
|
||||
* "onscreen" by their own strut).
|
||||
*/
|
||||
if (window->type == META_WINDOW_DESKTOP ||
|
||||
window->type == META_WINDOW_DOCK ||
|
||||
!window->require_titlebar_visible ||
|
||||
!window->decorated ||
|
||||
unconstrained_user_action)
|
||||
return TRUE;
|
||||
|
||||
/* Determine how much offscreen things are allowed. We first need to
|
||||
* figure out how much must remain on the screen. For that, we use 25%
|
||||
* window width/height but clamp to the range of (10,75) pixels. This is
|
||||
* somewhat of a seat of my pants random guess at what might look good.
|
||||
* Then, the amount that is allowed off is just the window size minus
|
||||
* this amount (but no less than 0 for tiny windows).
|
||||
*/
|
||||
horiz_amount_onscreen = info->current.width / 4;
|
||||
vert_amount_onscreen = info->current.height / 4;
|
||||
horiz_amount_onscreen = CLAMP (horiz_amount_onscreen, 10, 75);
|
||||
vert_amount_onscreen = CLAMP (vert_amount_onscreen, 10, 75);
|
||||
horiz_amount_offscreen = info->current.width - horiz_amount_onscreen;
|
||||
vert_amount_offscreen = info->current.height - vert_amount_onscreen;
|
||||
horiz_amount_offscreen = MAX (horiz_amount_offscreen, 0);
|
||||
vert_amount_offscreen = MAX (vert_amount_offscreen, 0);
|
||||
/* Allow the titlebar to touch the bottom panel; If there is no titlebar,
|
||||
* require vert_amount to remain on the screen.
|
||||
*/
|
||||
if (window->frame)
|
||||
{
|
||||
bottom_amount = info->current.height + info->fgeom->bottom_height;
|
||||
vert_amount_onscreen = info->fgeom->top_height;
|
||||
}
|
||||
else
|
||||
bottom_amount = vert_amount_offscreen;
|
||||
|
||||
/* Extend the region, have a helper function handle the constraint,
|
||||
* then return the region to its original size.
|
||||
*/
|
||||
meta_rectangle_expand_region_conditionally (info->usable_screen_region,
|
||||
horiz_amount_offscreen,
|
||||
horiz_amount_offscreen,
|
||||
0, /* Don't let titlebar off */
|
||||
bottom_amount,
|
||||
horiz_amount_onscreen,
|
||||
vert_amount_onscreen);
|
||||
retval =
|
||||
do_screen_and_xinerama_relative_constraints (window,
|
||||
info->usable_screen_region,
|
||||
info,
|
||||
check_only);
|
||||
meta_rectangle_expand_region_conditionally (info->usable_screen_region,
|
||||
-horiz_amount_offscreen,
|
||||
-horiz_amount_offscreen,
|
||||
0, /* Don't let titlebar off */
|
||||
-bottom_amount,
|
||||
horiz_amount_onscreen,
|
||||
vert_amount_onscreen);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
constrain_partially_onscreen (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
|
@ -44,7 +44,6 @@ struct ResistanceDataForAnEdge
|
||||
GSourceFunc timeout_func;
|
||||
MetaWindow *window;
|
||||
int keyboard_buildup;
|
||||
gboolean allow_past_screen_edge;
|
||||
};
|
||||
typedef struct ResistanceDataForAnEdge ResistanceDataForAnEdge;
|
||||
|
||||
@ -397,18 +396,6 @@ apply_edge_resistance (MetaWindow *window,
|
||||
{
|
||||
int threshold;
|
||||
|
||||
/* INFINITE RESISTANCE for screen edges under certain cases; If
|
||||
* the edge is relevant and we're moving towards it and it's a
|
||||
* screen edge and infinite resistance has been requested for
|
||||
* this particular grab op then don't allow movement past it.
|
||||
*/
|
||||
if (edge->edge_type == META_EDGE_SCREEN &&
|
||||
!resistance_data->allow_past_screen_edge &&
|
||||
movement_towards_edge (edge->side_type, increment))
|
||||
{
|
||||
return compare;
|
||||
}
|
||||
|
||||
/* TIMEOUT RESISTANCE: If the edge is relevant and we're moving
|
||||
* towards it, then we may want to have some kind of time delay
|
||||
* before the user can move past this edge.
|
||||
@ -913,12 +900,6 @@ initialize_grab_edge_resistance_data (MetaDisplay *display)
|
||||
edge_data->right_data.keyboard_buildup = 0;
|
||||
edge_data->top_data.keyboard_buildup = 0;
|
||||
edge_data->bottom_data.keyboard_buildup = 0;
|
||||
|
||||
edge_data->left_data.allow_past_screen_edge = TRUE;
|
||||
edge_data->right_data.allow_past_screen_edge = TRUE;
|
||||
edge_data->bottom_data.allow_past_screen_edge = TRUE;
|
||||
edge_data->top_data.allow_past_screen_edge =
|
||||
display->grab_anchor_root_y >= display->grab_initial_window_pos.y;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -448,6 +448,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
||||
window->fullscreen = FALSE;
|
||||
window->require_fully_onscreen = TRUE;
|
||||
window->require_on_single_xinerama = TRUE;
|
||||
window->require_titlebar_visible = TRUE;
|
||||
window->on_all_workspaces = FALSE;
|
||||
window->shaded = FALSE;
|
||||
window->initially_iconic = FALSE;
|
||||
|
@ -138,6 +138,9 @@ struct _MetaWindow
|
||||
/* Whether we're trying to constrain the window to be on a single xinerama */
|
||||
guint require_on_single_xinerama : 1;
|
||||
|
||||
/* Whether we're trying to constrain the window's titlebar to be onscreen */
|
||||
guint require_titlebar_visible : 1;
|
||||
|
||||
/* Whether we're sticky in the multi-workspace sense
|
||||
* (vs. the not-scroll-with-viewport sense, we don't
|
||||
* have no stupid viewports)
|
||||
|
Loading…
Reference in New Issue
Block a user