+#define STRUT_LEFT_ON_MONITOR(s, i) \
+ (RANGES_INTERSECT(s->left_start, s->left_end - s->left_start + 1, \
+ monitor_area[i].y, monitor_area[i].height))
+#define STRUT_RIGHT_ON_MONITOR(s, i) \
+ (RANGES_INTERSECT(s->right_start, s->right_end - s->right_start + 1, \
+ monitor_area[i].y, monitor_area[i].height))
+#define STRUT_TOP_ON_MONITOR(s, i) \
+ (RANGES_INTERSECT(s->top_start, s->top_end - s->top_start + 1, \
+ monitor_area[i].x, monitor_area[i].width))
+#define STRUT_BOTTOM_ON_MONITOR(s, i) \
+ (RANGES_INTERSECT(s->bottom_start, s->bottom_end - s->bottom_start + 1, \
+ monitor_area[i].x, monitor_area[i].width))
+
+typedef struct {
+ guint desktop;
+ StrutPartial *strut;
+} ObScreenStrut;
+
+#define RESET_STRUT_LIST(sl) \
+ (g_slist_free(sl), sl = NULL)
+
+#define ADD_STRUT_TO_LIST(sl, d, s) \
+{ \
+ ObScreenStrut *ss = g_new(ObScreenStrut, 1); \
+ ss->desktop = d; \
+ ss->strut = s; \
+ sl = g_slist_prepend(sl, ss); \
+}
+
+#define VALIDATE_STRUTS(sl, side, max) \
+{ \
+ GSList *it; \
+ for (it = sl; it; it = g_slist_next(it)) { \
+ ObScreenStrut *ss = it->data; \
+ ss->strut->side = MIN(max, ss->strut->side); \
+ } \
+}
+
+void screen_update_areas(void)
+{
+ guint i, j;
+ gulong *dims;
+ GList *it;
+ GSList *sit;
+
+ g_free(monitor_area);
+ extensions_xinerama_screens(&monitor_area, &screen_num_monitors);
+
+ /* set up the user-specified margins */
+ config_margins.top_start = RECT_LEFT(monitor_area[screen_num_monitors]);
+ config_margins.top_end = RECT_RIGHT(monitor_area[screen_num_monitors]);
+ config_margins.bottom_start = RECT_LEFT(monitor_area[screen_num_monitors]);
+ config_margins.bottom_end = RECT_RIGHT(monitor_area[screen_num_monitors]);
+ config_margins.left_start = RECT_TOP(monitor_area[screen_num_monitors]);
+ config_margins.left_end = RECT_BOTTOM(monitor_area[screen_num_monitors]);
+ config_margins.right_start = RECT_TOP(monitor_area[screen_num_monitors]);
+ config_margins.right_end = RECT_BOTTOM(monitor_area[screen_num_monitors]);
+
+ dims = g_new(gulong, 4 * screen_num_desktops * screen_num_monitors);
+
+ RESET_STRUT_LIST(struts_left);
+ RESET_STRUT_LIST(struts_top);
+ RESET_STRUT_LIST(struts_right);
+ RESET_STRUT_LIST(struts_bottom);
+
+ /* collect the struts */
+ for (it = client_list; it; it = g_list_next(it)) {
+ ObClient *c = it->data;
+ if (c->strut.left)
+ ADD_STRUT_TO_LIST(struts_left, c->desktop, &c->strut);
+ if (c->strut.top)
+ ADD_STRUT_TO_LIST(struts_top, c->desktop, &c->strut);
+ if (c->strut.right)
+ ADD_STRUT_TO_LIST(struts_right, c->desktop, &c->strut);
+ if (c->strut.bottom)
+ ADD_STRUT_TO_LIST(struts_bottom, c->desktop, &c->strut);
+ }
+ if (dock_strut.left)
+ ADD_STRUT_TO_LIST(struts_left, DESKTOP_ALL, &dock_strut);
+ if (dock_strut.top)
+ ADD_STRUT_TO_LIST(struts_top, DESKTOP_ALL, &dock_strut);
+ if (dock_strut.right)
+ ADD_STRUT_TO_LIST(struts_right, DESKTOP_ALL, &dock_strut);
+ if (dock_strut.bottom)
+ ADD_STRUT_TO_LIST(struts_bottom, DESKTOP_ALL, &dock_strut);
+
+ if (config_margins.left)
+ ADD_STRUT_TO_LIST(struts_left, DESKTOP_ALL, &config_margins);
+ if (config_margins.top)
+ ADD_STRUT_TO_LIST(struts_top, DESKTOP_ALL, &config_margins);
+ if (config_margins.right)
+ ADD_STRUT_TO_LIST(struts_right, DESKTOP_ALL, &config_margins);
+ if (config_margins.bottom)
+ ADD_STRUT_TO_LIST(struts_bottom, DESKTOP_ALL, &config_margins);
+
+ VALIDATE_STRUTS(struts_left, left,
+ monitor_area[screen_num_monitors].width / 2);
+ VALIDATE_STRUTS(struts_right, right,
+ monitor_area[screen_num_monitors].width / 2);
+ VALIDATE_STRUTS(struts_top, top,
+ monitor_area[screen_num_monitors].height / 2);
+ VALIDATE_STRUTS(struts_bottom, bottom,
+ monitor_area[screen_num_monitors].height / 2);
+
+ /* set up the work areas to be full screen */
+ for (i = 0; i < screen_num_monitors; ++i)
+ for (j = 0; j < screen_num_desktops; ++j) {
+ dims[(i * screen_num_desktops + j) * 4+0] = monitor_area[i].x;
+ dims[(i * screen_num_desktops + j) * 4+1] = monitor_area[i].y;
+ dims[(i * screen_num_desktops + j) * 4+2] = monitor_area[i].width;
+ dims[(i * screen_num_desktops + j) * 4+3] = monitor_area[i].height;
+ }
+
+ /* calculate the work areas from the struts */
+ for (i = 0; i < screen_num_monitors; ++i)
+ for (j = 0; j < screen_num_desktops; ++j) {
+ gint l = 0, r = 0, t = 0, b = 0;
+
+ /* only add the strut to the area if it touches the monitor */
+
+ for (sit = struts_left; sit; sit = g_slist_next(sit)) {
+ ObScreenStrut *s = sit->data;
+ if ((s->desktop == j || s->desktop == DESKTOP_ALL) &&
+ STRUT_LEFT_ON_MONITOR(s->strut, i))
+ l = MAX(l, s->strut->left);
+ }
+ for (sit = struts_top; sit; sit = g_slist_next(sit)) {
+ ObScreenStrut *s = sit->data;
+ if ((s->desktop == j || s->desktop == DESKTOP_ALL) &&
+ STRUT_TOP_ON_MONITOR(s->strut, i))
+ t = MAX(t, s->strut->top);
+ }
+ for (sit = struts_right; sit; sit = g_slist_next(sit)) {
+ ObScreenStrut *s = sit->data;
+ if ((s->desktop == j || s->desktop == DESKTOP_ALL) &&
+ STRUT_RIGHT_ON_MONITOR(s->strut, i))
+ r = MAX(r, s->strut->right);
+ }
+ for (sit = struts_bottom; sit; sit = g_slist_next(sit)) {
+ ObScreenStrut *s = sit->data;
+ if ((s->desktop == j || s->desktop == DESKTOP_ALL) &&
+ STRUT_BOTTOM_ON_MONITOR(s->strut, i))
+ b = MAX(b, s->strut->bottom);
+ }
+
+ /* based on these margins, set the work area for the
+ monitor/desktop */
+ dims[(i * screen_num_desktops + j) * 4 + 0] += l;
+ dims[(i * screen_num_desktops + j) * 4 + 1] += t;
+ dims[(i * screen_num_desktops + j) * 4 + 2] -= l + r;
+ dims[(i * screen_num_desktops + j) * 4 + 3] -= t + b;
+ }
+
+ /* all the work areas are not used here, only the ones for the first
+ monitor are */
+ PROP_SETA32(RootWindow(ob_display, ob_screen), net_workarea, cardinal,
+ dims, 4 * screen_num_desktops);
+
+ /* the area has changed, adjust all the windows if they need it */
+ for (it = client_list; it; it = g_list_next(it))
+ client_reconfigure(it->data, FALSE);
+
+ g_free(dims);
+}
+
+#if 0
+Rect* screen_area_all_monitors(guint desktop)