X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fscreen.c;h=92d4d9a421bac5db1a62a8b59fc81cc9fee8f6b4;hb=15d615853671b0988b9a87720cac2762c702f28b;hp=613f774f71d03e2b2cafd8c6e8710d75f814d12a;hpb=809619497d73598a9f3c2bd2e4b8968297af6bfd;p=chaz%2Fopenbox diff --git a/openbox/screen.c b/openbox/screen.c index 613f774f..92d4d9a4 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -66,11 +66,12 @@ Window screen_support_win; 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; @@ -730,7 +731,7 @@ void screen_desktop_popup(guint d, gboolean show) 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, @@ -1083,6 +1084,35 @@ void screen_install_colormap(ObClient *client, gboolean install) } } +#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; @@ -1097,39 +1127,39 @@ void screen_update_areas() 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 */ @@ -1140,74 +1170,59 @@ void screen_update_areas() /* 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)); @@ -1222,55 +1237,140 @@ Rect* screen_area(guint desktop, Rect *search) 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; } @@ -1299,7 +1399,7 @@ guint screen_find_monitor(Rect *search) return most; } -Rect* screen_physical_area() +Rect* screen_physical_area_all_monitors() { return screen_physical_area_monitor(screen_num_monitors); } @@ -1314,7 +1414,14 @@ Rect* screen_physical_area_monitor(guint head) 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;