mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 15:40:41 -05:00
store strut information, update it on property changes, etc. etc. so we
2002-01-09 Havoc Pennington <hp@pobox.com> * src/window.c, src/window.h: store strut information, update it on property changes, etc. etc. so we avoid panel on maximize. * src/workspace.c (meta_workspace_get_work_area): add accessor for work area so we can compute it lazily * src/display.h, src/display.c: add _NET_WM_STRUT atom and _WIN_HINTS atom
This commit is contained in:
parent
da6ded6f3f
commit
b2bbb306f4
12
ChangeLog
12
ChangeLog
@ -1,3 +1,15 @@
|
||||
2002-01-09 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/window.c, src/window.h: store strut information,
|
||||
update it on property changes, etc. etc. so we avoid panel
|
||||
on maximize.
|
||||
|
||||
* src/workspace.c (meta_workspace_get_work_area): add accessor for
|
||||
work area so we can compute it lazily
|
||||
|
||||
* src/display.h, src/display.c: add _NET_WM_STRUT atom
|
||||
and _WIN_HINTS atom
|
||||
|
||||
2002-01-08 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* configure.in (ACLOCAL): add code to save ACLOCAL_FLAGS
|
||||
|
@ -139,7 +139,9 @@ meta_display_open (const char *name)
|
||||
"_KWM_WIN_ICON",
|
||||
"_NET_WM_MOVERESIZE",
|
||||
"_NET_ACTIVE_WINDOW",
|
||||
"_METACITY_RESTART_MESSAGE"
|
||||
"_METACITY_RESTART_MESSAGE",
|
||||
"_NET_WM_STRUT",
|
||||
"_WIN_HINTS"
|
||||
};
|
||||
Atom atoms[G_N_ELEMENTS(atom_names)];
|
||||
|
||||
@ -230,6 +232,8 @@ meta_display_open (const char *name)
|
||||
display->atom_net_wm_moveresize = atoms[42];
|
||||
display->atom_net_active_window = atoms[43];
|
||||
display->atom_metacity_restart_message = atoms[44];
|
||||
display->atom_net_wm_strut = atoms[45];
|
||||
display->atom_win_hints = atoms[46];
|
||||
|
||||
/* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK,
|
||||
* created in screen_new
|
||||
|
@ -104,6 +104,8 @@ struct _MetaDisplay
|
||||
Atom atom_net_wm_moveresize;
|
||||
Atom atom_net_active_window;
|
||||
Atom atom_metacity_restart_message;
|
||||
Atom atom_net_wm_strut;
|
||||
Atom atom_win_hints;
|
||||
|
||||
/* This is the actual window from focus events,
|
||||
* not the one we last set
|
||||
|
35
src/place.c
35
src/place.c
@ -85,6 +85,7 @@ find_next_cascade (MetaWindow *window,
|
||||
GList *sorted;
|
||||
int cascade_x, cascade_y;
|
||||
int x_threshold, y_threshold;
|
||||
MetaRectangle work_area;
|
||||
|
||||
sorted = g_list_copy (windows);
|
||||
sorted = g_list_sort (sorted, northwestcmp);
|
||||
@ -99,18 +100,10 @@ find_next_cascade (MetaWindow *window,
|
||||
* cascade_x, cascade_y are the target position
|
||||
* of NW corner of window frame.
|
||||
*/
|
||||
cascade_x = 0;
|
||||
cascade_y = 0;
|
||||
tmp = window->workspaces;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWorkspace *space = tmp->data;
|
||||
|
||||
cascade_x = MAX (cascade_x, space->workarea.x);
|
||||
cascade_y = MAX (cascade_y, space->workarea.y);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
meta_window_get_work_area (window, &work_area);
|
||||
|
||||
cascade_x = MAX (0, work_area.x);
|
||||
cascade_y = MAX (0, work_area.y);
|
||||
|
||||
/* Find first cascade position that's not used. */
|
||||
|
||||
@ -445,6 +438,7 @@ get_vertical_edges (MetaWindow *window,
|
||||
int i;
|
||||
int n_edges;
|
||||
MetaRectangle rect;
|
||||
MetaRectangle work_area;
|
||||
|
||||
windows = get_windows_on_same_workspace (window, &n_windows);
|
||||
|
||||
@ -453,11 +447,13 @@ get_vertical_edges (MetaWindow *window,
|
||||
edges = g_new (int, n_edges);
|
||||
|
||||
/* workspace/screen edges */
|
||||
edges[i] = window->screen->active_workspace->workarea.x;
|
||||
meta_window_get_work_area (window, &work_area);
|
||||
|
||||
edges[i] = work_area.x;
|
||||
++i;
|
||||
edges[i] =
|
||||
window->screen->active_workspace->workarea.x +
|
||||
window->screen->active_workspace->workarea.width;
|
||||
work_area.x +
|
||||
work_area.width;
|
||||
++i;
|
||||
edges[i] = 0;
|
||||
++i;
|
||||
@ -508,6 +504,7 @@ get_horizontal_edges (MetaWindow *window,
|
||||
int i;
|
||||
int n_edges;
|
||||
MetaRectangle rect;
|
||||
MetaRectangle work_area;
|
||||
|
||||
windows = get_windows_on_same_workspace (window, &n_windows);
|
||||
|
||||
@ -516,11 +513,13 @@ get_horizontal_edges (MetaWindow *window,
|
||||
edges = g_new (int, n_edges);
|
||||
|
||||
/* workspace/screen edges */
|
||||
edges[i] = window->screen->active_workspace->workarea.y;
|
||||
meta_window_get_work_area (window, &work_area);
|
||||
|
||||
edges[i] = work_area.y;
|
||||
++i;
|
||||
edges[i] =
|
||||
window->screen->active_workspace->workarea.y +
|
||||
window->screen->active_workspace->workarea.height;
|
||||
work_area.y +
|
||||
work_area.height;
|
||||
++i;
|
||||
edges[i] = 0;
|
||||
++i;
|
||||
|
309
src/window.c
309
src/window.c
@ -43,6 +43,16 @@ typedef enum
|
||||
META_USER_MOVE_RESIZE = 1 << 2
|
||||
} MetaMoveResizeFlags;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
WIN_HINTS_SKIP_FOCUS = (1<<0), /* "alt-tab" skips this win */
|
||||
WIN_HINTS_SKIP_WINLIST = (1<<1), /* not in win list */
|
||||
WIN_HINTS_SKIP_TASKBAR = (1<<2), /* not on taskbar */
|
||||
WIN_HINTS_GROUP_TRANSIENT = (1<<3), /* ??????? */
|
||||
WIN_HINTS_FOCUS_ON_CLICK = (1<<4), /* app only accepts focus when clicked */
|
||||
WIN_HINTS_DO_NOT_COVER = (1<<5) /* attempt to not cover this window */
|
||||
} GnomeWinHints;
|
||||
|
||||
static void constrain_size (MetaWindow *window,
|
||||
MetaFrameGeometry *fgeom,
|
||||
int width,
|
||||
@ -72,8 +82,11 @@ static int update_icon_name (MetaWindow *window);
|
||||
static int update_icon (MetaWindow *window,
|
||||
gboolean reread_rgb_icon);
|
||||
static int update_kwm_icon (MetaWindow *window);
|
||||
static void update_struts (MetaWindow *window);
|
||||
static void recalc_window_type (MetaWindow *window);
|
||||
static void recalc_window_features (MetaWindow *window);
|
||||
static void recalc_do_not_cover_struts(MetaWindow *window);
|
||||
static void invalidate_work_areas (MetaWindow *window);
|
||||
static int set_wm_state (MetaWindow *window,
|
||||
int state);
|
||||
static int set_net_wm_state (MetaWindow *window);
|
||||
@ -83,6 +96,8 @@ static gboolean process_property_notify (MetaWindow *window,
|
||||
static void meta_window_show (MetaWindow *window);
|
||||
static void meta_window_hide (MetaWindow *window);
|
||||
|
||||
static GList* meta_window_get_workspaces (MetaWindow *window);
|
||||
|
||||
static gboolean meta_window_get_icon_geometry (MetaWindow *window,
|
||||
MetaRectangle *rect);
|
||||
|
||||
@ -350,6 +365,12 @@ meta_window_new (MetaDisplay *display, Window xwindow,
|
||||
window->type = META_WINDOW_NORMAL;
|
||||
window->type_atom = None;
|
||||
|
||||
window->has_struts = FALSE;
|
||||
window->left_strut = 0;
|
||||
window->right_strut = 0;
|
||||
window->top_strut = 0;
|
||||
window->bottom_strut = 0;
|
||||
|
||||
window->layer = META_LAYER_NORMAL;
|
||||
window->stack_op = NULL;
|
||||
window->initial_workspace = 0; /* not used */
|
||||
@ -359,6 +380,7 @@ meta_window_new (MetaDisplay *display, Window xwindow,
|
||||
update_title (window);
|
||||
update_protocols (window);
|
||||
update_wm_hints (window);
|
||||
update_struts (window);
|
||||
|
||||
update_net_wm_state (window);
|
||||
/* Initially maximize if window is fullscreen; FIXME
|
||||
@ -1193,6 +1215,8 @@ meta_window_maximize (MetaWindow *window)
|
||||
{
|
||||
if (!window->maximized)
|
||||
{
|
||||
meta_verbose ("Maximizing %s\n", window->desc);
|
||||
|
||||
window->maximized = TRUE;
|
||||
|
||||
meta_window_raise (window);
|
||||
@ -1218,6 +1242,8 @@ meta_window_unmaximize (MetaWindow *window)
|
||||
{
|
||||
if (window->maximized)
|
||||
{
|
||||
meta_verbose ("Unmaximizing %s\n", window->desc);
|
||||
|
||||
window->maximized = FALSE;
|
||||
|
||||
meta_window_move_resize (window,
|
||||
@ -1660,7 +1686,7 @@ meta_window_move_resize_internal (MetaWindow *window,
|
||||
window->frame->right_width = fgeom.right_width;
|
||||
window->frame->bottom_height = fgeom.bottom_height;
|
||||
}
|
||||
|
||||
|
||||
/* See ICCCM 4.1.5 for when to send ConfigureNotify */
|
||||
|
||||
need_configure_notify = FALSE;
|
||||
@ -1756,6 +1782,19 @@ meta_window_move_resize_internal (MetaWindow *window,
|
||||
{
|
||||
meta_verbose ("Size/position not modified\n");
|
||||
}
|
||||
|
||||
/* Update struts for new window size */
|
||||
if (window->do_not_cover && (need_resize_client || need_move_client))
|
||||
{
|
||||
recalc_do_not_cover_struts (window);
|
||||
|
||||
/* Does a resize on all windows on entire current workspace,
|
||||
* would be an infinite loop except for need_resize_client
|
||||
* above.
|
||||
*/
|
||||
|
||||
invalidate_work_areas (window);
|
||||
}
|
||||
|
||||
/* Invariants leaving this function are:
|
||||
* a) window->rect and frame->rect reflect the actual
|
||||
@ -2636,6 +2675,44 @@ meta_window_client_message (MetaWindow *window,
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->xclient.message_type ==
|
||||
display->atom_win_hints)
|
||||
{
|
||||
/* gnome-winhints.c seems to indicate that the hints are
|
||||
* in l[1], though god knows why it's like that
|
||||
*/
|
||||
gulong data[1];
|
||||
|
||||
meta_verbose ("_WIN_HINTS client message, hints: %ld\n",
|
||||
event->xclient.data.l[1]);
|
||||
|
||||
if (event->xclient.data.l[1] & WIN_HINTS_DO_NOT_COVER)
|
||||
{
|
||||
meta_verbose ("Setting WIN_HINTS_DO_NOT_COVER\n");
|
||||
|
||||
data[0] = WIN_HINTS_DO_NOT_COVER;
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
XChangeProperty (window->display->xdisplay,
|
||||
window->xwindow, window->display->atom_win_hints,
|
||||
XA_CARDINAL, 32, PropModeReplace,
|
||||
(unsigned char *)data, 1);
|
||||
meta_error_trap_pop (window->display);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_verbose ("Unsetting WIN_HINTS_DO_NOT_COVER\n");
|
||||
|
||||
data[0] = 0;
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
XDeleteProperty (window->display->xdisplay,
|
||||
window->xwindow, window->display->atom_win_hints);
|
||||
meta_error_trap_pop (window->display);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@ -2858,6 +2935,16 @@ process_property_notify (MetaWindow *window,
|
||||
update_kwm_icon (window);
|
||||
update_icon (window, FALSE);
|
||||
}
|
||||
else if (event->atom == window->display->atom_net_wm_strut)
|
||||
{
|
||||
meta_verbose ("Property notify on %s for _NET_WM_STRUT\n", window->desc);
|
||||
update_struts (window);
|
||||
}
|
||||
else if (event->atom == window->display->atom_win_hints)
|
||||
{
|
||||
meta_verbose ("Property notify on %s for _WIN_HINTS\n", window->desc);
|
||||
update_struts (window);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -4377,6 +4464,166 @@ update_kwm_icon (MetaWindow *window)
|
||||
return Success;
|
||||
}
|
||||
|
||||
static GList*
|
||||
meta_window_get_workspaces (MetaWindow *window)
|
||||
{
|
||||
if (window->on_all_workspaces)
|
||||
return window->display->workspaces;
|
||||
else
|
||||
return window->workspaces;
|
||||
}
|
||||
|
||||
static void
|
||||
invalidate_work_areas (MetaWindow *window)
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
tmp = meta_window_get_workspaces (window);
|
||||
|
||||
while (tmp != NULL)
|
||||
{
|
||||
meta_workspace_invalidate_work_area (tmp->data);
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_struts (MetaWindow *window)
|
||||
{
|
||||
gulong *struts = NULL;
|
||||
int nitems;
|
||||
|
||||
meta_verbose ("Updating struts for %s\n", window->desc);
|
||||
|
||||
window->has_struts = FALSE;
|
||||
window->do_not_cover = FALSE;
|
||||
window->left_strut = 0;
|
||||
window->right_strut = 0;
|
||||
window->top_strut = 0;
|
||||
window->bottom_strut = 0;
|
||||
|
||||
if (meta_prop_get_cardinal_list (window->display,
|
||||
window->xwindow,
|
||||
window->display->atom_net_wm_strut,
|
||||
&struts, &nitems))
|
||||
{
|
||||
if (nitems != 4)
|
||||
{
|
||||
meta_verbose ("_NET_WM_STRUT on %s has %d values instead of 4\n",
|
||||
window->desc, nitems);
|
||||
meta_XFree (struts);
|
||||
}
|
||||
|
||||
window->has_struts = TRUE;
|
||||
window->left_strut = struts[0];
|
||||
window->right_strut = struts[1];
|
||||
window->top_strut = struts[2];
|
||||
window->bottom_strut = struts[3];
|
||||
|
||||
meta_verbose ("Using _NET_WM_STRUT struts %d %d %d %d for window %s\n",
|
||||
window->left_strut, window->right_strut,
|
||||
window->top_strut, window->bottom_strut,
|
||||
window->desc);
|
||||
|
||||
meta_XFree (struts);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_verbose ("No _NET_WM_STRUT property for %s\n",
|
||||
window->desc);
|
||||
}
|
||||
|
||||
if (!window->has_struts)
|
||||
{
|
||||
/* Try _WIN_HINTS */
|
||||
gulong hints;
|
||||
|
||||
if (meta_prop_get_cardinal (window->display,
|
||||
window->xwindow,
|
||||
window->display->atom_win_hints,
|
||||
&hints))
|
||||
{
|
||||
if (hints & WIN_HINTS_DO_NOT_COVER)
|
||||
{
|
||||
window->has_struts = TRUE;
|
||||
window->do_not_cover = TRUE;
|
||||
recalc_do_not_cover_struts (window);
|
||||
|
||||
meta_verbose ("Using _WIN_HINTS struts %d %d %d %d for window %s\n",
|
||||
window->left_strut, window->right_strut,
|
||||
window->top_strut, window->bottom_strut,
|
||||
window->desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_verbose ("DO_NOT_COVER hint not set in _WIN_HINTS\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_verbose ("No _WIN_HINTS property on %s\n",
|
||||
window->desc);
|
||||
}
|
||||
}
|
||||
|
||||
invalidate_work_areas (window);
|
||||
}
|
||||
|
||||
static void
|
||||
recalc_do_not_cover_struts (MetaWindow *window)
|
||||
{
|
||||
if (window->do_not_cover)
|
||||
{
|
||||
/* We only understand windows that are aligned to
|
||||
* a screen edge
|
||||
*/
|
||||
gboolean horizontal;
|
||||
gboolean on_left_edge;
|
||||
gboolean on_right_edge;
|
||||
gboolean on_bottom_edge;
|
||||
gboolean on_top_edge;
|
||||
|
||||
window->left_strut = 0;
|
||||
window->right_strut = 0;
|
||||
window->top_strut = 0;
|
||||
window->bottom_strut = 0;
|
||||
|
||||
on_left_edge = window->rect.x == 0;
|
||||
on_right_edge = (window->rect.x + window->rect.width) ==
|
||||
window->screen->width;
|
||||
on_top_edge = window->rect.y == 0;
|
||||
on_bottom_edge = (window->rect.y + window->rect.height) ==
|
||||
window->screen->height;
|
||||
|
||||
/* cheesy heuristic to decide where the strut goes */
|
||||
if (on_left_edge && on_right_edge && on_bottom_edge)
|
||||
horizontal = TRUE;
|
||||
else if (on_left_edge && on_right_edge && on_top_edge)
|
||||
horizontal = TRUE;
|
||||
else if (on_top_edge && on_bottom_edge && on_left_edge)
|
||||
horizontal = FALSE;
|
||||
else if (on_top_edge && on_bottom_edge && on_right_edge)
|
||||
horizontal = FALSE;
|
||||
else
|
||||
horizontal = window->rect.width > window->rect.height;
|
||||
|
||||
if (horizontal)
|
||||
{
|
||||
if (on_top_edge)
|
||||
window->top_strut = window->rect.height;
|
||||
else if (on_bottom_edge)
|
||||
window->bottom_strut = window->rect.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (on_left_edge)
|
||||
window->left_strut = window->rect.width;
|
||||
else if (on_right_edge)
|
||||
window->right_strut = window->rect.width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
recalc_window_type (MetaWindow *window)
|
||||
{
|
||||
@ -4499,10 +4746,13 @@ constrain_size (MetaWindow *window,
|
||||
int delta;
|
||||
double min_aspect, max_aspect;
|
||||
int minw, minh, maxw, maxh, fullw, fullh;
|
||||
|
||||
MetaRectangle work_area;
|
||||
|
||||
/* frame member variables should NEVER be used in here */
|
||||
|
||||
#define FLOOR(value, base) ( ((int) ((value) / (base))) * (base) )
|
||||
|
||||
meta_window_get_work_area (window, &work_area);
|
||||
|
||||
/* Get the allowed size ranges, considering maximized, etc. */
|
||||
if (window->type == META_WINDOW_DESKTOP ||
|
||||
@ -4513,8 +4763,8 @@ constrain_size (MetaWindow *window,
|
||||
}
|
||||
else
|
||||
{
|
||||
fullw = window->screen->active_workspace->workarea.width;
|
||||
fullh = window->screen->active_workspace->workarea.height;
|
||||
fullw = work_area.width;
|
||||
fullh = work_area.height;
|
||||
}
|
||||
|
||||
if (window->frame)
|
||||
@ -4620,6 +4870,10 @@ constrain_position (MetaWindow *window,
|
||||
int *new_x,
|
||||
int *new_y)
|
||||
{
|
||||
MetaRectangle work_area;
|
||||
|
||||
meta_window_get_work_area (window, &work_area);
|
||||
|
||||
/* frame member variables should NEVER be used in here, only
|
||||
* MetaFrameGeometry
|
||||
*/
|
||||
@ -4644,8 +4898,8 @@ constrain_position (MetaWindow *window,
|
||||
/* find furthest northwest point the window can occupy,
|
||||
* to disallow moving titlebar off the top or left
|
||||
*/
|
||||
nw_x = window->screen->active_workspace->workarea.x;
|
||||
nw_y = window->screen->active_workspace->workarea.y;
|
||||
nw_x = work_area.x;
|
||||
nw_y = work_area.y;
|
||||
if (window->frame)
|
||||
{
|
||||
nw_x += fgeom->left_width;
|
||||
@ -4653,10 +4907,8 @@ constrain_position (MetaWindow *window,
|
||||
}
|
||||
|
||||
/* find bottom-right corner of workarea */
|
||||
se_x = window->screen->active_workspace->workarea.x +
|
||||
window->screen->active_workspace->workarea.width;
|
||||
se_y = window->screen->active_workspace->workarea.y +
|
||||
window->screen->active_workspace->workarea.height;
|
||||
se_x = work_area.x + work_area.width;
|
||||
se_y = work_area.y + work_area.height;
|
||||
|
||||
/* if the window's size exceeds the screen size,
|
||||
* we allow it to go off the top/left far enough
|
||||
@ -5181,3 +5433,40 @@ meta_window_set_gravity (MetaWindow *window,
|
||||
|
||||
meta_error_trap_pop (window->display);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_get_work_area (MetaWindow *window,
|
||||
MetaRectangle *area)
|
||||
{
|
||||
MetaRectangle space_area;
|
||||
GList *tmp;
|
||||
|
||||
int left_strut = 0;
|
||||
int right_strut = 0;
|
||||
int top_strut = 0;
|
||||
int bottom_strut = 0;
|
||||
|
||||
tmp = meta_window_get_workspaces (window);
|
||||
|
||||
while (tmp != NULL)
|
||||
{
|
||||
meta_workspace_get_work_area (tmp->data, &space_area);
|
||||
|
||||
left_strut = MAX (left_strut, space_area.x);
|
||||
right_strut = MAX (right_strut,
|
||||
(window->screen->width - space_area.x - space_area.width));
|
||||
top_strut = MAX (top_strut, space_area.y);
|
||||
bottom_strut = MAX (bottom_strut,
|
||||
(window->screen->height - space_area.y - space_area.height));
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
area->x = left_strut;
|
||||
area->y = top_strut;
|
||||
area->width = window->screen->width - left_strut - right_strut;
|
||||
area->height = window->screen->height - top_strut - bottom_strut;
|
||||
|
||||
meta_verbose ("Window %s has work area %d,%d %d x %d\n",
|
||||
window->desc, area->x, area->y, area->width, area->height);
|
||||
}
|
||||
|
15
src/window.h
15
src/window.h
@ -183,6 +183,11 @@ struct _MetaWindow
|
||||
* only relevant if !window->placed
|
||||
*/
|
||||
guint calc_placement : 1;
|
||||
|
||||
/* Has nonzero struts */
|
||||
guint has_struts : 1;
|
||||
/* Struts are from the _WIN_HINTS do not cover deal */
|
||||
guint do_not_cover : 1;
|
||||
|
||||
/* Number of UnmapNotify that are caused by us, if
|
||||
* we get UnmapNotify with none pending then the client
|
||||
@ -220,6 +225,12 @@ struct _MetaWindow
|
||||
/* x/y/w/h here get filled with ConfigureRequest values */
|
||||
XSizeHints size_hints;
|
||||
|
||||
/* struts */
|
||||
int left_strut;
|
||||
int right_strut;
|
||||
int top_strut;
|
||||
int bottom_strut;
|
||||
|
||||
/* Managed by stack.c */
|
||||
MetaStackLayer layer;
|
||||
MetaStackOp *stack_op;
|
||||
@ -342,4 +353,8 @@ void meta_window_handle_mouse_grab_op_event (MetaWindow *window,
|
||||
gboolean meta_window_visible_on_workspace (MetaWindow *window,
|
||||
MetaWorkspace *workspace);
|
||||
|
||||
/* Get minimum work area for all workspaces we're on */
|
||||
void meta_window_get_work_area (MetaWindow *window,
|
||||
MetaRectangle *area);
|
||||
|
||||
#endif
|
||||
|
147
src/workspace.c
147
src/workspace.c
@ -40,14 +40,12 @@ meta_workspace_new (MetaScreen *screen)
|
||||
g_list_append (workspace->screen->display->workspaces, workspace);
|
||||
workspace->windows = NULL;
|
||||
|
||||
/* This may have something to do with the strut hints
|
||||
* eventually
|
||||
*/
|
||||
workspace->workarea.x = 0;
|
||||
workspace->workarea.y = 0;
|
||||
workspace->workarea.width = screen->width;
|
||||
workspace->workarea.height = screen->height;
|
||||
|
||||
workspace->work_area.x = 0;
|
||||
workspace->work_area.y = 0;
|
||||
workspace->work_area.width = screen->width;
|
||||
workspace->work_area.height = screen->height;
|
||||
workspace->work_area_invalid = TRUE;
|
||||
|
||||
/* Update hint for current number of workspaces */
|
||||
set_number_of_spaces_hint (screen);
|
||||
|
||||
@ -105,6 +103,13 @@ meta_workspace_add_window (MetaWorkspace *workspace,
|
||||
meta_window_set_current_workspace_hint (window);
|
||||
|
||||
meta_window_queue_calc_showing (window);
|
||||
if (window->has_struts)
|
||||
meta_workspace_invalidate_work_area (workspace);
|
||||
|
||||
/* queue a move_resize since changing workspaces may change
|
||||
* the relevant struts
|
||||
*/
|
||||
meta_window_queue_move_resize (window);
|
||||
}
|
||||
|
||||
void
|
||||
@ -119,6 +124,14 @@ meta_workspace_remove_window (MetaWorkspace *workspace,
|
||||
meta_window_set_current_workspace_hint (window);
|
||||
|
||||
meta_window_queue_calc_showing (window);
|
||||
|
||||
if (window->has_struts)
|
||||
meta_workspace_invalidate_work_area (workspace);
|
||||
|
||||
/* queue a move_resize since changing workspaces may change
|
||||
* the relevant struts
|
||||
*/
|
||||
meta_window_queue_move_resize (window);
|
||||
}
|
||||
|
||||
void
|
||||
@ -242,6 +255,37 @@ meta_workspace_screen_index (MetaWorkspace *workspace)
|
||||
meta_bug ("Workspace does not exist to index!\n");
|
||||
}
|
||||
|
||||
/* get windows contained on workspace, including workspace->windows
|
||||
* and also sticky windows.
|
||||
*/
|
||||
GList*
|
||||
meta_workspace_list_windows (MetaWorkspace *workspace)
|
||||
{
|
||||
GSList *display_windows;
|
||||
GSList *tmp;
|
||||
GList *workspace_windows;
|
||||
|
||||
display_windows = meta_display_list_windows (workspace->screen->display);
|
||||
|
||||
workspace_windows = NULL;
|
||||
tmp = display_windows;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWindow *window = tmp->data;
|
||||
|
||||
if (window->on_all_workspaces ||
|
||||
meta_workspace_contains_window (workspace, window))
|
||||
workspace_windows = g_list_prepend (workspace_windows,
|
||||
window);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
g_slist_free (display_windows);
|
||||
|
||||
return workspace_windows;
|
||||
}
|
||||
|
||||
static int
|
||||
set_number_of_spaces_hint (MetaScreen *screen)
|
||||
{
|
||||
@ -275,3 +319,90 @@ set_active_space_hint (MetaScreen *screen)
|
||||
32, PropModeReplace, (guchar*) data, 1);
|
||||
return meta_error_trap_pop (screen->display);
|
||||
}
|
||||
|
||||
void
|
||||
meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
if (workspace->work_area_invalid)
|
||||
return;
|
||||
|
||||
workspace->work_area_invalid = TRUE;
|
||||
|
||||
/* redo the size/position constraints on all windows */
|
||||
tmp = workspace->windows;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWindow *w = tmp->data;
|
||||
|
||||
meta_window_queue_move_resize (w);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_workspace_get_work_area (MetaWorkspace *workspace,
|
||||
MetaRectangle *area)
|
||||
{
|
||||
if (workspace->work_area_invalid)
|
||||
{
|
||||
int left_strut = 0;
|
||||
int right_strut = 0;
|
||||
int top_strut = 0;
|
||||
int bottom_strut = 0;
|
||||
GList *tmp;
|
||||
GList *windows;
|
||||
|
||||
windows = meta_workspace_list_windows (workspace);
|
||||
tmp = windows;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWindow *w = tmp->data;
|
||||
|
||||
if (w->has_struts)
|
||||
{
|
||||
left_strut = MAX (left_strut, w->left_strut);
|
||||
right_strut = MAX (right_strut, w->right_strut);
|
||||
top_strut = MAX (top_strut, w->top_strut);
|
||||
bottom_strut = MAX (bottom_strut, w->bottom_strut);
|
||||
}
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
g_list_free (windows);
|
||||
|
||||
/* Some paranoid robustness */
|
||||
#define MIN_SANE_AREA 100
|
||||
|
||||
if ((left_strut + right_strut) > (workspace->screen->width - MIN_SANE_AREA))
|
||||
{
|
||||
left_strut = (workspace->screen->width - MIN_SANE_AREA) / 2;
|
||||
right_strut = left_strut;
|
||||
}
|
||||
|
||||
if ((top_strut + bottom_strut) > (workspace->screen->height - MIN_SANE_AREA))
|
||||
{
|
||||
top_strut = (workspace->screen->height - MIN_SANE_AREA) / 2;
|
||||
bottom_strut = top_strut;
|
||||
}
|
||||
|
||||
workspace->work_area.x = left_strut;
|
||||
workspace->work_area.y = top_strut;
|
||||
workspace->work_area.width = workspace->screen->width - left_strut - right_strut;
|
||||
workspace->work_area.height = workspace->screen->height - top_strut - bottom_strut;
|
||||
|
||||
workspace->work_area_invalid = FALSE;
|
||||
|
||||
meta_verbose ("Workspace %d has work area %d,%d %d x %d\n",
|
||||
meta_workspace_index (workspace),
|
||||
workspace->work_area.x,
|
||||
workspace->work_area.y,
|
||||
workspace->work_area.width,
|
||||
workspace->work_area.height);
|
||||
}
|
||||
|
||||
*area = workspace->work_area;
|
||||
}
|
||||
|
@ -30,7 +30,8 @@ struct _MetaWorkspace
|
||||
|
||||
GList *windows;
|
||||
|
||||
MetaRectangle workarea;
|
||||
MetaRectangle work_area;
|
||||
guint work_area_invalid : 1;
|
||||
};
|
||||
|
||||
MetaWorkspace* meta_workspace_new (MetaScreen *screen);
|
||||
@ -47,6 +48,12 @@ gboolean meta_workspace_contains_window (MetaWorkspace *workspace,
|
||||
void meta_workspace_activate (MetaWorkspace *workspace);
|
||||
int meta_workspace_index (MetaWorkspace *workspace);
|
||||
int meta_workspace_screen_index (MetaWorkspace *workspace);
|
||||
GList* meta_workspace_list_windows (MetaWorkspace *workspace);
|
||||
|
||||
void meta_workspace_invalidate_work_area (MetaWorkspace *workspace);
|
||||
void meta_workspace_get_work_area (MetaWorkspace *workspace,
|
||||
MetaRectangle *area);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user