mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 23:50: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>
|
2002-01-08 Havoc Pennington <hp@pobox.com>
|
||||||
|
|
||||||
* configure.in (ACLOCAL): add code to save ACLOCAL_FLAGS
|
* configure.in (ACLOCAL): add code to save ACLOCAL_FLAGS
|
||||||
|
@ -139,7 +139,9 @@ meta_display_open (const char *name)
|
|||||||
"_KWM_WIN_ICON",
|
"_KWM_WIN_ICON",
|
||||||
"_NET_WM_MOVERESIZE",
|
"_NET_WM_MOVERESIZE",
|
||||||
"_NET_ACTIVE_WINDOW",
|
"_NET_ACTIVE_WINDOW",
|
||||||
"_METACITY_RESTART_MESSAGE"
|
"_METACITY_RESTART_MESSAGE",
|
||||||
|
"_NET_WM_STRUT",
|
||||||
|
"_WIN_HINTS"
|
||||||
};
|
};
|
||||||
Atom atoms[G_N_ELEMENTS(atom_names)];
|
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_wm_moveresize = atoms[42];
|
||||||
display->atom_net_active_window = atoms[43];
|
display->atom_net_active_window = atoms[43];
|
||||||
display->atom_metacity_restart_message = atoms[44];
|
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,
|
/* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK,
|
||||||
* created in screen_new
|
* created in screen_new
|
||||||
|
@ -104,6 +104,8 @@ struct _MetaDisplay
|
|||||||
Atom atom_net_wm_moveresize;
|
Atom atom_net_wm_moveresize;
|
||||||
Atom atom_net_active_window;
|
Atom atom_net_active_window;
|
||||||
Atom atom_metacity_restart_message;
|
Atom atom_metacity_restart_message;
|
||||||
|
Atom atom_net_wm_strut;
|
||||||
|
Atom atom_win_hints;
|
||||||
|
|
||||||
/* This is the actual window from focus events,
|
/* This is the actual window from focus events,
|
||||||
* not the one we last set
|
* 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;
|
GList *sorted;
|
||||||
int cascade_x, cascade_y;
|
int cascade_x, cascade_y;
|
||||||
int x_threshold, y_threshold;
|
int x_threshold, y_threshold;
|
||||||
|
MetaRectangle work_area;
|
||||||
|
|
||||||
sorted = g_list_copy (windows);
|
sorted = g_list_copy (windows);
|
||||||
sorted = g_list_sort (sorted, northwestcmp);
|
sorted = g_list_sort (sorted, northwestcmp);
|
||||||
@ -99,18 +100,10 @@ find_next_cascade (MetaWindow *window,
|
|||||||
* cascade_x, cascade_y are the target position
|
* cascade_x, cascade_y are the target position
|
||||||
* of NW corner of window frame.
|
* of NW corner of window frame.
|
||||||
*/
|
*/
|
||||||
cascade_x = 0;
|
meta_window_get_work_area (window, &work_area);
|
||||||
cascade_y = 0;
|
|
||||||
tmp = window->workspaces;
|
cascade_x = MAX (0, work_area.x);
|
||||||
while (tmp != NULL)
|
cascade_y = MAX (0, work_area.y);
|
||||||
{
|
|
||||||
MetaWorkspace *space = tmp->data;
|
|
||||||
|
|
||||||
cascade_x = MAX (cascade_x, space->workarea.x);
|
|
||||||
cascade_y = MAX (cascade_y, space->workarea.y);
|
|
||||||
|
|
||||||
tmp = tmp->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find first cascade position that's not used. */
|
/* Find first cascade position that's not used. */
|
||||||
|
|
||||||
@ -445,6 +438,7 @@ get_vertical_edges (MetaWindow *window,
|
|||||||
int i;
|
int i;
|
||||||
int n_edges;
|
int n_edges;
|
||||||
MetaRectangle rect;
|
MetaRectangle rect;
|
||||||
|
MetaRectangle work_area;
|
||||||
|
|
||||||
windows = get_windows_on_same_workspace (window, &n_windows);
|
windows = get_windows_on_same_workspace (window, &n_windows);
|
||||||
|
|
||||||
@ -453,11 +447,13 @@ get_vertical_edges (MetaWindow *window,
|
|||||||
edges = g_new (int, n_edges);
|
edges = g_new (int, n_edges);
|
||||||
|
|
||||||
/* workspace/screen 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;
|
++i;
|
||||||
edges[i] =
|
edges[i] =
|
||||||
window->screen->active_workspace->workarea.x +
|
work_area.x +
|
||||||
window->screen->active_workspace->workarea.width;
|
work_area.width;
|
||||||
++i;
|
++i;
|
||||||
edges[i] = 0;
|
edges[i] = 0;
|
||||||
++i;
|
++i;
|
||||||
@ -508,6 +504,7 @@ get_horizontal_edges (MetaWindow *window,
|
|||||||
int i;
|
int i;
|
||||||
int n_edges;
|
int n_edges;
|
||||||
MetaRectangle rect;
|
MetaRectangle rect;
|
||||||
|
MetaRectangle work_area;
|
||||||
|
|
||||||
windows = get_windows_on_same_workspace (window, &n_windows);
|
windows = get_windows_on_same_workspace (window, &n_windows);
|
||||||
|
|
||||||
@ -516,11 +513,13 @@ get_horizontal_edges (MetaWindow *window,
|
|||||||
edges = g_new (int, n_edges);
|
edges = g_new (int, n_edges);
|
||||||
|
|
||||||
/* workspace/screen 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;
|
++i;
|
||||||
edges[i] =
|
edges[i] =
|
||||||
window->screen->active_workspace->workarea.y +
|
work_area.y +
|
||||||
window->screen->active_workspace->workarea.height;
|
work_area.height;
|
||||||
++i;
|
++i;
|
||||||
edges[i] = 0;
|
edges[i] = 0;
|
||||||
++i;
|
++i;
|
||||||
|
309
src/window.c
309
src/window.c
@ -43,6 +43,16 @@ typedef enum
|
|||||||
META_USER_MOVE_RESIZE = 1 << 2
|
META_USER_MOVE_RESIZE = 1 << 2
|
||||||
} MetaMoveResizeFlags;
|
} 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,
|
static void constrain_size (MetaWindow *window,
|
||||||
MetaFrameGeometry *fgeom,
|
MetaFrameGeometry *fgeom,
|
||||||
int width,
|
int width,
|
||||||
@ -72,8 +82,11 @@ static int update_icon_name (MetaWindow *window);
|
|||||||
static int update_icon (MetaWindow *window,
|
static int update_icon (MetaWindow *window,
|
||||||
gboolean reread_rgb_icon);
|
gboolean reread_rgb_icon);
|
||||||
static int update_kwm_icon (MetaWindow *window);
|
static int update_kwm_icon (MetaWindow *window);
|
||||||
|
static void update_struts (MetaWindow *window);
|
||||||
static void recalc_window_type (MetaWindow *window);
|
static void recalc_window_type (MetaWindow *window);
|
||||||
static void recalc_window_features (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,
|
static int set_wm_state (MetaWindow *window,
|
||||||
int state);
|
int state);
|
||||||
static int set_net_wm_state (MetaWindow *window);
|
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_show (MetaWindow *window);
|
||||||
static void meta_window_hide (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,
|
static gboolean meta_window_get_icon_geometry (MetaWindow *window,
|
||||||
MetaRectangle *rect);
|
MetaRectangle *rect);
|
||||||
|
|
||||||
@ -350,6 +365,12 @@ meta_window_new (MetaDisplay *display, Window xwindow,
|
|||||||
window->type = META_WINDOW_NORMAL;
|
window->type = META_WINDOW_NORMAL;
|
||||||
window->type_atom = None;
|
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->layer = META_LAYER_NORMAL;
|
||||||
window->stack_op = NULL;
|
window->stack_op = NULL;
|
||||||
window->initial_workspace = 0; /* not used */
|
window->initial_workspace = 0; /* not used */
|
||||||
@ -359,6 +380,7 @@ meta_window_new (MetaDisplay *display, Window xwindow,
|
|||||||
update_title (window);
|
update_title (window);
|
||||||
update_protocols (window);
|
update_protocols (window);
|
||||||
update_wm_hints (window);
|
update_wm_hints (window);
|
||||||
|
update_struts (window);
|
||||||
|
|
||||||
update_net_wm_state (window);
|
update_net_wm_state (window);
|
||||||
/* Initially maximize if window is fullscreen; FIXME
|
/* Initially maximize if window is fullscreen; FIXME
|
||||||
@ -1193,6 +1215,8 @@ meta_window_maximize (MetaWindow *window)
|
|||||||
{
|
{
|
||||||
if (!window->maximized)
|
if (!window->maximized)
|
||||||
{
|
{
|
||||||
|
meta_verbose ("Maximizing %s\n", window->desc);
|
||||||
|
|
||||||
window->maximized = TRUE;
|
window->maximized = TRUE;
|
||||||
|
|
||||||
meta_window_raise (window);
|
meta_window_raise (window);
|
||||||
@ -1218,6 +1242,8 @@ meta_window_unmaximize (MetaWindow *window)
|
|||||||
{
|
{
|
||||||
if (window->maximized)
|
if (window->maximized)
|
||||||
{
|
{
|
||||||
|
meta_verbose ("Unmaximizing %s\n", window->desc);
|
||||||
|
|
||||||
window->maximized = FALSE;
|
window->maximized = FALSE;
|
||||||
|
|
||||||
meta_window_move_resize (window,
|
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->right_width = fgeom.right_width;
|
||||||
window->frame->bottom_height = fgeom.bottom_height;
|
window->frame->bottom_height = fgeom.bottom_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See ICCCM 4.1.5 for when to send ConfigureNotify */
|
/* See ICCCM 4.1.5 for when to send ConfigureNotify */
|
||||||
|
|
||||||
need_configure_notify = FALSE;
|
need_configure_notify = FALSE;
|
||||||
@ -1756,6 +1782,19 @@ meta_window_move_resize_internal (MetaWindow *window,
|
|||||||
{
|
{
|
||||||
meta_verbose ("Size/position not modified\n");
|
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:
|
/* Invariants leaving this function are:
|
||||||
* a) window->rect and frame->rect reflect the actual
|
* a) window->rect and frame->rect reflect the actual
|
||||||
@ -2636,6 +2675,44 @@ meta_window_client_message (MetaWindow *window,
|
|||||||
|
|
||||||
return TRUE;
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -2858,6 +2935,16 @@ process_property_notify (MetaWindow *window,
|
|||||||
update_kwm_icon (window);
|
update_kwm_icon (window);
|
||||||
update_icon (window, FALSE);
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -4377,6 +4464,166 @@ update_kwm_icon (MetaWindow *window)
|
|||||||
return Success;
|
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
|
static void
|
||||||
recalc_window_type (MetaWindow *window)
|
recalc_window_type (MetaWindow *window)
|
||||||
{
|
{
|
||||||
@ -4499,10 +4746,13 @@ constrain_size (MetaWindow *window,
|
|||||||
int delta;
|
int delta;
|
||||||
double min_aspect, max_aspect;
|
double min_aspect, max_aspect;
|
||||||
int minw, minh, maxw, maxh, fullw, fullh;
|
int minw, minh, maxw, maxh, fullw, fullh;
|
||||||
|
MetaRectangle work_area;
|
||||||
|
|
||||||
/* frame member variables should NEVER be used in here */
|
/* frame member variables should NEVER be used in here */
|
||||||
|
|
||||||
#define FLOOR(value, base) ( ((int) ((value) / (base))) * (base) )
|
#define FLOOR(value, base) ( ((int) ((value) / (base))) * (base) )
|
||||||
|
|
||||||
|
meta_window_get_work_area (window, &work_area);
|
||||||
|
|
||||||
/* Get the allowed size ranges, considering maximized, etc. */
|
/* Get the allowed size ranges, considering maximized, etc. */
|
||||||
if (window->type == META_WINDOW_DESKTOP ||
|
if (window->type == META_WINDOW_DESKTOP ||
|
||||||
@ -4513,8 +4763,8 @@ constrain_size (MetaWindow *window,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fullw = window->screen->active_workspace->workarea.width;
|
fullw = work_area.width;
|
||||||
fullh = window->screen->active_workspace->workarea.height;
|
fullh = work_area.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->frame)
|
if (window->frame)
|
||||||
@ -4620,6 +4870,10 @@ constrain_position (MetaWindow *window,
|
|||||||
int *new_x,
|
int *new_x,
|
||||||
int *new_y)
|
int *new_y)
|
||||||
{
|
{
|
||||||
|
MetaRectangle work_area;
|
||||||
|
|
||||||
|
meta_window_get_work_area (window, &work_area);
|
||||||
|
|
||||||
/* frame member variables should NEVER be used in here, only
|
/* frame member variables should NEVER be used in here, only
|
||||||
* MetaFrameGeometry
|
* MetaFrameGeometry
|
||||||
*/
|
*/
|
||||||
@ -4644,8 +4898,8 @@ constrain_position (MetaWindow *window,
|
|||||||
/* find furthest northwest point the window can occupy,
|
/* find furthest northwest point the window can occupy,
|
||||||
* to disallow moving titlebar off the top or left
|
* to disallow moving titlebar off the top or left
|
||||||
*/
|
*/
|
||||||
nw_x = window->screen->active_workspace->workarea.x;
|
nw_x = work_area.x;
|
||||||
nw_y = window->screen->active_workspace->workarea.y;
|
nw_y = work_area.y;
|
||||||
if (window->frame)
|
if (window->frame)
|
||||||
{
|
{
|
||||||
nw_x += fgeom->left_width;
|
nw_x += fgeom->left_width;
|
||||||
@ -4653,10 +4907,8 @@ constrain_position (MetaWindow *window,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* find bottom-right corner of workarea */
|
/* find bottom-right corner of workarea */
|
||||||
se_x = window->screen->active_workspace->workarea.x +
|
se_x = work_area.x + work_area.width;
|
||||||
window->screen->active_workspace->workarea.width;
|
se_y = work_area.y + work_area.height;
|
||||||
se_y = window->screen->active_workspace->workarea.y +
|
|
||||||
window->screen->active_workspace->workarea.height;
|
|
||||||
|
|
||||||
/* if the window's size exceeds the screen size,
|
/* if the window's size exceeds the screen size,
|
||||||
* we allow it to go off the top/left far enough
|
* 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);
|
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
|
* only relevant if !window->placed
|
||||||
*/
|
*/
|
||||||
guint calc_placement : 1;
|
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
|
/* Number of UnmapNotify that are caused by us, if
|
||||||
* we get UnmapNotify with none pending then the client
|
* 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 */
|
/* x/y/w/h here get filled with ConfigureRequest values */
|
||||||
XSizeHints size_hints;
|
XSizeHints size_hints;
|
||||||
|
|
||||||
|
/* struts */
|
||||||
|
int left_strut;
|
||||||
|
int right_strut;
|
||||||
|
int top_strut;
|
||||||
|
int bottom_strut;
|
||||||
|
|
||||||
/* Managed by stack.c */
|
/* Managed by stack.c */
|
||||||
MetaStackLayer layer;
|
MetaStackLayer layer;
|
||||||
MetaStackOp *stack_op;
|
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,
|
gboolean meta_window_visible_on_workspace (MetaWindow *window,
|
||||||
MetaWorkspace *workspace);
|
MetaWorkspace *workspace);
|
||||||
|
|
||||||
|
/* Get minimum work area for all workspaces we're on */
|
||||||
|
void meta_window_get_work_area (MetaWindow *window,
|
||||||
|
MetaRectangle *area);
|
||||||
|
|
||||||
#endif
|
#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);
|
g_list_append (workspace->screen->display->workspaces, workspace);
|
||||||
workspace->windows = NULL;
|
workspace->windows = NULL;
|
||||||
|
|
||||||
/* This may have something to do with the strut hints
|
workspace->work_area.x = 0;
|
||||||
* eventually
|
workspace->work_area.y = 0;
|
||||||
*/
|
workspace->work_area.width = screen->width;
|
||||||
workspace->workarea.x = 0;
|
workspace->work_area.height = screen->height;
|
||||||
workspace->workarea.y = 0;
|
workspace->work_area_invalid = TRUE;
|
||||||
workspace->workarea.width = screen->width;
|
|
||||||
workspace->workarea.height = screen->height;
|
|
||||||
|
|
||||||
/* Update hint for current number of workspaces */
|
/* Update hint for current number of workspaces */
|
||||||
set_number_of_spaces_hint (screen);
|
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_set_current_workspace_hint (window);
|
||||||
|
|
||||||
meta_window_queue_calc_showing (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
|
void
|
||||||
@ -119,6 +124,14 @@ meta_workspace_remove_window (MetaWorkspace *workspace,
|
|||||||
meta_window_set_current_workspace_hint (window);
|
meta_window_set_current_workspace_hint (window);
|
||||||
|
|
||||||
meta_window_queue_calc_showing (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
|
void
|
||||||
@ -242,6 +255,37 @@ meta_workspace_screen_index (MetaWorkspace *workspace)
|
|||||||
meta_bug ("Workspace does not exist to index!\n");
|
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
|
static int
|
||||||
set_number_of_spaces_hint (MetaScreen *screen)
|
set_number_of_spaces_hint (MetaScreen *screen)
|
||||||
{
|
{
|
||||||
@ -275,3 +319,90 @@ set_active_space_hint (MetaScreen *screen)
|
|||||||
32, PropModeReplace, (guchar*) data, 1);
|
32, PropModeReplace, (guchar*) data, 1);
|
||||||
return meta_error_trap_pop (screen->display);
|
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;
|
GList *windows;
|
||||||
|
|
||||||
MetaRectangle workarea;
|
MetaRectangle work_area;
|
||||||
|
guint work_area_invalid : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
MetaWorkspace* meta_workspace_new (MetaScreen *screen);
|
MetaWorkspace* meta_workspace_new (MetaScreen *screen);
|
||||||
@ -47,6 +48,12 @@ gboolean meta_workspace_contains_window (MetaWorkspace *workspace,
|
|||||||
void meta_workspace_activate (MetaWorkspace *workspace);
|
void meta_workspace_activate (MetaWorkspace *workspace);
|
||||||
int meta_workspace_index (MetaWorkspace *workspace);
|
int meta_workspace_index (MetaWorkspace *workspace);
|
||||||
int meta_workspace_screen_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
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user