diff --git a/bar.c b/bar.c index 90c2229..a4492e9 100644 --- a/bar.c +++ b/bar.c @@ -34,6 +34,7 @@ typedef struct monitor_t { } monitor_t; typedef struct area_t { + bool active; int begin, end, align, button; xcb_window_t window; char *cmd; @@ -219,11 +220,15 @@ set_attribute (const char modifier, const char attribute) area_t * -area_get (xcb_window_t win, const int x) +area_get (xcb_window_t win, const int btn, const int x) { - for (int i = 0; i < astack.pos; i++) - if (astack.slot[i].window == win && x >= astack.slot[i].begin && x < astack.slot[i].end) - return &astack.slot[i]; + /* Looping backwards ensures that we get the innermost area first */ + for (int i = astack.pos; i >= 0; i--) { + area_t *a = &astack.slot[i]; + if (a->window == win && a->button == btn + && x >= a->begin && x < a->end) + return a; + } return NULL; } @@ -248,17 +253,18 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x { char *p = str; char *trail; - area_t *a = &astack.slot[astack.pos]; - - if (astack.pos == N) { - fprintf(stderr, "astack overflow!\n"); - return false; - } + area_t *a; // A wild close area tag appeared! if (*p != ':') { *end = p; + /* Find most recent unclosed area. */ + int i; + for (i = astack.pos - 1; i >= 0 && !astack.slot[i].active; i--) + ; + a = &astack.slot[i]; + // Basic safety checks if (!a->cmd || a->align != align || a->window != mon->window) return false; @@ -280,11 +286,16 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x break; } - astack.pos++; - + a->active = false; return true; } + if (astack.pos >= N) { + fprintf(stderr, "astack overflow!\n"); + return false; + } + a = &astack.slot[astack.pos++]; + // Found the closing : and check if it's just an escaped one for (trail = strchr(++p, ':'); trail && trail[-1] == '\\'; trail = strchr(trail + 1, ':')) ; @@ -308,6 +319,7 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x // This is a pointer to the string buffer allocated in the main a->cmd = p; + a->active = true; a->align = align; a->begin = x; a->window = mon->window; @@ -1191,7 +1203,7 @@ main (int argc, char **argv) case XCB_BUTTON_PRESS: press_ev = (xcb_button_press_event_t *)ev; { - area_t *area = area_get(press_ev->event, press_ev->event_x); + area_t *area = area_get(press_ev->event, press_ev->detail, press_ev->event_x); // Respond to the click if (area && area->button == press_ev->detail) { write(STDOUT_FILENO, area->cmd, strlen(area->cmd));