+
+ return a;
+}
+#endif
+
+#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;
+ guint i, d;
+ gboolean us = search != NULL; /* user provided search */
+
+ 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));
+
+ /* find any struts for this monitor
+ which will be affecting the search area.
+ */
+
+ /* search everything if search is null */
+ if (!search) {
+ if (head < screen_num_monitors) search = &monitor_area[head];
+ else search = &monitor_area[screen_num_monitors];
+ }
+ 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)) {
+ l = RECT_RIGHT(monitor_area[screen_num_monitors]);
+ t = RECT_BOTTOM(monitor_area[screen_num_monitors]);
+ r = RECT_LEFT(monitor_area[screen_num_monitors]);
+ 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))
+ {
+ t = MIN(t, RECT_TOP(monitor_area[i]));
+ b = MAX(b, RECT_BOTTOM(monitor_area[i]));
+ }
+ if (RANGES_INTERSECT(search->y, search->height,
+ monitor_area[i].y, monitor_area[i].height))
+ {
+ l = MIN(l, RECT_LEFT(monitor_area[i]));
+ r = MAX(r, RECT_RIGHT(monitor_area[i]));
+ }
+ }
+ } else {
+ l = RECT_LEFT(monitor_area[screen_num_monitors]);
+ t = RECT_TOP(monitor_area[screen_num_monitors]);
+ r = RECT_RIGHT(monitor_area[screen_num_monitors]);
+ b = RECT_BOTTOM(monitor_area[screen_num_monitors]);
+ }
+
+ 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, RECT_LEFT(monitor_area[screen_num_monitors])
+ + 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, RECT_TOP(monitor_area[screen_num_monitors])
+ + 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, RECT_RIGHT(monitor_area[screen_num_monitors])
+ - 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, RECT_BOTTOM(monitor_area[screen_num_monitors])
+ - 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 = g_slice_new(Rect);
+ a->x = l;
+ a->y = t;
+ a->width = r - l + 1;
+ a->height = b - t + 1;
+ return a;
+}
+
+guint screen_find_monitor(const Rect *search)
+{
+ guint i;
+ guint most = screen_num_monitors;
+ guint mostv = 0;
+
+ for (i = 0; i < screen_num_monitors; ++i) {
+ const Rect *area = screen_physical_area_monitor(i);
+ if (RECT_INTERSECTS_RECT(*area, *search)) {
+ Rect r;
+ guint v;
+
+ RECT_SET_INTERSECTION(r, *area, *search);
+ v = r.width * r.height;
+
+ if (v > mostv) {
+ mostv = v;
+ most = i;
+ }
+ }
+ }
+ return most;
+}
+
+const Rect* screen_physical_area_all_monitors(void)
+{
+ return screen_physical_area_monitor(screen_num_monitors);
+}
+
+const Rect* screen_physical_area_monitor(guint head)
+{
+ g_assert(head <= screen_num_monitors);
+
+ return &monitor_area[head];
+}
+
+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);
+}
+
+guint screen_monitor_active(void)
+{
+ if (moveresize_client)
+ return client_monitor(moveresize_client);
+ else if (focus_client)
+ return client_monitor(focus_client);
+ else
+ return screen_monitor_pointer();
+}
+
+const Rect* screen_physical_area_active(void)
+{
+ return screen_physical_area_monitor(screen_monitor_active());
+}
+
+guint screen_monitor_primary(gboolean fixed)
+{
+ if (config_primary_monitor_index > 0) {
+ if (config_primary_monitor_index-1 < screen_num_monitors)
+ return config_primary_monitor_index - 1;
+ else
+ return 0;
+ }
+ else if (fixed)
+ return 0;
+ else if (config_primary_monitor == OB_PLACE_MONITOR_ACTIVE)
+ return screen_monitor_active();
+ else /* config_primary_monitor == OB_PLACE_MONITOR_MOUSE */
+ return screen_monitor_pointer();
+}
+
+const Rect* screen_physical_area_primary(gboolean fixed)
+{
+ return screen_physical_area_monitor(screen_monitor_primary(fixed));
+}
+
+void screen_set_root_cursor(void)
+{
+ if (sn_app_starting())
+ XDefineCursor(obt_display, obt_root(ob_screen),
+ ob_cursor(OB_CURSOR_BUSYPOINTER));
+ else
+ XDefineCursor(obt_display, obt_root(ob_screen),
+ ob_cursor(OB_CURSOR_POINTER));
+}
+
+guint screen_find_monitor_point(guint x, guint y)
+{
+ Rect mon;
+ RECT_SET(mon, x, y, 1, 1);
+ return screen_find_monitor(&mon);
+}
+
+guint screen_monitor_pointer()
+{
+ gint x, y;
+ if (!screen_pointer_pos(&x, &y))
+ x = y = 0;
+ return screen_find_monitor_point(x, y);