X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=i3bar%2Fsrc%2Fxcb.c;h=c0486181b02933db87200396c318e0ee322924e2;hb=5d70e2850f87bbdac7fe98f08411f3bfb159adba;hp=39368c88bdd673546572d875e9866a1fad288628;hpb=c40c79538e0b9b873f3f921d0a4473d7dad74566;p=i3%2Fi3 diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 39368c88..c0486181 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -92,6 +92,9 @@ static mode binding; /* Indicates whether a new binding mode was recently activated */ bool activated_mode = false; +/* The output in which the tray should be displayed. */ +static i3_output *output_for_tray; + /* The parsed colors */ struct xcb_colors_t { color_t bar_fg; @@ -146,13 +149,13 @@ int _xcb_request_failed(xcb_void_cookie_t cookie, char *err_msg, int line) { return 0; } -uint32_t get_sep_offset(struct status_block *block) { +static uint32_t get_sep_offset(struct status_block *block) { if (!block->no_separator && block->sep_block_width > 0) return block->sep_block_width / 2 + block->sep_block_width % 2; return 0; } -int get_tray_width(struct tc_head *trayclients) { +static int get_tray_width(struct tc_head *trayclients) { trayclient *trayclient; int tray_width = 0; TAILQ_FOREACH_REVERSE(trayclient, trayclients, tc_head, tailq) { @@ -193,7 +196,7 @@ static void draw_separator(i3_output *output, uint32_t x, struct status_block *b } } -uint32_t predict_statusline_length(bool use_short_text) { +static uint32_t predict_statusline_length(bool use_short_text) { uint32_t width = 0; struct status_block *block; @@ -245,7 +248,7 @@ uint32_t predict_statusline_length(bool use_short_text) { /* * Redraws the statusline to the output's statusline_buffer */ -void draw_statusline(i3_output *output, uint32_t clip_left, bool use_focus_colors, bool use_short_text) { +static void draw_statusline(i3_output *output, uint32_t clip_left, bool use_focus_colors, bool use_short_text) { struct status_block *block; color_t bar_color = (use_focus_colors ? colors.focus_bar_bg : colors.bar_bg); @@ -330,7 +333,7 @@ void draw_statusline(i3_output *output, uint32_t clip_left, bool use_focus_color * Hides all bars (unmaps them) * */ -void hide_bars(void) { +static void hide_bars(void) { if ((config.hide_on_modifier == M_DOCK) || (config.hidden_state == S_SHOW && config.hide_on_modifier == M_HIDE)) { return; } @@ -349,7 +352,7 @@ void hide_bars(void) { * Unhides all bars (maps them) * */ -void unhide_bars(void) { +static void unhide_bars(void) { if (config.hide_on_modifier != M_HIDE) { return; } @@ -457,7 +460,7 @@ static bool execute_custom_command(xcb_keycode_t input_code, bool event_is_relea * wheel was used and change the workspace appropriately * */ -void handle_button(xcb_button_press_event_t *event) { +static void handle_button(xcb_button_press_event_t *event) { /* Determine, which bar was clicked */ i3_output *walk; xcb_window_t bar = event->event; @@ -758,58 +761,16 @@ static void handle_client_message(xcb_client_message_event_t *event) { } DLOG("X window %08x requested docking\n", client); - i3_output *output = NULL; - i3_output *walk = NULL; - tray_output_t *tray_output = NULL; - /* We need to iterate through the tray_output assignments first in - * order to prioritize them. Otherwise, if this bar manages two - * outputs and both are assigned as tray_output as well, the first - * output in our list would receive the tray rather than the first - * one defined via tray_output. */ - TAILQ_FOREACH(tray_output, &(config.tray_outputs), tray_outputs) { - SLIST_FOREACH(walk, outputs, slist) { - if (!walk->active) - continue; - - if (strcasecmp(walk->name, tray_output->output) == 0) { - DLOG("Found tray_output assignment for output %s.\n", walk->name); - output = walk; - break; - } - if (walk->primary && strcasecmp("primary", tray_output->output) == 0) { - DLOG("Found tray_output assignment on primary output %s.\n", walk->name); - output = walk; - break; - } - } - - /* If we found an output, we're done. */ - if (output != NULL) - break; - } - - /* If no tray_output has been specified, we fall back to the first - * available output. */ - if (output == NULL && TAILQ_EMPTY(&(config.tray_outputs))) { - SLIST_FOREACH(walk, outputs, slist) { - if (!walk->active) - continue; - DLOG("Falling back to output %s because no primary output is configured\n", walk->name); - output = walk; - break; - } - } - - if (output == NULL) { - ELOG("No output found\n"); + if (output_for_tray == NULL) { + ELOG("No output found for tray\n"); return; } xcb_void_cookie_t rcookie = xcb_reparent_window(xcb_connection, client, - output->bar.id, - output->rect.w - icon_size - logical_px(config.tray_padding), + output_for_tray->bar.id, + output_for_tray->rect.w - icon_size - logical_px(config.tray_padding), logical_px(config.tray_padding)); if (xcb_request_failed(rcookie, "Could not reparent window. Maybe it is using an incorrect depth/visual?")) return; @@ -836,7 +797,7 @@ static void handle_client_message(xcb_client_message_event_t *event) { ev->format = 32; ev->data.data32[0] = XCB_CURRENT_TIME; ev->data.data32[1] = XEMBED_EMBEDDED_NOTIFY; - ev->data.data32[2] = output->bar.id; + ev->data.data32[2] = output_for_tray->bar.id; ev->data.data32[3] = xe_version; xcb_send_event(xcb_connection, 0, @@ -856,7 +817,7 @@ static void handle_client_message(xcb_client_message_event_t *event) { tc->win = client; tc->xe_version = xe_version; tc->mapped = false; - TAILQ_INSERT_TAIL(output->trayclients, tc, tailq); + TAILQ_INSERT_TAIL(output_for_tray->trayclients, tc, tailq); if (map_it) { DLOG("Mapping dock client\n"); @@ -1080,7 +1041,7 @@ static void handle_resize_request(xcb_resize_request_event_t *event) { * events from X11, handle them, then flush our outgoing queue. * */ -void xcb_prep_cb(struct ev_loop *loop, ev_prepare *watcher, int revents) { +static void xcb_prep_cb(struct ev_loop *loop, ev_prepare *watcher, int revents) { xcb_generic_event_t *event; if (xcb_connection_has_error(xcb_connection)) { @@ -1180,7 +1141,7 @@ void xcb_prep_cb(struct ev_loop *loop, ev_prepare *watcher, int revents) { * are triggered * */ -void xcb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { +static void xcb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { } /* @@ -1188,7 +1149,7 @@ void xcb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { * depend on 'config'. * */ -char *init_xcb_early() { +char *init_xcb_early(void) { /* FIXME: xcb_connect leaks memory */ xcb_connection = xcb_connect(NULL, &screen); if (xcb_connection_has_error(xcb_connection)) { @@ -1251,7 +1212,7 @@ char *init_xcb_early() { * in xcb. * */ -void register_xkb_keyevents() { +static void register_xkb_keyevents(void) { const xcb_query_extension_reply_t *extreply; extreply = xcb_get_extension_data(conn, &xcb_xkb_id); if (!extreply->present) { @@ -1275,7 +1236,7 @@ void register_xkb_keyevents() { * Deregister from xkb keyevents. * */ -void deregister_xkb_keyevents() { +static void deregister_xkb_keyevents(void) { xcb_xkb_select_events(conn, XCB_XKB_ID_USE_CORE_KBD, 0, @@ -1341,7 +1302,7 @@ static void send_tray_clientmessage(void) { * atom. Afterwards, tray clients will send ClientMessages to our window. * */ -void init_tray(void) { +static void init_tray(void) { DLOG("Initializing system tray functionality\n"); /* request the tray manager atom for the X11 display we are running on */ char atomname[strlen("_NET_SYSTEM_TRAY_S") + 11]; @@ -1570,7 +1531,7 @@ void destroy_window(i3_output *output) { /* Strut partial tells i3 where to reserve space for i3bar. This is determined * by the `position` bar config directive. */ -xcb_void_cookie_t config_strut_partial(i3_output *output) { +static xcb_void_cookie_t config_strut_partial(i3_output *output) { /* A local struct to save the strut_partial property */ struct { uint32_t left; @@ -1612,6 +1573,56 @@ xcb_void_cookie_t config_strut_partial(i3_output *output) { &strut_partial); } +/* + * Returns the output which should hold the tray, if one exists. + * + * An output is returned in these scenarios: + * 1. A specific output was listed in tray_outputs which is also in the list + * of outputs managed by this bar. + * 2. No tray_output directive was specified. In this case, we use the first + * available output. + * 3. 'tray_output primary' was specified. In this case we use the primary + * output. + * + * Three scenarios in which we specifically don't want to use a tray: + * 1. 'tray_output none' was specified. + * 2. A specific output was listed as a tray_output, but is not one of the + * outputs managed by this bar. For example, consider tray_outputs == [VGA-1], + * but outputs == [HDMI-1]. + * 3. 'tray_output primary' was specified and no output in the list is + * primary. + */ +static i3_output *get_tray_output(void) { + i3_output *output = NULL; + if (TAILQ_EMPTY(&(config.tray_outputs))) { + /* No tray_output specified, use first active output. */ + SLIST_FOREACH(output, outputs, slist) { + if (output->active) { + return output; + } + } + return NULL; + } else if (strcasecmp(TAILQ_FIRST(&(config.tray_outputs))->output, "none") == 0) { + /* Check for "tray_output none" */ + return NULL; + } + + /* If one or more tray_output assignments were specified, we ensure that at + * least one of them is actually an output managed by this instance. */ + tray_output_t *tray_output; + TAILQ_FOREACH(tray_output, &(config.tray_outputs), tray_outputs) { + SLIST_FOREACH(output, outputs, slist) { + if (output->active && + (strcasecmp(output->name, tray_output->output) == 0 || + (strcasecmp(tray_output->output, "primary") == 0 && output->primary))) { + return output; + } + } + } + + return NULL; +} + /* * Reconfigure all bars and create new bars for recently activated outputs * @@ -1619,7 +1630,6 @@ xcb_void_cookie_t config_strut_partial(i3_output *output) { void reconfig_windows(bool redraw_bars) { uint32_t mask; uint32_t values[6]; - static bool tray_configured = false; i3_output *walk; SLIST_FOREACH(walk, outputs, slist) { @@ -1747,58 +1757,6 @@ void reconfig_windows(bool redraw_bars) { exit(EXIT_FAILURE); } - /* Unless "tray_output none" was specified, we need to initialize the tray. */ - bool no_tray = false; - if (!(TAILQ_EMPTY(&(config.tray_outputs)))) { - no_tray = strcasecmp(TAILQ_FIRST(&(config.tray_outputs))->output, "none") == 0; - } - - /* - * There are three scenarios in which we need to initialize the tray: - * 1. A specific output was listed in tray_outputs which is also - * in the list of outputs managed by this bar. - * 2. No tray_output directive was specified. In this case, we - * use the first available output. - * 3. 'tray_output primary' was specified. In this case we use the - * primary output. - * - * Three scenarios in which we specifically don't want to - * initialize the tray are: - * 1. 'tray_output none' was specified. - * 2. A specific output was listed as a tray_output, but is not - * one of the outputs managed by this bar. For example, consider - * tray_outputs == [VGA-1], but outputs == [HDMI-1]. - * 3. 'tray_output primary' was specified and no output in the list - * is primary. - */ - if (!tray_configured && !no_tray) { - /* If no tray_output was specified, we go ahead and initialize the tray as - * we will be using the first available output. */ - if (TAILQ_EMPTY(&(config.tray_outputs))) { - init_tray(); - } - - /* If one or more tray_output assignments were specified, we ensure that at least one of - * them is actually an output managed by this instance. */ - tray_output_t *tray_output; - TAILQ_FOREACH(tray_output, &(config.tray_outputs), tray_outputs) { - i3_output *output; - bool found = false; - SLIST_FOREACH(output, outputs, slist) { - if (strcasecmp(output->name, tray_output->output) == 0 || - (strcasecmp(tray_output->output, "primary") == 0 && output->primary)) { - found = true; - init_tray(); - break; - } - } - - if (found) - break; - } - - tray_configured = true; - } } else { /* We already have a bar, so we just reconfigure it */ mask = XCB_CONFIG_WINDOW_X | @@ -1892,6 +1850,19 @@ void reconfig_windows(bool redraw_bars) { } } } + + /* Finally, check if we want to initialize the tray or destroy the selection + * window. The result of get_tray_output() is cached. */ + output_for_tray = get_tray_output(); + if (output_for_tray) { + if (selwin == XCB_NONE) { + init_tray(); + } + } else if (selwin != XCB_NONE) { + DLOG("Destroying tray selection window\n"); + xcb_destroy_window(xcb_connection, selwin); + selwin = XCB_NONE; + } } /*