summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog35
-rw-r--r--src/constraints.c26
-rw-r--r--src/place.c149
-rw-r--r--src/window.c66
-rw-r--r--src/window.h3
5 files changed, 172 insertions, 107 deletions
diff --git a/ChangeLog b/ChangeLog
index d2f61917..80b5c067 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,40 @@
2003-06-09 Rob Adams <robadams@ucla.edu>
+ Revamp placement policy for windows that are maximized when they
+ are mapped, including windows that set a hint to be maximized or
+ windows that are auto-maximized using our heuristic. See #111902.
+
+ * src/window.h: add new flag maximize_after_placement and new
+ function meta_window_maximize_internal.
+
+ * src/window.c (meta_window_new): initialize
+ maximize_after_placement to FALSE and remove the automaximize
+ heuristic.
+ (meta_window_maximize_internal): new function accepts a saved_rect
+ argument to be used as the new saved_rect for the window, and does
+ not queue a move_resize.
+ (meta_window_maximize): re-implement using
+ meta_window_maximize_internal.
+ (update_net_wm_state): If a window has a maximize hint set on
+ startup set maximize_after_placement to TRUE
+
+ * src/constraints.c (meta_window_constrain): Update the xinerama
+ information in the ConstraintInfo after placing the window, and
+ maximize the window after placement if
+ window->maximize_after_placement
+
+ * src/place.c (find_first_fit): take a natural xinerama list as an
+ argument instead of generating it here
+ (constrain_placement): remove function, since it is no longer
+ needed
+ (meta_window_place): generate the natural xinerama list here and
+ pass it into find_first_fit. If find_first_fit fails, use the
+ list to find empty xineramas where we can place windows that may
+ be maximized later. This makes maximized windows follow the
+ correct placement policy. Move the automaximize heuristic here.
+
+2003-06-09 Rob Adams <robadams@ucla.edu>
+
* src/metacity-dialog.c (warn_about_no_sm_support): install an
alarm to timeout the no-sm-dialog after 4 minutes of inactivity.
Patch from Ximian. See #114789.
diff --git a/src/constraints.c b/src/constraints.c
index 7913a8c1..bc658a24 100644
--- a/src/constraints.c
+++ b/src/constraints.c
@@ -1119,20 +1119,38 @@ meta_window_constrain (MetaWindow *window,
!window->maximized &&
!window->fullscreen)
{
- int x, y;
+ MetaRectangle placed_rect = current;
meta_window_place (window, orig_fgeom, current.x, current.y,
- &x, &y);
+ &placed_rect.x, &placed_rect.y);
+
+ /* placing the window may have changed the xinerama. Find the
+ * new xinerama and update the ConstraintInfo
+ */
+ info.xinerama = meta_screen_get_xinerama_for_rect (window->screen,
+ &placed_rect);
+ meta_window_get_work_area_for_xinerama (window,
+ info.xinerama->number,
+ &info.work_area_xinerama);
+ update_position_limits (window, &info);
constrain_move (window, &info, &current,
- x - current.x,
- y - current.y,
+ placed_rect.x - current.x,
+ placed_rect.y - current.y,
new);
current = *new;
/* Ignore any non-placement movement */
x_move_delta = 0;
y_move_delta = 0;
+
+ }
+
+ if (window->maximize_after_placement &&
+ window->placed)
+ {
+ window->maximize_after_placement = FALSE;
+ meta_window_maximize_internal (window, new);
}
/* Maximization, fullscreen, etc. are defined as a move followed by
diff --git a/src/place.c b/src/place.c
index 4e1a7dde..df480016 100644
--- a/src/place.c
+++ b/src/place.c
@@ -404,6 +404,8 @@ find_first_fit (MetaWindow *window,
MetaFrameGeometry *fgeom,
/* visible windows on relevant workspaces */
GList *windows,
+ int* xineramas_list,
+ int n_xineramas,
int x,
int y,
int *new_x,
@@ -423,8 +425,6 @@ find_first_fit (MetaWindow *window,
MetaRectangle rect;
MetaRectangle work_area;
int i;
- int* xineramas_list;
- int n_xineramas;
retval = FALSE;
@@ -447,9 +447,6 @@ find_first_fit (MetaWindow *window,
rect.height += fgeom->top_height + fgeom->bottom_height;
}
- meta_screen_get_natural_xinerama_list (window->screen,
- &xineramas_list,
- &n_xineramas);
for (i = 0; i < n_xineramas; i++)
{
meta_topic (META_DEBUG_XINERAMA,
@@ -552,68 +549,11 @@ find_first_fit (MetaWindow *window,
out:
- g_free (xineramas_list);
g_list_free (below_sorted);
g_list_free (right_sorted);
return retval;
}
-static void
-constrain_placement (MetaWindow *window,
- MetaFrameGeometry *fgeom,
- int x,
- int y,
- int *new_x,
- int *new_y)
-{
- /* The purpose of this function is to apply constraints that are not
- * covered by window.c:constrain_position(), but should apply
- * whenever we are _placing_ a window regardless of placement algorithm.
- */
- MetaRectangle work_area;
- int nw_x, nw_y;
- int offscreen_w, offscreen_h;
- MetaRectangle outer_rect;
-
- meta_window_get_outer_rect (window, &outer_rect);
-
- /* FIXME this is bogus because we get the current xinerama
- * for the window based on its position, but we haven't
- * placed it yet.
- */
- meta_window_get_work_area_current_xinerama (window, &work_area);
-
- nw_x = work_area.x;
- nw_y = work_area.y;
-
- if (window->frame)
- {
- nw_x += fgeom->left_width;
- nw_y += fgeom->top_height;
- }
-
- /* Keep window from going off the bottom right, though we don't have
- * this constraint once the window has been placed
- */
- offscreen_w = (outer_rect.x + outer_rect.width) - (work_area.x + work_area.width);
- if (offscreen_w > 0)
- nw_x -= offscreen_w;
- offscreen_h = (outer_rect.y + outer_rect.height) - (work_area.y + work_area.height);
- if (offscreen_h > 0)
- nw_y -= offscreen_h;
-
- /* Keep window from going off left edge, though again we don't have
- * this constraint once the window has been placed.
- */
- if (x < nw_x)
- x = nw_x;
- if (y < nw_y)
- y = nw_y;
-
- *new_x = x;
- *new_y = y;
-}
-
void
meta_window_place (MetaWindow *window,
MetaFrameGeometry *fgeom,
@@ -624,6 +564,10 @@ meta_window_place (MetaWindow *window,
{
GList *windows;
const MetaXineramaScreenInfo *xi;
+ int* xineramas_list = NULL;
+ int n_xineramas;
+ int i;
+ int placed_on = -1;
/* frame member variables should NEVER be used in here, only
* MetaFrameGeometry. But remember fgeom == NULL
@@ -811,16 +755,87 @@ meta_window_place (MetaWindow *window,
x = xi->x_origin;
y = xi->y_origin;
- if (find_first_fit (window, fgeom, windows, x, y, &x, &y))
+ meta_screen_get_natural_xinerama_list (window->screen,
+ &xineramas_list,
+ &n_xineramas);
+
+ if (find_first_fit (window, fgeom, windows,
+ xineramas_list, n_xineramas,
+ x, y, &x, &y))
goto done;
-
- find_next_cascade (window, fgeom, windows, x, y, &x, &y);
+
+ /* This is a special-case origin-cascade so that windows that are
+ * too large to fit onto a workspace (and which will be
+ * automaximized later) will go onto an empty xinerama if one is
+ * available.
+ */
+ if (window->has_maximize_func && window->decorated &&
+ !window->fullscreen)
+ {
+ if (window->frame)
+ {
+ x = fgeom->left_width;
+ y = fgeom->top_height;
+ }
+ else
+ {
+ x = 0;
+ y = 0;
+ }
+
+ for (i = 0; i < n_xineramas; i++)
+ {
+ MetaRectangle work_area;
+
+ meta_window_get_work_area_for_xinerama (window, xineramas_list[i], &work_area);
+
+ if (!rectangle_overlaps_some_window (&work_area, windows))
+ {
+ x += work_area.x;
+ y += work_area.y;
+ placed_on = i;
+ break;
+ }
+ }
+ }
+
+ /* if the window wasn't placed at the origin of an empty xinerama,
+ * cascade it onto the current xinerama
+ */
+ if (placed_on == -1)
+ {
+ find_next_cascade (window, fgeom, windows, x, y, &x, &y);
+ placed_on = 0;
+ }
+
+ /* Maximize windows if they are too big for their work area (bit of
+ * a hack here). Assume undecorated windows probably don't intend to
+ * be maximized.
+ */
+ if (window->has_maximize_func && window->decorated &&
+ !window->fullscreen)
+ {
+ MetaRectangle workarea;
+ MetaRectangle outer;
+
+ meta_window_get_work_area_for_xinerama (window,
+ xineramas_list[placed_on],
+ &workarea);
+ meta_window_get_outer_rect (window, &outer);
+
+ if (outer.width >= workarea.width &&
+ outer.height >= workarea.height)
+ {
+ outer.x = x;
+ outer.y = y;
+ meta_window_maximize_internal (window, &outer);
+ }
+ }
done:
+ g_free (xineramas_list);
g_list_free (windows);
- constrain_placement (window, fgeom, x, y, &x, &y);
-
done_no_constraints:
*new_x = x;
diff --git a/src/window.c b/src/window.c
index ddba6a07..31af946b 100644
--- a/src/window.c
+++ b/src/window.c
@@ -417,6 +417,7 @@ meta_window_new (MetaDisplay *display,
window->user_has_move_resized = FALSE;
window->maximized = FALSE;
+ window->maximize_after_placement = FALSE;
window->fullscreen = FALSE;
window->on_all_workspaces = FALSE;
window->shaded = FALSE;
@@ -695,28 +696,6 @@ meta_window_new (MetaDisplay *display,
}
}
- /* Maximize windows if they are too big for their work
- * area (bit of a hack here). Assume undecorated windows
- * probably don't intend to be maximized.
- */
- if (window->has_maximize_func && window->decorated &&
- !window->fullscreen)
- {
- MetaRectangle workarea;
- MetaRectangle outer;
-
- if (!window->placed)
- meta_warning ("Metacity issue: using position-based current xinerama prior to placement\n");
-
- meta_window_get_work_area_current_xinerama (window, &workarea);
-
- meta_window_get_outer_rect (window, &outer);
-
- if (outer.width >= workarea.width &&
- outer.height >= workarea.height)
- meta_window_maximize (window);
- }
-
/* Sync stack changes */
meta_stack_thaw (window->screen->stack);
@@ -1841,29 +1820,44 @@ meta_window_save_rect (MetaWindow *window)
}
void
+meta_window_maximize_internal (MetaWindow *window,
+ MetaRectangle *saved_rect)
+{
+ meta_topic (META_DEBUG_WINDOW_OPS,
+ "Maximizing %s\n", window->desc);
+
+ if (saved_rect != NULL)
+ window->saved_rect = *saved_rect;
+ else
+ meta_window_save_rect (window);
+
+ window->maximized = TRUE;
+
+ recalc_window_features (window);
+ set_net_wm_state (window);
+}
+
+void
meta_window_maximize (MetaWindow *window)
{
if (!window->maximized)
{
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Maximizing %s\n", window->desc);
-
if (window->shaded)
meta_window_unshade (window);
-
- meta_window_save_rect (window);
- window->maximized = TRUE;
+ /* if the window hasn't been placed yet, we'll maximize it then
+ */
+ if (!window->placed)
+ {
+ window->maximize_after_placement = TRUE;
+ return;
+ }
+
+ meta_window_maximize_internal (window, NULL);
- /* FIXME why did I put this here? */
- meta_window_raise (window);
-
/* move_resize with new maximization constraints
*/
meta_window_queue_move_resize (window);
-
- recalc_window_features (window);
- set_net_wm_state (window);
}
}
@@ -4309,9 +4303,9 @@ update_net_wm_state (MetaWindow *window)
if (atoms[i] == window->display->atom_net_wm_state_shaded)
window->shaded = TRUE;
else if (atoms[i] == window->display->atom_net_wm_state_maximized_horz)
- window->maximized = TRUE;
+ window->maximize_after_placement = TRUE;
else if (atoms[i] == window->display->atom_net_wm_state_maximized_vert)
- window->maximized = TRUE;
+ window->maximize_after_placement = TRUE;
else if (atoms[i] == window->display->atom_net_wm_state_modal)
window->wm_state_modal = TRUE;
else if (atoms[i] == window->display->atom_net_wm_state_skip_taskbar)
diff --git a/src/window.h b/src/window.h
index 2b6a8fa0..f9353d1e 100644
--- a/src/window.h
+++ b/src/window.h
@@ -94,6 +94,7 @@ struct _MetaWindow
/* Whether we're maximized */
guint maximized : 1;
+ guint maximize_after_placement : 1;
/* Whether we're shaded */
guint shaded : 1;
@@ -304,6 +305,8 @@ void meta_window_queue_calc_showing (MetaWindow *window);
void meta_window_minimize (MetaWindow *window);
void meta_window_unminimize (MetaWindow *window);
void meta_window_maximize (MetaWindow *window);
+void meta_window_maximize_internal (MetaWindow *window,
+ MetaRectangle *saved_rect);
void meta_window_unmaximize (MetaWindow *window);
void meta_window_shade (MetaWindow *window);
void meta_window_unshade (MetaWindow *window);