...
 
Commits (4)
......@@ -135,6 +135,7 @@ item(_NET_WM_STATE_FULLSCREEN)
item(_NET_WM_PING)
item(_NET_WM_PID)
item(_NET_WORKAREA)
item(_NET_WORKAREAS)
item(_NET_SHOWING_DESKTOP)
item(_NET_DESKTOP_LAYOUT)
item(_NET_DESKTOP_NAMES)
......@@ -151,6 +152,7 @@ item(_NET_WM_STATE_ABOVE)
item(_NET_WM_STATE_BELOW)
item(_NET_STARTUP_ID)
item(_NET_WM_STRUT_PARTIAL)
item(_NET_WM_STRUT_AREA)
item(_NET_WM_ACTION_FULLSCREEN)
item(_NET_WM_ACTION_MINIMIZE)
item(_NET_FRAME_EXTENTS)
......
......@@ -518,7 +518,8 @@ compare_rect_areas (gconstpointer a, gconstpointer b)
GList*
meta_rectangle_get_minimal_spanning_set_for_region (
const MetaRectangle *basic_rect,
const GSList *all_struts)
const GSList *all_struts,
gboolean skip_middle_struts)
{
/* NOTE FOR OPTIMIZERS: This function *might* be somewhat slow,
* especially due to the call to merge_spanning_rects_in_region() (which
......@@ -580,7 +581,24 @@ meta_rectangle_get_minimal_spanning_set_for_region (
for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next)
{
GList *rect_iter;
MetaRectangle *strut_rect = &((MetaStrut*)strut_iter->data)->rect;
MetaEdge *strut = (MetaEdge *) strut_iter->data;
MetaRectangle *strut_rect = &strut->rect;
if (skip_middle_struts &&
strut->edge_type == META_EDGE_MONITOR)
{
if ((strut->side_type == META_SIDE_LEFT &&
strut_rect->x != basic_rect->x) ||
(strut->side_type == META_SIDE_RIGHT &&
strut_rect->x + strut_rect->width != basic_rect->width) ||
(strut->side_type == META_SIDE_TOP &&
strut_rect->y != basic_rect->y) ||
(strut->side_type == META_SIDE_BOTTOM &&
strut_rect->y + strut_rect->height != basic_rect->height))
{
continue;
}
}
tmp_list = ret;
ret = NULL;
......@@ -722,7 +740,7 @@ meta_rectangle_expand_to_avoiding_struts (MetaRectangle *rect,
/* Run over all struts */
for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next)
{
MetaStrut *strut = (MetaStrut*) strut_iter->data;
MetaEdge *strut = (MetaEdge *) strut_iter->data;
/* Skip struts that don't overlap */
if (!meta_rectangle_overlap (&strut->rect, rect))
......@@ -730,13 +748,13 @@ meta_rectangle_expand_to_avoiding_struts (MetaRectangle *rect,
if (direction == META_DIRECTION_HORIZONTAL)
{
if (strut->side == META_SIDE_LEFT)
if (strut->side_type == META_SIDE_LEFT)
{
int offset = BOX_RIGHT(strut->rect) - BOX_LEFT(*rect);
rect->x += offset;
rect->width -= offset;
}
else if (strut->side == META_SIDE_RIGHT)
else if (strut->side_type == META_SIDE_RIGHT)
{
int offset = BOX_RIGHT (*rect) - BOX_LEFT(strut->rect);
rect->width -= offset;
......@@ -745,13 +763,13 @@ meta_rectangle_expand_to_avoiding_struts (MetaRectangle *rect,
}
else /* direction == META_DIRECTION_VERTICAL */
{
if (strut->side == META_SIDE_TOP)
if (strut->side_type == META_SIDE_TOP)
{
int offset = BOX_BOTTOM(strut->rect) - BOX_TOP(*rect);
rect->y += offset;
rect->height -= offset;
}
else if (strut->side == META_SIDE_BOTTOM)
else if (strut->side_type == META_SIDE_BOTTOM)
{
int offset = BOX_BOTTOM(*rect) - BOX_TOP(strut->rect);
rect->height -= offset;
......@@ -1255,7 +1273,7 @@ get_disjoint_strut_rect_list_in_region (const GSList *old_struts,
strut_rects = NULL;
while (old_struts)
{
MetaRectangle *cur = &((MetaStrut*)old_struts->data)->rect;
MetaRectangle *cur = &((MetaEdge *)old_struts->data)->rect;
MetaRectangle *copy = g_new (MetaRectangle, 1);
*copy = *cur;
if (meta_rectangle_intersect (copy, region, copy))
......@@ -1855,7 +1873,7 @@ meta_rectangle_find_nonintersected_monitor_edges (
temp_rects = NULL;
for (; all_struts; all_struts = all_struts->next)
temp_rects = g_slist_prepend (temp_rects,
&((MetaStrut*)all_struts->data)->rect);
&((MetaEdge *)all_struts->data)->rect);
ret = meta_rectangle_remove_intersections_with_boxes_from_edges (ret,
temp_rects);
g_slist_free (temp_rects);
......
......@@ -1876,6 +1876,51 @@ set_work_area_hint (MetaScreen *screen)
(guchar*) data, num_workspaces*4);
g_free (data);
meta_error_trap_pop (screen->display);
tmp_list = screen->workspaces;
while (tmp_list != NULL)
{
MetaWorkspace *workspace = tmp_list->data;
if (workspace->screen == screen)
{
int i;
gchar *atom_name;
Atom region_atom;
data = g_new (unsigned long, screen->n_monitor_infos * 4);
tmp = data;
for (i = 0; i < screen->n_monitor_infos; i++)
{
meta_workspace_get_work_area_for_monitor (workspace, i, &area);
tmp[0] = area.x;
tmp[1] = area.y;
tmp[2] = area.width;
tmp[3] = area.height;
tmp += 4;
}
atom_name = g_strdup_printf ("_NET_WORKAREAS_D%d",
meta_workspace_index (workspace));
region_atom = XInternAtom (screen->display->xdisplay, atom_name, False);
g_free (atom_name);
meta_error_trap_push (screen->display);
XChangeProperty (screen->display->xdisplay, screen->xroot, region_atom,
XA_CARDINAL, 32, PropModeReplace,
(guchar*) data, screen->n_monitor_infos * 4);
meta_error_trap_pop (screen->display);
g_free (data);
}
tmp_list = tmp_list->next;
}
}
static gboolean
......
......@@ -56,19 +56,12 @@ new_meta_rect (int x, int y, int width, int height)
return temporary;
}
static MetaStrut*
new_meta_strut (int x, int y, int width, int height, int side)
{
MetaStrut* temporary;
temporary = g_new (MetaStrut, 1);
temporary->rect = meta_rect(x, y, width, height);
temporary->side = side;
return temporary;
}
static MetaEdge*
new_screen_edge (int x, int y, int width, int height, int side_type)
new_screen_edge (int x,
int y,
int width,
int height,
MetaSide side_type)
{
MetaEdge* temporary;
temporary = g_new (MetaEdge, 1);
......@@ -83,11 +76,11 @@ new_screen_edge (int x, int y, int width, int height, int side_type)
}
static MetaEdge *
new_monitor_edge (int x,
int y,
int width,
int height,
int side_type)
new_monitor_edge (int x,
int y,
int width,
int height,
MetaSide side_type)
{
MetaEdge* temporary;
temporary = g_new (MetaEdge, 1);
......@@ -242,7 +235,7 @@ static GSList*
get_strut_list (int which)
{
GSList *ans;
MetaDirection wc = 0; /* wc == who cares? ;-) */
MetaSide wc = 0; /* wc == who cares? ;-) */
ans = NULL;
......@@ -252,32 +245,32 @@ get_strut_list (int which)
case 0:
break;
case 1:
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 400, 1160, 1600, 40, wc));
ans = g_slist_prepend (ans, new_screen_edge ( 0, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_screen_edge ( 400, 1160, 1600, 40, wc));
break;
case 2:
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 150, 50, wc));
ans = g_slist_prepend (ans, new_screen_edge ( 0, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_screen_edge ( 800, 1100, 400, 100, wc));
ans = g_slist_prepend (ans, new_screen_edge ( 300, 1150, 150, 50, wc));
break;
case 3:
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 80, 50, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 700, 525, 200, 150, wc));
ans = g_slist_prepend (ans, new_screen_edge ( 0, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_screen_edge ( 800, 1100, 400, 100, wc));
ans = g_slist_prepend (ans, new_screen_edge ( 300, 1150, 80, 50, wc));
ans = g_slist_prepend (ans, new_screen_edge ( 700, 525, 200, 150, wc));
break;
case 4:
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_screen_edge ( 0, 0, 800, 1200, wc));
ans = g_slist_prepend (ans, new_screen_edge ( 800, 0, 1600, 20, wc));
break;
case 5:
ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 10, 800, 1200, wc));
ans = g_slist_prepend (ans, new_screen_edge ( 800, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_screen_edge ( 0, 0, 800, 1200, wc));
ans = g_slist_prepend (ans, new_screen_edge ( 800, 10, 800, 1200, wc));
break;
case 6:
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 40, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_screen_edge ( 0, 0, 1600, 40, wc));
ans = g_slist_prepend (ans, new_screen_edge ( 0, 0, 1600, 20, wc));
break;
default:
break;
......@@ -297,7 +290,10 @@ get_screen_region (int which)
ret = NULL;
struts = get_strut_list (which);
ret = meta_rectangle_get_minimal_spanning_set_for_region (&basic_rect, struts);
ret = meta_rectangle_get_minimal_spanning_set_for_region (&basic_rect,
struts,
FALSE);
free_strut_list (struts);
return ret;
......@@ -1030,10 +1026,10 @@ test_find_onscreen_edges (void)
GList* edges;
GList* tmp;
int left = META_DIRECTION_LEFT;
int right = META_DIRECTION_RIGHT;
int top = META_DIRECTION_TOP;
int bottom = META_DIRECTION_BOTTOM;
int left = META_SIDE_LEFT;
int right = META_SIDE_RIGHT;
int top = META_SIDE_TOP;
int bottom = META_SIDE_BOTTOM;
/*************************************************/
/* Make sure test region 0 has the correct edges */
......@@ -1163,10 +1159,10 @@ test_find_nonintersected_monitor_edges (void)
GList* edges;
GList* tmp;
int left = META_DIRECTION_LEFT;
int right = META_DIRECTION_RIGHT;
int top = META_DIRECTION_TOP;
int bottom = META_DIRECTION_BOTTOM;
int left = META_SIDE_LEFT;
int right = META_SIDE_RIGHT;
int top = META_SIDE_TOP;
int bottom = META_SIDE_BOTTOM;
/*************************************************************************/
/* Make sure test monitor set 0 for with region 0 has the correct edges */
......
......@@ -1954,6 +1954,12 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
reload_struts,
NONE
},
{
display->atom__NET_WM_STRUT_AREA,
META_PROP_VALUE_INVALID,
reload_struts,
NONE
},
{
display->atom__NET_WM_WINDOW_OPACITY,
META_PROP_VALUE_CARDINAL,
......
......@@ -6375,6 +6375,91 @@ meta_window_update_struts (MetaWindow *window)
new_struts = NULL;
if (meta_prop_get_cardinal_list (window->display,
window->xwindow,
window->display->atom__NET_WM_STRUT_AREA,
&struts, &nitems))
{
if (nitems != 4)
{
meta_verbose ("_NET_WM_STRUT_AREA on %s has %d values instead of 4\n",
window->desc, nitems);
}
else
{
MetaEdge *temp;
MetaSide side;
gboolean valid;
int i;
temp = g_new (MetaEdge, 1);
temp->rect.x = struts[0];
temp->rect.y = struts[1];
temp->rect.width = struts[2];
temp->rect.height = struts[3];
side = META_SIDE_LEFT;
valid = FALSE;
for (i = 0; i < window->screen->n_monitor_infos; i++)
{
MetaRectangle monitor;
monitor = window->screen->monitor_infos[i].rect;
if (!meta_rectangle_contains_rect (&monitor, &temp->rect))
continue;
if (temp->rect.height > temp->rect.width)
{
if (temp->rect.x == monitor.x)
{
side = META_SIDE_LEFT;
valid = TRUE;
}
else if (temp->rect.x + temp->rect.width == monitor.x + monitor.width)
{
side = META_SIDE_RIGHT;
valid = TRUE;
}
}
else
{
if (temp->rect.y == monitor.y)
{
side = META_SIDE_TOP;
valid = TRUE;
}
else if (temp->rect.y + temp->rect.height == monitor.y + monitor.height)
{
side = META_SIDE_BOTTOM;
valid = TRUE;
}
}
}
if (valid)
{
temp->side_type = side;
temp->edge_type = META_EDGE_MONITOR;
new_struts = g_slist_prepend (new_struts, temp);
}
else
{
g_free (temp);
}
}
meta_XFree (struts);
}
else
{
meta_verbose ("No _NET_WM_STRUT_AREA property for %s\n",
window->desc);
}
if (!new_struts &&
meta_prop_get_cardinal_list (window->display,
window->xwindow,
window->display->atom__NET_WM_STRUT_PARTIAL,
&struts, &nitems))
......@@ -6389,7 +6474,7 @@ meta_window_update_struts (MetaWindow *window)
int i;
for (i=0; i<4; i++)
{
MetaStrut *temp;
MetaEdge *temp;
int thickness, strut_begin, strut_end;
thickness = struts[i];
......@@ -6398,10 +6483,13 @@ meta_window_update_struts (MetaWindow *window)
strut_begin = struts[4+(i*2)];
strut_end = struts[4+(i*2)+1];
temp = g_new (MetaStrut, 1);
temp->side = 1 << i; /* See MetaSide def. Matches nicely, eh? */
temp = g_new (MetaEdge, 1);
temp->side_type = i;
temp->edge_type = META_EDGE_SCREEN;
temp->rect = window->screen->rect;
switch (temp->side)
switch (temp->side_type)
{
case META_SIDE_RIGHT:
temp->rect.x = BOX_RIGHT(temp->rect) - thickness;
......@@ -6460,17 +6548,20 @@ meta_window_update_struts (MetaWindow *window)
int i;
for (i=0; i<4; i++)
{
MetaStrut *temp;
MetaEdge *temp;
int thickness;
thickness = struts[i];
if (thickness == 0)
continue;
temp = g_new (MetaStrut, 1);
temp->side = 1 << i;
temp = g_new (MetaEdge, 1);
temp->side_type = i;
temp->edge_type = META_EDGE_SCREEN;
temp->rect = window->screen->rect;
switch (temp->side)
switch (temp->side_type)
{
case META_SIDE_RIGHT:
temp->rect.x = BOX_RIGHT(temp->rect) - thickness;
......@@ -6510,10 +6601,11 @@ meta_window_update_struts (MetaWindow *window)
new_iter = new_struts;
while (old_iter && new_iter)
{
MetaStrut *old_strut = (MetaStrut*) old_iter->data;
MetaStrut *new_strut = (MetaStrut*) new_iter->data;
MetaEdge *old_strut = (MetaEdge *) old_iter->data;
MetaEdge *new_strut = (MetaEdge *) new_iter->data;
if (old_strut->side != new_strut->side ||
if (old_strut->side_type != new_strut->side_type ||
old_strut->edge_type != new_strut->edge_type ||
!meta_rectangle_equal (&old_strut->rect, &new_strut->rect))
break;
......
......@@ -624,8 +624,8 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
GSList *s_iter;
for (s_iter = win->struts; s_iter != NULL; s_iter = s_iter->next) {
MetaStrut *cpy = g_new (MetaStrut, 1);
*cpy = *((MetaStrut *)s_iter->data);
MetaEdge *cpy = g_new (MetaEdge, 1);
*cpy = *((MetaEdge *)s_iter->data);
workspace->all_struts = g_slist_prepend (workspace->all_struts,
cpy);
}
......@@ -646,12 +646,14 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
workspace->monitor_region[i] =
meta_rectangle_get_minimal_spanning_set_for_region (
&workspace->screen->monitor_infos[i].rect,
workspace->all_struts);
workspace->all_struts,
FALSE);
}
workspace->screen_region =
meta_rectangle_get_minimal_spanning_set_for_region (
&workspace->screen->rect,
workspace->all_struts);
workspace->all_struts,
TRUE);
/* STEP 3: Get the work areas (region-to-maximize-to) for the screen and
* monitors.
......
......@@ -34,13 +34,6 @@ struct _MetaRectangle
int height;
};
typedef struct _MetaStrut MetaStrut;
struct _MetaStrut
{
MetaRectangle rect;
MetaSide side;
};
#define BOX_LEFT(box) ((box).x) /* Leftmost pixel of rect */
#define BOX_RIGHT(box) ((box).x + (box).width) /* One pixel past right */
#define BOX_TOP(box) ((box).y) /* Topmost pixel of rect */
......@@ -156,7 +149,8 @@ void meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect,
*/
GList* meta_rectangle_get_minimal_spanning_set_for_region (
const MetaRectangle *basic_rect,
const GSList *all_struts);
const GSList *all_struts,
gboolean skip_middle_struts);
/* Expand all rectangles in region by the given amount on each side */
GList* meta_rectangle_expand_region (GList *region,
......
......@@ -183,15 +183,14 @@ typedef enum
/* Sometimes we want to talk about sides instead of directions; note
* that the values must be as follows or meta_window_update_struts()
* won't work. Using these values also is a safety blanket since
* MetaDirection used to be used as a side.
* won't work.
*/
typedef enum
{
META_SIDE_LEFT = META_DIRECTION_LEFT,
META_SIDE_RIGHT = META_DIRECTION_RIGHT,
META_SIDE_TOP = META_DIRECTION_TOP,
META_SIDE_BOTTOM = META_DIRECTION_BOTTOM
META_SIDE_LEFT = 0,
META_SIDE_RIGHT = 1,
META_SIDE_TOP = 2,
META_SIDE_BOTTOM = 3
} MetaSide;
/* should investigate changing these to whatever most apps use */
......