+static void child_handle_button(xcb_button_press_event_t *event, i3_output *output, int32_t x) {
+ if (!child_want_click_events()) {
+ return;
+ }
+
+ const int tray_width = get_tray_width(output->trayclients);
+ /* Calculate the horizontal coordinate (x) of the start of the statusline by
+ * subtracting its width and the width of the tray from the bar width. */
+ const int offset = output->rect.w - output->statusline_width - tray_width - logical_px((tray_width > 0) * sb_hoff_px);
+ /* x of the click event relative to the start of the statusline. */
+ const uint32_t statusline_x = x - offset;
+
+ if (x < offset || statusline_x > (uint32_t)output->statusline_width) {
+ return;
+ }
+
+ /* x of the start of the current block relative to the statusline. */
+ uint32_t last_block_x = 0;
+ struct status_block *block;
+ TAILQ_FOREACH(block, &statusline_head, blocks) {
+ i3String *text;
+ struct status_block_render_desc *render;
+ if (output->statusline_short_text && block->short_text != NULL) {
+ text = block->short_text;
+ render = &block->short_render;
+ } else {
+ text = block->full_text;
+ render = &block->full_render;
+ }
+
+ if (i3string_get_num_bytes(text) == 0) {
+ continue;
+ }
+
+ /* Include the whole block in our calculations: when min_width is
+ * specified, we have to take padding width into account. */
+ const uint32_t full_render_width = render->width + render->x_offset + render->x_append;
+ /* x of the click event relative to the current block. */
+ const uint32_t relative_x = statusline_x - last_block_x;
+ if (relative_x <= full_render_width) {
+ send_block_clicked(event->detail, block->name, block->instance,
+ event->root_x, event->root_y, relative_x,
+ event->event_y, full_render_width, bar_height,
+ event->state);
+ return;
+ }
+
+ last_block_x += full_render_width + block->sep_block_width;
+ if (last_block_x > statusline_x) {
+ /* Click was on a separator. */
+ return;
+ }
+ }
+}
+