on unminimize, queue calc_showing on all transients

2002-05-05  Havoc Pennington  <hp@pobox.com>

	* src/window.c (meta_window_unminimize): on unminimize, queue
	calc_showing on all transients
	(meta_window_activate): on activate, unminimize all a window's
	ancestors, not just the window itself.

	* src/workspace.c (set_work_area_hint): don't increment "tmp" by
	16 unsigned long, increment by 4

	* src/window.c (meta_window_free): if a window isn't minimized,
	restore its WM_STATE to NormalState instead of IconicState,
	since IconicState on initial window map means that the window
	should be minimized.

	* src/workspace.c (meta_workspace_invalidate_work_area): queue an
	idle to recompute the work area hint.
	(set_work_area_hint): we need 4*num_workspaces ints, not just
	num_workspaces.

	* src/screen.c (meta_screen_new): add work_area_idle field,
	handle it on screen shutdown

	* src/common.h (META_PRIORITY_PREFS_NOTIFY,
	META_PRIORITY_WORK_AREA_HINT): define some idle priorities

	* src/window.c (meta_window_calc_showing): hide windows if
	their parent window is minimized
	(meta_window_minimize): also queue_calc_showing on all
	transients of the window being minimized

	* src/place.c (constrain_placement): function to apply
	placement-time-only constraints, such as "not off the left of the
	screen"
	(meta_window_place): put dialogs down a bit over their parent,
	not right at the top.
	(meta_window_place): when centering a dialog, center it
	on the current xinerama screen, rather than the entire
	screen.

	* src/screen.c (meta_screen_get_current_xinerama): new function,
	but not implemented
This commit is contained in:
Havoc Pennington 2002-05-05 05:41:13 +00:00 committed by Havoc Pennington
parent 6f8a7f1870
commit 41120f2a79
9 changed files with 354 additions and 58 deletions

View File

@ -1,3 +1,46 @@
2002-05-05 Havoc Pennington <hp@pobox.com>
* src/window.c (meta_window_unminimize): on unminimize, queue
calc_showing on all transients
(meta_window_activate): on activate, unminimize all a window's
ancestors, not just the window itself.
* src/workspace.c (set_work_area_hint): don't increment "tmp" by
16 unsigned long, increment by 4
* src/window.c (meta_window_free): if a window isn't minimized,
restore its WM_STATE to NormalState instead of IconicState,
since IconicState on initial window map means that the window
should be minimized.
* src/workspace.c (meta_workspace_invalidate_work_area): queue an
idle to recompute the work area hint.
(set_work_area_hint): we need 4*num_workspaces ints, not just
num_workspaces.
* src/screen.c (meta_screen_new): add work_area_idle field,
handle it on screen shutdown
* src/common.h (META_PRIORITY_PREFS_NOTIFY,
META_PRIORITY_WORK_AREA_HINT): define some idle priorities
* src/window.c (meta_window_calc_showing): hide windows if
their parent window is minimized
(meta_window_minimize): also queue_calc_showing on all
transients of the window being minimized
* src/place.c (constrain_placement): function to apply
placement-time-only constraints, such as "not off the left of the
screen"
(meta_window_place): put dialogs down a bit over their parent,
not right at the top.
(meta_window_place): when centering a dialog, center it
on the current xinerama screen, rather than the entire
screen.
* src/screen.c (meta_screen_get_current_xinerama): new function,
but not implemented
2002-05-04 Havoc Pennington <hp@pobox.com>
* src/frames.c (meta_frames_paint_to_drawable): chop out the

View File

@ -148,6 +148,9 @@ typedef enum
#define META_MINI_ICON_WIDTH 16
#define META_MINI_ICON_HEIGHT 16
#define META_PRIORITY_PREFS_NOTIFY (G_PRIORITY_DEFAULT_IDLE + 10)
#define META_PRIORITY_WORK_AREA_HINT (G_PRIORITY_DEFAULT_IDLE + 15)
#endif

View File

@ -197,13 +197,50 @@ find_first_fit (MetaWindow *window,
/* FIXME */
}
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;
meta_window_get_work_area (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 left edge, though 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,
meta_window_place (MetaWindow *window,
MetaFrameGeometry *fgeom,
int x,
int y,
int *new_x,
int *new_y)
int x,
int y,
int *new_x,
int *new_y)
{
GList *windows;
@ -215,10 +252,6 @@ meta_window_place (MetaWindow *window,
*/
meta_topic (META_DEBUG_PLACEMENT, "Placing window %s\n", window->desc);
/* FIXME copying Mac, when placing a dialog
* put it at 1/5 down and horizontally centered
*/
if ((window->type == META_WINDOW_DIALOG ||
window->type == META_WINDOW_MODAL_DIALOG) &&
@ -244,6 +277,14 @@ meta_window_place (MetaWindow *window,
/* center of child over center of parent */
x -= window->rect.width / 2;
/* put child down 1/5 or so from the top of parent, unless
* it makes us have more of parent showing above child than
* below
*/
if (window->rect.height <= (parent->rect.height - (parent->rect.height / 5) * 2))
y += parent->rect.height / 5;
/* put top of child's frame, not top of child's client */
if (fgeom)
y += fgeom->top_height;
@ -264,16 +305,22 @@ meta_window_place (MetaWindow *window,
{
/* Center on screen */
int w, h;
const MetaXineramaScreenInfo *xi;
/* I think whole screen will look nicer than workarea */
w = window->screen->width;
h = window->screen->height;
xi = meta_screen_get_current_xinerama (window->screen);
w = xi->width;
h = xi->height;
x = (w - window->rect.width) / 2;
y = (h - window->rect.height) / 2;
meta_topic (META_DEBUG_PLACEMENT, "Centered window %s on screen\n",
window->desc);
x += xi->x_origin;
y += xi->y_origin;
meta_topic (META_DEBUG_PLACEMENT, "Centered window %s on screen %d xinerama %d\n",
window->desc, window->screen->number, xi->number);
goto done;
}
@ -313,6 +360,8 @@ meta_window_place (MetaWindow *window,
g_list_free (windows);
done:
constrain_placement (window, fgeom, x, y, &x, &y);
*new_x = x;
*new_y = y;
}

View File

@ -190,7 +190,7 @@ queue_changed (MetaPreference pref)
/* add idle at priority below the gconf notify idle */
if (changed_idle == 0)
changed_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 10,
changed_idle = g_idle_add_full (META_PRIORITY_PREFS_NOTIFY,
changed_idle_handler, NULL, NULL);
}

View File

@ -217,6 +217,8 @@ meta_screen_new (MetaDisplay *display,
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
screen->work_area_idle = 0;
screen->xinerama_infos = NULL;
screen->n_xinerama_infos = 0;
@ -351,6 +353,9 @@ meta_screen_free (MetaScreen *screen)
if (meta_error_trap_pop (screen->display) != Success)
meta_warning (_("Could not release screen %d on display '%s'\n"),
screen->number, screen->display->name);
if (screen->work_area_idle != 0)
g_source_remove (screen->work_area_idle);
g_free (screen->screen_name);
g_free (screen);
@ -778,3 +783,11 @@ meta_screen_focus_top_window (MetaScreen *screen,
meta_topic (META_DEBUG_FOCUS, "No top window to focus found\n");
}
}
const MetaXineramaScreenInfo*
meta_screen_get_current_xinerama (MetaScreen *screen)
{
/* FIXME how do we decide which is current? */
return &screen->xinerama_infos[0];
}

View File

@ -63,6 +63,8 @@ struct _MetaScreen
MetaXineramaScreenInfo *xinerama_infos;
int n_xinerama_infos;
guint work_area_idle;
guint keys_grabbed : 1;
};
@ -88,6 +90,8 @@ void meta_screen_ensure_tab_popup (MetaScreen *scree
void meta_screen_focus_top_window (MetaScreen *screen,
MetaWindow *not_this_one);
const MetaXineramaScreenInfo* meta_screen_get_current_xinerama (MetaScreen *screen);
#endif

View File

@ -866,6 +866,18 @@ meta_window_free (MetaWindow *window)
set_wm_state (window, WithdrawnState);
meta_error_trap_pop (window->display);
}
else
{
/* We need to put WM_STATE so that others will understand it on
* restart.
*/
if (!window->minimized)
{
meta_error_trap_push (window->display);
set_wm_state (window, NormalState);
meta_error_trap_pop (window->display);
}
}
if (window->frame)
meta_window_destroy_frame (window);
@ -1004,13 +1016,17 @@ meta_window_visible_on_workspace (MetaWindow *window,
void
meta_window_calc_showing (MetaWindow *window)
{
gboolean on_workspace;
gboolean showing, on_workspace;
meta_verbose ("Calc showing for window %s\n", window->desc);
/* 1. See if we're on the workspace */
on_workspace = meta_window_visible_on_workspace (window,
window->screen->active_workspace);
showing = on_workspace;
if (!on_workspace)
meta_verbose ("Window %s is not on workspace %d\n",
window->desc,
@ -1023,17 +1039,55 @@ meta_window_calc_showing (MetaWindow *window)
if (window->on_all_workspaces)
meta_verbose ("Window %s is on all workspaces\n", window->desc);
if (on_workspace &&
/* 2. See if we're minimized */
if (window->minimized)
showing = FALSE;
/* 3. See if we're in "show desktop" mode */
if (showing &&
window->display->showing_desktop &&
window->type != META_WINDOW_DESKTOP &&
window->type != META_WINDOW_DOCK)
{
meta_verbose ("Window %s is on current workspace, but we're showing the desktop\n",
window->desc);
on_workspace = FALSE;
showing = FALSE;
}
/* 4. See if an ancestor is minimized (note that
* ancestor's "mapped" field may not be up to date
* since it's being computed in this same idle queue)
*/
if (window->minimized || !on_workspace)
if (showing)
{
MetaWindow *w;
w = window;
while (w != NULL)
{
if (w->minimized)
{
showing = FALSE;
break;
}
if (w->xtransient_for == None)
break;
w = meta_display_lookup_x_window (w->display, w->xtransient_for);
if (w == window)
break; /* Cute, someone thought they'd make a transient_for cycle */
/* w may be null... */
}
}
/* Actually show/hide the window */
if (!showing)
{
/* Really this effects code should probably
* be in meta_window_hide so the window->mapped
@ -1385,6 +1439,13 @@ meta_window_hide (MetaWindow *window)
}
}
static void
queue_calc_showing_func (MetaWindow *window,
void *data)
{
meta_window_queue_calc_showing (window);
}
void
meta_window_minimize (MetaWindow *window)
{
@ -1392,6 +1453,11 @@ meta_window_minimize (MetaWindow *window)
{
window->minimized = TRUE;
meta_window_queue_calc_showing (window);
meta_window_foreach_transient (window,
queue_calc_showing_func,
NULL);
if (window->has_focus)
{
meta_topic (META_DEBUG_FOCUS,
@ -1418,6 +1484,10 @@ meta_window_unminimize (MetaWindow *window)
{
window->minimized = FALSE;
meta_window_queue_calc_showing (window);
meta_window_foreach_transient (window,
queue_calc_showing_func,
NULL);
}
}
@ -1590,6 +1660,28 @@ meta_window_unshade (MetaWindow *window)
}
}
static void
unminimize_window_and_all_transient_parents (MetaWindow *window)
{
MetaWindow *w;
w = window;
while (w != NULL)
{
meta_window_unminimize (w);
if (w->xtransient_for == None)
break;
w = meta_display_lookup_x_window (w->display, w->xtransient_for);
if (w == window)
break; /* Cute, someone thought they'd make a transient_for cycle */
/* w may be null... */
}
}
void
meta_window_activate (MetaWindow *window,
guint32 timestamp)
@ -1609,8 +1701,7 @@ meta_window_activate (MetaWindow *window,
if (window->shaded)
meta_window_unshade (window);
if (window->minimized)
meta_window_unminimize (window);
unminimize_window_and_all_transient_parents (window);
meta_window_raise (window);
meta_topic (META_DEBUG_FOCUS,
@ -5578,3 +5669,56 @@ meta_window_refresh_resize_popup (MetaWindow *window)
TRUE);
}
}
void
meta_window_foreach_transient (MetaWindow *window,
MetaWindowForeachFunc func,
void *data)
{
GSList *windows;
GSList *tmp;
windows = meta_display_list_windows (window->display);
tmp = windows;
while (tmp != NULL)
{
MetaWindow *transient = tmp->data;
if (meta_window_is_ancestor_of_transient (window, transient))
(* func) (transient, data);
tmp = tmp->next;
}
g_slist_free (windows);
}
gboolean
meta_window_is_ancestor_of_transient (MetaWindow *window,
MetaWindow *transient)
{
MetaWindow *w;
if (window == transient)
return FALSE;
w = transient;
while (w != NULL)
{
if (w->xtransient_for == None)
return FALSE;
if (w->xtransient_for == window->xwindow)
return TRUE;
w = meta_display_lookup_x_window (w->display, w->xtransient_for);
if (w == transient)
return FALSE; /* Cycle */
/* w may be null... */
}
return FALSE;
}

View File

@ -29,6 +29,8 @@
#include <X11/Xutil.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
typedef void (*MetaWindowForeachFunc) (MetaWindow *window,
void *data);
typedef enum
{
@ -383,4 +385,10 @@ void meta_window_refresh_resize_popup (MetaWindow *window);
void meta_window_free_delete_dialog (MetaWindow *window);
void meta_window_foreach_transient (MetaWindow *window,
MetaWindowForeachFunc func,
void *data);
gboolean meta_window_is_ancestor_of_transient (MetaWindow *window,
MetaWindow *transient);
#endif

View File

@ -27,7 +27,7 @@ void meta_workspace_queue_calc_showing (MetaWorkspace *workspace);
static int set_number_of_spaces_hint (MetaScreen *screen);
static int set_active_space_hint (MetaScreen *screen);
static int set_workarea_hint (MetaScreen *screen);
static int set_work_area_hint (MetaScreen *screen);
MetaWorkspace*
meta_workspace_new (MetaScreen *screen)
@ -314,43 +314,6 @@ set_number_of_spaces_hint (MetaScreen *screen)
return meta_error_trap_pop (screen->display);
}
static int
set_workarea_hint (MetaScreen *screen)
{
int num_workspaces;
GList *tmp_list;
unsigned long *data, *tmp;
MetaRectangle area;
num_workspaces = g_list_length (screen->display->workspaces);
data = g_new (unsigned long, num_workspaces);
tmp_list = screen->display->workspaces;
tmp = data;
while (tmp_list != NULL)
{
MetaWorkspace *workspace = tmp_list->data;
meta_workspace_get_work_area (workspace, &area);
tmp[0] = area.x;
tmp[1] = area.y;
tmp[2] = area.width;
tmp[3] = area.height;
tmp += sizeof (unsigned long) * 4;
tmp_list = tmp_list->next;
}
meta_error_trap_push (screen->display);
XChangeProperty (screen->display->xdisplay, screen->xroot,
screen->display->atom_net_wm_workarea,
XA_CARDINAL, 32, PropModeReplace,
(guchar*) data, num_workspaces * 4);
g_free (data);
return meta_error_trap_pop (screen->display);
}
static int
set_active_space_hint (MetaScreen *screen)
{
@ -368,6 +331,63 @@ set_active_space_hint (MetaScreen *screen)
return meta_error_trap_pop (screen->display);
}
static int
set_work_area_hint (MetaScreen *screen)
{
int num_workspaces;
GList *tmp_list;
unsigned long *data, *tmp;
MetaRectangle area;
num_workspaces = meta_screen_get_n_workspaces (screen);
data = g_new (unsigned long, num_workspaces * 4);
tmp_list = screen->display->workspaces;
tmp = data;
while (tmp_list != NULL)
{
MetaWorkspace *workspace = tmp_list->data;
if (workspace->screen == screen)
{
meta_workspace_get_work_area (workspace, &area);
tmp[0] = area.x;
tmp[1] = area.y;
tmp[2] = area.width;
tmp[3] = area.height;
}
tmp += 4;
tmp_list = tmp_list->next;
}
meta_error_trap_push (screen->display);
XChangeProperty (screen->display->xdisplay, screen->xroot,
screen->display->atom_net_wm_workarea,
XA_CARDINAL, 32, PropModeReplace,
(guchar*) data, num_workspaces*4);
g_free (data);
return meta_error_trap_pop (screen->display);
}
static gboolean
set_work_area_idle_func (void *data)
{
MetaScreen *screen;
meta_topic (META_DEBUG_WORKAREA,
"Running work area idle function\n");
screen = data;
screen->work_area_idle = 0;
set_work_area_hint (screen);
return FALSE;
}
void
meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
{
@ -401,6 +421,18 @@ meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
}
g_list_free (windows);
/* Recompute work area in an idle */
if (workspace->screen->work_area_idle == 0)
{
meta_topic (META_DEBUG_WORKAREA,
"Adding work area hint idle function\n");
workspace->screen->work_area_idle =
g_idle_add_full (META_PRIORITY_WORK_AREA_HINT,
set_work_area_idle_func,
workspace->screen,
NULL);
}
}
void