Time screen_desktop_user_time = CurrentTime;
/*! An array of desktops, holding array of areas per monitor */
-static Rect *monitor_area;
-static GSList *struts_top;
-static GSList *struts_left;
-static GSList *struts_right;
-static GSList *struts_bottom;
+static Rect *monitor_area = NULL;
+/*! An array of desktops, holding an array of struts */
+static GSList *struts_top = NULL;
+static GSList *struts_left = NULL;
+static GSList *struts_right = NULL;
+static GSList *struts_bottom = NULL;
static ObPagerPopup *desktop_cycle_popup;
if (!show) {
pager_popup_hide(desktop_cycle_popup);
} else {
- a = screen_physical_area_monitor_active();
+ a = screen_physical_area_active();
pager_popup_position(desktop_cycle_popup, CenterGravity,
a->x + a->width / 2, a->y + a->height / 2);
pager_popup_icon_size_multiplier(desktop_cycle_popup,
}
}
+#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); \
+}
+
void screen_update_areas()
{
guint i, j;
dims = g_new(gulong, 4 * screen_num_desktops * screen_num_monitors);
- g_slist_free(struts_left); struts_left = NULL;
- g_slist_free(struts_top); struts_top = NULL;
- g_slist_free(struts_right); struts_right = NULL;
- g_slist_free(struts_bottom); struts_bottom = NULL;
+ 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)
- struts_left = g_slist_prepend(struts_left, &c->strut);
+ ADD_STRUT_TO_LIST(struts_left, c->desktop, &c->strut);
if (c->strut.top)
- struts_top = g_slist_prepend(struts_top, &c->strut);
+ ADD_STRUT_TO_LIST(struts_top, c->desktop, &c->strut);
if (c->strut.right)
- struts_right = g_slist_prepend(struts_right, &c->strut);
+ ADD_STRUT_TO_LIST(struts_right, c->desktop, &c->strut);
if (c->strut.bottom)
- struts_bottom = g_slist_prepend(struts_bottom, &c->strut);
+ ADD_STRUT_TO_LIST(struts_bottom, c->desktop, &c->strut);
}
if (dock_strut.left)
- struts_left = g_slist_prepend(struts_left, &dock_strut);
+ ADD_STRUT_TO_LIST(struts_left, DESKTOP_ALL, &dock_strut);
if (dock_strut.top)
- struts_top = g_slist_prepend(struts_top, &dock_strut);
+ ADD_STRUT_TO_LIST(struts_top, DESKTOP_ALL, &dock_strut);
if (dock_strut.right)
- struts_right = g_slist_prepend(struts_right, &dock_strut);
+ ADD_STRUT_TO_LIST(struts_right, DESKTOP_ALL, &dock_strut);
if (dock_strut.bottom)
- struts_bottom = g_slist_prepend(struts_bottom, &dock_strut);
+ ADD_STRUT_TO_LIST(struts_bottom, DESKTOP_ALL, &dock_strut);
/* 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 * j + 0] = monitor_area[i].x;
- dims[i * j + 1] = monitor_area[i].y;
- dims[i * j + 2] = monitor_area[i].width;
- dims[i * j + 3] = monitor_area[i].height;
+ 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 */
/* only add the strut to the area if it touches the monitor */
for (sit = struts_left; sit; sit = g_slist_next(sit)) {
- StrutPartial *s = sit->data;
- if (RANGE_INTERSECT
- (s->left_start, s->left_end - s->left_start + 1,
- monitor_area[i].y, monitor_area[i].height))
- l = MAX(l, s->left);
+ 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)) {
- StrutPartial *s = sit->data;
- if (RANGE_INTERSECT
- (s->top_start, s->top_end - s->top_start + 1,
- monitor_area[i].x, monitor_area[i].width))
- t = MAX(t, s->top);
+ 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)) {
- StrutPartial *s = sit->data;
- if (RANGE_INTERSECT
- (s->right_start, s->right_end - s->right_start + 1,
- monitor_area[i].y, monitor_area[i].height))
- r = MAX(r, s->right);
+ 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)) {
- StrutPartial *s = sit->data;
- if (RANGE_INTERSECT
- (s->bottom_start, s->bottom_end - s->bottom_start + 1,
- monitor_area[i].x, monitor_area[i].width))
- b = MAX(b, s->bottom);
+ 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 * j + 0] += l;
- dims[i * j + 1] += t;
- dims[i * j + 2] -= l + r;
- dims[i * j + 3] -= t + b;
+ 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;
}
PROP_SETA32(RootWindow(ob_display, ob_screen), net_workarea, cardinal,
dims, 4 * screen_num_desktops * screen_num_monitors);
/* the area has changed, adjust all the windows if they need it */
- for (it = client_list; it; it = g_list_next(it)) {
- gint x, y, w, h, lw, lh;
- ObClient *client = it->data;
-
- RECT_TO_DIMS(client->area, x, y, w, h);
- client_try_configure(client, &x, &y, &w, &h, &lw, &lh, FALSE);
- if (!RECT_EQUAL_DIMS(client->area, x, y, w, h)) {
- gulong ignore_start;
-
- ignore_start = event_start_ignore_all_enters();
- client_configure(client, x, y, w, h, FALSE, TRUE);
- event_end_ignore_all_enters(ignore_start);
- }
- }
+ for (it = client_list; it; it = g_list_next(it))
+ client_reconfigure(it->data, FALSE);
g_free(dims);
}
-Rect* screen_area(guint desktop, Rect *search)
+#if 0
+Rect* screen_area_all_monitors(guint desktop)
{
guint i;
Rect *a;
- a = screen_area_monitor(desktop, 0, search);
+ a = screen_area_monitor(desktop, 0);
/* combine all the monitors together */
- for (i = 0; i < screen_num_monitors; ++i) {
- Rect *m = screen_area_monitor(desktop, i, search);
+ for (i = 1; i < screen_num_monitors; ++i) {
+ Rect *m = screen_area_monitor(desktop, i);
gint l, r, t, b;
l = MIN(RECT_LEFT(*a), RECT_LEFT(*m));
return a;
}
+#endif
-Rect* screen_area_monitor(guint desktop, guint head, Rect *search)
+#define STRUT_LEFT_IN_SEARCH(s, search) \
+ (RANGES_INTERSECT(search->y, search->height, \
+ s->left_start, s->left_end - s->left_start + 1))
+#define STRUT_RIGHT_IN_SEARCH(s, search) \
+ (RANGES_INTERSECT(search->y, search->height, \
+ s->right_start, s->right_end - s->right_start + 1))
+#define STRUT_TOP_IN_SEARCH(s, search) \
+ (RANGES_INTERSECT(search->x, search->width, \
+ s->top_start, s->top_end - s->top_start + 1))
+#define STRUT_BOTTOM_IN_SEARCH(s, search) \
+ (RANGES_INTERSECT(search->x, search->width, \
+ s->bottom_start, s->bottom_end - s->bottom_start + 1))
+
+#define STRUT_LEFT_IGNORE(s, us, search) \
+ (head == SCREEN_AREA_ALL_MONITORS && us && \
+ RECT_LEFT(monitor_area[i]) + s->left > RECT_LEFT(*search))
+#define STRUT_RIGHT_IGNORE(s, us, search) \
+ (head == SCREEN_AREA_ALL_MONITORS && us && \
+ RECT_RIGHT(monitor_area[i]) - s->right < RECT_RIGHT(*search))
+#define STRUT_TOP_IGNORE(s, us, search) \
+ (head == SCREEN_AREA_ALL_MONITORS && us && \
+ RECT_TOP(monitor_area[i]) + s->top > RECT_TOP(*search))
+#define STRUT_BOTTOM_IGNORE(s, us, search) \
+ (head == SCREEN_AREA_ALL_MONITORS && us && \
+ RECT_BOTTOM(monitor_area[i]) - s->bottom < RECT_BOTTOM(*search))
+
+Rect* screen_area(guint desktop, guint head, Rect *search)
{
Rect *a;
GSList *it;
- gint l, r, t, b;
+ gint l, r, t, b, al, ar, at, ab;
+ guint i, d;
+ gboolean us = search != NULL; /* user provided search */
- g_assert(head < screen_num_monitors);
+ g_assert(desktop < screen_num_desktops || desktop == DESKTOP_ALL);
+ g_assert(head < screen_num_monitors || head == SCREEN_AREA_ONE_MONITOR ||
+ head == SCREEN_AREA_ALL_MONITORS);
+ g_assert(!(head == SCREEN_AREA_ONE_MONITOR && search == NULL));
- /* get the base area for the monitor */
- a = g_new(Rect, 1);
- *a = monitor_area[head];
+ /* find any struts for this monitor
+ which will be affecting the search area.
+ */
- /* remove any struts which will be affecting the search area */
- l = t = r = b = 0;
- for (it = struts_left; it; it = g_slist_next(it)) {
- StrutPartial *s = it->data;
- if (!search ||
- RANGE_INTERSECT(search->y, search->height,
- s->left_start, s->left_end - s->left_start + 1))
- l = MAX(l, s->left);
- }
- for (it = struts_right; it; it = g_slist_next(it)) {
- StrutPartial *s = it->data;
- if (!search ||
- RANGE_INTERSECT(search->y, search->height,
- s->right_start, s->right_end - s->right_start + 1))
- r = MAX(r, s->right);
+ /* search everything if search is null */
+ if (!search) {
+ if (head < screen_num_monitors) search = &monitor_area[head];
+ else search = &monitor_area[screen_num_monitors];
}
- for (it = struts_top; it; it = g_slist_next(it)) {
- StrutPartial *s = it->data;
- if (!search ||
- RANGE_INTERSECT(search->x, search->width,
- s->top_start, s->top_end - s->top_start + 1))
- t = MAX(t, s->top);
+ if (head == SCREEN_AREA_ONE_MONITOR) head = screen_find_monitor(search);
+
+ /* al is "all left" meaning the furthest left you can get, l is our
+ "working left" meaning our current strut edge which we're calculating
+ */
+
+ /* only include monitors which the search area lines up with */
+ if (RECT_INTERSECTS_RECT(monitor_area[screen_num_monitors], *search)) {
+ al = l = RECT_RIGHT(monitor_area[screen_num_monitors]);
+ at = t = RECT_BOTTOM(monitor_area[screen_num_monitors]);
+ ar = r = RECT_LEFT(monitor_area[screen_num_monitors]);
+ ab = b = RECT_TOP(monitor_area[screen_num_monitors]);
+ for (i = 0; i < screen_num_monitors; ++i) {
+ /* add the monitor if applicable */
+ if (RANGES_INTERSECT(search->x, search->width,
+ monitor_area[i].x, monitor_area[i].width))
+ {
+ at = t = MIN(t, RECT_TOP(monitor_area[i]));
+ ab = b = MAX(b, RECT_BOTTOM(monitor_area[i]));
+ }
+ if (RANGES_INTERSECT(search->y, search->height,
+ monitor_area[i].y, monitor_area[i].height))
+ {
+ al = l = MIN(l, RECT_LEFT(monitor_area[i]));
+ ar = r = MAX(r, RECT_RIGHT(monitor_area[i]));
+ }
+ }
+ } else {
+ al = l = RECT_LEFT(monitor_area[screen_num_monitors]);
+ at = t = RECT_TOP(monitor_area[screen_num_monitors]);
+ ar = r = RECT_RIGHT(monitor_area[screen_num_monitors]);
+ ab = b = RECT_BOTTOM(monitor_area[screen_num_monitors]);
}
- for (it = struts_bottom; it; it = g_slist_next(it)) {
- StrutPartial *s = it->data;
- if (!search ||
- RANGE_INTERSECT(search->x, search->width,
- s->bottom_start,
- s->bottom_end - s->bottom_start + 1))
- b = MAX(b, s->bottom);
+
+ for (d = 0; d < screen_num_desktops; ++d) {
+ if (d != desktop && desktop != DESKTOP_ALL) continue;
+
+ for (i = 0; i < screen_num_monitors; ++i) {
+ if (head != SCREEN_AREA_ALL_MONITORS && head != i) continue;
+
+ for (it = struts_left; it; it = g_slist_next(it)) {
+ ObScreenStrut *s = it->data;
+ if ((s->desktop == d || s->desktop == DESKTOP_ALL) &&
+ STRUT_LEFT_IN_SEARCH(s->strut, search) &&
+ !STRUT_LEFT_IGNORE(s->strut, us, search))
+ l = MAX(l, al + s->strut->left);
+ }
+ for (it = struts_top; it; it = g_slist_next(it)) {
+ ObScreenStrut *s = it->data;
+ if ((s->desktop == d || s->desktop == DESKTOP_ALL) &&
+ STRUT_TOP_IN_SEARCH(s->strut, search) &&
+ !STRUT_TOP_IGNORE(s->strut, us, search))
+ t = MAX(t, at + s->strut->top);
+ }
+ for (it = struts_right; it; it = g_slist_next(it)) {
+ ObScreenStrut *s = it->data;
+ if ((s->desktop == d || s->desktop == DESKTOP_ALL) &&
+ STRUT_RIGHT_IN_SEARCH(s->strut, search) &&
+ !STRUT_RIGHT_IGNORE(s->strut, us, search))
+ r = MIN(r, ar - s->strut->right);
+ }
+ for (it = struts_bottom; it; it = g_slist_next(it)) {
+ ObScreenStrut *s = it->data;
+ if ((s->desktop == d || s->desktop == DESKTOP_ALL) &&
+ STRUT_BOTTOM_IN_SEARCH(s->strut, search) &&
+ !STRUT_BOTTOM_IGNORE(s->strut, us, search))
+ b = MIN(b, ab - s->strut->bottom);
+ }
+
+ /* limit to this monitor */
+ if (head == i) {
+ l = MAX(l, RECT_LEFT(monitor_area[i]));
+ t = MAX(t, RECT_TOP(monitor_area[i]));
+ r = MIN(r, RECT_RIGHT(monitor_area[i]));
+ b = MIN(b, RECT_BOTTOM(monitor_area[i]));
+ }
+ }
}
- a->x += l;
- a->y += t;
- a->width -= l + r;
- a->height -= t + b;
+ a = g_new(Rect, 1);
+ a->x = l;
+ a->y = t;
+ a->width = r - l + 1;
+ a->height = b - t + 1;
return a;
}
return most;
}
-Rect* screen_physical_area()
+Rect* screen_physical_area_all_monitors()
{
return screen_physical_area_monitor(screen_num_monitors);
}
return a;
}
-Rect* screen_physical_area_monitor_active()
+gboolean screen_physical_area_monitor_contains(guint head, Rect *search)
+{
+ g_assert(head <= screen_num_monitors);
+ g_assert(search);
+ return RECT_INTERSECTS_RECT(monitor_area[head], *search);
+}
+
+Rect* screen_physical_area_active()
{
Rect *a;
gint x, y;