diff --git a/bar.c b/bar.c index c12ef1f..9a0a179 100644 --- a/bar.c +++ b/bar.c @@ -44,6 +44,7 @@ typedef struct screen_t { } screen_t; static xcb_connection_t *c; +static xcb_screen_t *scr; static xcb_window_t win; static xcb_drawable_t canvas; static xcb_gcontext_t draw_gc; @@ -488,14 +489,58 @@ get_randr_outputs(xcb_window_t w, screen_t **spp) return cnt; } +int +screen_adjust (screen_t *s, int num, screen_t **spp) +{ + int i, cnt, right_bar_offset; + screen_t *t; + + /* Add BAR_OFFSET to the last screen */ + right_bar_offset = scr->width_in_pixels - bar_width - BAR_OFFSET; + + for (cnt = num, i = num-1; i >= 0; i--) { + if (right_bar_offset > 0) { + if (right_bar_offset >= s[i].width) { + /* Remove the screen */ + cnt--; + right_bar_offset -= s[i].width; + } else { + s[i].width -= right_bar_offset; + right_bar_offset = 0; + } + } + + s[i].x -= BAR_OFFSET; + if (s[i].x < 0) { + /* First screen */ + s[i].x = 0; + break; + } + } + + /* Remove BAR_OFFSET from the first screen */ + s[i].width -= BAR_OFFSET; + + t = calloc(cnt, sizeof(screen_t)); + if (t == NULL) + exit(1); + + for (i = 0; i < cnt; i++) { + t[i].x = s[i].x; + t[i].width = s[i].width; + } + + *spp = t; + + return cnt; +} void init (void) { - xcb_screen_t *scr; xcb_window_t root; - screen_t *temp; + screen_t *stemp; + int snum; int y; - int right_bar_offset; xcb_generic_error_t *err; const xcb_query_extension_reply_t *ext_reply; @@ -519,46 +564,18 @@ init (void) exit (1); /* Generate a list of screens */ - num_screens = 0; + snum = 0; if ((ext_reply = xcb_get_extension_data(c, &xcb_randr_id)) && ext_reply->present) { - num_screens = get_randr_outputs(root, &screens); - randr_event = ext_reply->first_event; + snum = get_randr_outputs(root, &stemp); + if (snum) + randr_event = ext_reply->first_event; } else if ((ext_reply = xcb_get_extension_data(c, &xcb_xinerama_id)) && ext_reply->present) - num_screens = get_xinerama_outputs(root, &screens); + snum = get_xinerama_outputs(root, &stemp); - if (num_screens) { - int i, num_saved = num_screens; - /* Add BAR_OFFSET to the last screen */ - right_bar_offset = scr->width_in_pixels - bar_width - BAR_OFFSET; - for (i = num_screens-1; i >= 0; i--) { - if (right_bar_offset > 0) { - if (right_bar_offset >= screens[i].width) { - /* Remove the screen */ - num_screens--; - right_bar_offset -= screens[i].width; - } else { - screens[i].width -= right_bar_offset; - right_bar_offset = 0; - } - } - - screens[i].x -= BAR_OFFSET; - if (screens[i].x < 0) { - /* First screen */ - screens[i].x = 0; - break; - } - } - /* Remove BAR_OFFSET from the first screen */ - screens[i].width -= BAR_OFFSET; - - /* Reallocate */ - if (num_screens > num_saved) { - screens = realloc (screens, num_screens); - if (screens == NULL) - exit (1); - } + if (snum) { + num_screens = screen_adjust(stemp, snum, &screens); + free(stemp); } else { num_screens = 1; screens = calloc(1, sizeof(screen_t)); @@ -630,6 +647,18 @@ sighandle (int signal) exit (0); } +void +handle_randr_event (xcb_generic_event_t *ev) +{ + int num; + screen_t *s, *t = screens; + + num = get_randr_outputs(scr->root, &s); + num_screens = screen_adjust(s, num, &screens); + free(s); + free(t); +} + int main (int argc, char **argv) { @@ -685,12 +714,14 @@ main (int argc, char **argv) } if (pollin[1].revents & POLLIN) { /* Xserver broadcasted an event */ while ((ev = xcb_poll_for_event (c))) { - expose_ev = (xcb_expose_event_t *)ev; + int type = ev->response_type & 0x7f; - switch (ev->response_type & 0x7F) { - case XCB_EXPOSE: - if (expose_ev->count == 0) redraw = 1; - break; + if (randr_event > -1 && type == randr_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY) + handle_randr_event(ev); + else if (type == XCB_EXPOSE) { + expose_ev = (xcb_expose_event_t *)ev; + if (expose_ev->count == 0) + redraw = 1; } free (ev);