diff --git a/docs/userguide b/docs/userguide index d1660c49..13dae4fe 100644 --- a/docs/userguide +++ b/docs/userguide @@ -1011,31 +1011,6 @@ force_display_urgency_hint ms force_display_urgency_hint 500 ms --------------------------------- -=== Delaying exiting on zero displays - -Outputs may disappear momentarily and come back later. For example, -using a docking station that does not announce the undock (e.g. ACPI Undock -event triggered through manually pushing a button before actually ejecting -the notebook). During the removal of the notebook from the docking station, -all outputs disappear momentarily. - -To prevent i3 from exiting when no output is available momentarily, you can -tell i3 to delay a certain time first and check available outputs again using -the +delay_exit_on_zero_displays+ directive. Setting the value to 0 disables -this feature. - -The default is 500ms. - -*Syntax*: ----------------------------------------- -delay_exit_on_zero_displays ms ----------------------------------------- - -*Example*: ----------------------------------- -delay_exit_on_zero_displays 500 ms ----------------------------------- - === Focus on window activation [[focus_on_window_activation]] diff --git a/include/config.h b/include/config.h index ff360bb5..fd6fe6c0 100644 --- a/include/config.h +++ b/include/config.h @@ -167,10 +167,6 @@ struct Config { * flag can be delayed using an urgency timer. */ float workspace_urgency_timer; - /** Use a timer to delay exiting when no output is available. - * This can prevent i3 from exiting when all outputs disappear momentarily. */ - float zero_disp_exit_timer_ms; - /** Behavior when a window sends a NET_ACTIVE_WINDOW message. */ enum { /* Focus if the target workspace is visible, set urgency hint otherwise. */ diff --git a/include/config_directives.h b/include/config_directives.h index 72646651..c0c70bb4 100644 --- a/include/config_directives.h +++ b/include/config_directives.h @@ -51,7 +51,6 @@ CFGFUN(force_focus_wrapping, const char *value); CFGFUN(force_xinerama, const char *value); CFGFUN(fake_outputs, const char *outputs); CFGFUN(force_display_urgency_hint, const long duration_ms); -CFGFUN(delay_exit_on_zero_displays, const long duration_ms); CFGFUN(focus_on_window_activation, const char *mode); CFGFUN(show_marks, const char *value); CFGFUN(hide_edge_borders, const char *borders); diff --git a/include/randr.h b/include/randr.h index 823ddea4..2c379f6f 100644 --- a/include/randr.h +++ b/include/randr.h @@ -29,13 +29,6 @@ typedef enum { */ void randr_init(int *event_base); -/** - * Disables RandR support by creating exactly one output with the size of the - * X11 screen. - * - */ -void disable_randr(xcb_connection_t *conn); - /** * Initializes a CT_OUTPUT Con (searches existing ones from inplace restart * before) to use for the given Output. @@ -120,3 +113,9 @@ Output *get_output_next(direction_t direction, Output *current, output_close_far * */ Output *get_output_next_wrap(direction_t direction, Output *current); + +/* + * Creates an output covering the root window. + * + */ +void create_root_output(xcb_connection_t *conn); diff --git a/parser-specs/config.spec b/parser-specs/config.spec index 1191157c..b9542c8c 100644 --- a/parser-specs/config.spec +++ b/parser-specs/config.spec @@ -39,7 +39,6 @@ state INITIAL: 'workspace_auto_back_and_forth' -> WORKSPACE_BACK_AND_FORTH 'fake_outputs', 'fake-outputs' -> FAKE_OUTPUTS 'force_display_urgency_hint' -> FORCE_DISPLAY_URGENCY_HINT - 'delay_exit_on_zero_displays' -> DELAY_EXIT_ON_ZERO_DISPLAYS 'focus_on_window_activation' -> FOCUS_ON_WINDOW_ACTIVATION 'show_marks' -> SHOW_MARKS 'workspace' -> WORKSPACE @@ -228,17 +227,6 @@ state FORCE_DISPLAY_URGENCY_HINT_MS: end -> call cfg_force_display_urgency_hint(&duration_ms) -# delay_exit_on_zero_displays ms -state DELAY_EXIT_ON_ZERO_DISPLAYS: - duration_ms = number - -> DELAY_EXIT_ON_ZERO_DISPLAYS_MS - -state DELAY_EXIT_ON_ZERO_DISPLAYS_MS: - 'ms' - -> - end - -> call cfg_delay_exit_on_zero_displays(&duration_ms) - # focus_on_window_activation state FOCUS_ON_WINDOW_ACTIVATION: mode = word diff --git a/src/config.c b/src/config.c index 0dc59365..d8db85e6 100644 --- a/src/config.c +++ b/src/config.c @@ -206,10 +206,6 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath, if (config.workspace_urgency_timer == 0) config.workspace_urgency_timer = 0.5; - /* Set default zero displays exit delay to 500ms */ - if (config.zero_disp_exit_timer_ms == 0) - config.zero_disp_exit_timer_ms = 500; - parse_configuration(override_configpath, true); if (reload) { diff --git a/src/config_directives.c b/src/config_directives.c index 463b38e7..d772387d 100644 --- a/src/config_directives.c +++ b/src/config_directives.c @@ -367,10 +367,6 @@ CFGFUN(force_display_urgency_hint, const long duration_ms) { config.workspace_urgency_timer = duration_ms / 1000.0; } -CFGFUN(delay_exit_on_zero_displays, const long duration_ms) { - config.zero_disp_exit_timer_ms = duration_ms; -} - CFGFUN(focus_on_window_activation, const char *mode) { if (strcmp(mode, "smart") == 0) config.focus_on_window_activation = FOWA_SMART; diff --git a/src/main.c b/src/main.c index b4ec3720..0dc25936 100644 --- a/src/main.c +++ b/src/main.c @@ -655,8 +655,6 @@ int main(int argc, char *argv[]) { ELOG("ERROR: No screen at (%d, %d), starting on the first screen\n", pointerreply->root_x, pointerreply->root_y); output = get_first_output(); - if (!output) - die("No usable outputs available.\n"); } con_focus(con_descend_focused(output_get_content(output->con))); diff --git a/src/randr.c b/src/randr.c index 7cf9d99e..23dd98d5 100644 --- a/src/randr.c +++ b/src/randr.c @@ -27,7 +27,8 @@ xcb_randr_get_output_primary_reply_t *primary; /* Stores all outputs available in your current session. */ struct outputs_head outputs = TAILQ_HEAD_INITIALIZER(outputs); -static bool randr_disabled = false; +/* This is the output covering the root window */ +static Output *root_output; /* * Get a specific output by its internal X11 id. Used by randr_query_outputs @@ -69,7 +70,22 @@ Output *get_first_output(void) { if (output->active) return output; - return NULL; + die("No usable outputs available.\n"); +} + +/* + * Check whether there are any active outputs (excluding the root output). + * + */ +static bool any_randr_output_active(void) { + Output *output; + + TAILQ_FOREACH(output, &outputs, outputs) { + if (output != root_output && !output->to_be_disabled && output->active) + return true; + } + + return false; } /* @@ -220,27 +236,22 @@ Output *get_output_next(direction_t direction, Output *current, output_close_far } /* - * Disables RandR support by creating exactly one output with the size of the - * X11 screen. + * Creates an output covering the root window. * */ -void disable_randr(xcb_connection_t *conn) { - DLOG("RandR extension unusable, disabling.\n"); +void create_root_output(xcb_connection_t *conn) { + root_output = scalloc(1, sizeof(Output)); - Output *s = scalloc(1, sizeof(Output)); + root_output->active = true; + root_output->rect.x = 0; + root_output->rect.y = 0; + root_output->rect.width = root_screen->width_in_pixels; + root_output->rect.height = root_screen->height_in_pixels; + root_output->name = "xroot-0"; + output_init_con(root_output); + init_ws_for_output(root_output, output_get_content(root_output->con)); - s->active = true; - s->rect.x = 0; - s->rect.y = 0; - s->rect.width = root_screen->width_in_pixels; - s->rect.height = root_screen->height_in_pixels; - s->name = "xroot-0"; - output_init_con(s); - init_ws_for_output(s, output_get_content(s->con)); - - TAILQ_INSERT_TAIL(&outputs, s, outputs); - - randr_disabled = true; + TAILQ_INSERT_TAIL(&outputs, root_output, outputs); } /* @@ -564,8 +575,6 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id, if (!new->active) { DLOG("width/height 0/0, disabling output\n"); return; - } else { - new->to_be_disabled = false; } DLOG("mode: %dx%d+%d+%d\n", new->rect.width, new->rect.height, @@ -587,7 +596,13 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id, new->changed = true; } -static bool __randr_query_outputs(void) { +/* + * (Re-)queries the outputs via RandR and stores them in the list of outputs. + * + * If no outputs are found use the root window. + * + */ +void randr_query_outputs(void) { Output *output, *other, *first; xcb_randr_get_output_primary_cookie_t pcookie; xcb_randr_get_screen_resources_current_cookie_t rcookie; @@ -600,9 +615,6 @@ static bool __randr_query_outputs(void) { /* an output is VGA-1, LVDS-1, etc. (usually physical video outputs) */ xcb_randr_output_t *randr_outputs; - if (randr_disabled) - return true; - /* Get screen resources (primary output, crtcs, outputs, modes) */ rcookie = xcb_randr_get_screen_resources_current(conn, root); pcookie = xcb_randr_get_output_primary(conn, root); @@ -611,10 +623,9 @@ static bool __randr_query_outputs(void) { ELOG("Could not get RandR primary output\n"); else DLOG("primary output is %08x\n", primary->output); - if ((res = xcb_randr_get_screen_resources_current_reply(conn, rcookie, NULL)) == NULL) { - disable_randr(conn); - return true; - } + if ((res = xcb_randr_get_screen_resources_current_reply(conn, rcookie, NULL)) == NULL) + return; + cts = res->config_timestamp; int len = xcb_randr_get_screen_resources_current_outputs_length(res); @@ -636,6 +647,16 @@ static bool __randr_query_outputs(void) { free(output); } + /* If there's no randr output, enable the output covering the root window. */ + if (any_randr_output_active()) { + DLOG("Active RandR output found. Disabling root output.\n"); + if (root_output->active) + root_output->to_be_disabled = true; + } else { + DLOG("No active RandR output found. Enabling root output.\n"); + root_output->active = true; + } + /* Check for clones, disable the clones and reduce the mode to the * lowest common mode */ TAILQ_FOREACH(output, &outputs, outputs) { @@ -695,11 +716,6 @@ static bool __randr_query_outputs(void) { DLOG("Output %s disabled, re-assigning workspaces/docks\n", output->name); first = get_first_output(); - if (!first) { - FREE(res); - FREE(primary); - return false; - } /* TODO: refactor the following code into a nice function. maybe * use an on_destroy callback which is implement differently for @@ -782,11 +798,6 @@ static bool __randr_query_outputs(void) { } } - if (TAILQ_EMPTY(&outputs)) { - ELOG("No outputs found via RandR, disabling\n"); - disable_randr(conn); - } - /* Just go through each active output and assign one workspace */ TAILQ_FOREACH(output, &outputs, outputs) { if (!output->active) @@ -812,32 +823,6 @@ static bool __randr_query_outputs(void) { FREE(res); FREE(primary); - - return true; -} - -/* - * (Re-)queries the outputs via RandR and stores them in the list of outputs. - * - */ -void randr_query_outputs(void) { - static bool first_query = true; - - if (first_query) { - /* find monitors at least once via RandR */ - if (!__randr_query_outputs()) - die("No usable outputs available.\n"); - first_query = false; - } else { - /* requery */ - if (!__randr_query_outputs()) { - DLOG("sleep %f ms due to zero displays\n", config.zero_disp_exit_timer_ms); - usleep(config.zero_disp_exit_timer_ms * 1000); - - if (!__randr_query_outputs()) - die("No usable outputs available.\n"); - } - } } /* @@ -848,12 +833,13 @@ void randr_query_outputs(void) { void randr_init(int *event_base) { const xcb_query_extension_reply_t *extreply; + create_root_output(conn); + extreply = xcb_get_extension_data(conn, &xcb_randr_id); - if (!extreply->present) { - disable_randr(conn); + if (!extreply->present) return; - } else - randr_query_outputs(); + + randr_query_outputs(); if (event_base != NULL) *event_base = extreply->first_event; diff --git a/src/xinerama.c b/src/xinerama.c index cae71fc2..049e1bc4 100644 --- a/src/xinerama.c +++ b/src/xinerama.c @@ -94,15 +94,15 @@ static void query_screens(xcb_connection_t *conn) { */ void xinerama_init(void) { if (!xcb_get_extension_data(conn, &xcb_xinerama_id)->present) { - DLOG("Xinerama extension not found, disabling.\n"); - disable_randr(conn); + DLOG("Xinerama extension not found, using root output.\n"); + create_root_output(conn); } else { xcb_xinerama_is_active_reply_t *reply; reply = xcb_xinerama_is_active_reply(conn, xcb_xinerama_is_active(conn), NULL); if (reply == NULL || !reply->state) { - DLOG("Xinerama is not active (in your X-Server), disabling.\n"); - disable_randr(conn); + DLOG("Xinerama is not active (in your X-Server), using root output.\n"); + create_root_output(conn); } else query_screens(conn); diff --git a/testcases/t/201-config-parser.t b/testcases/t/201-config-parser.t index fbcc586a..a2b0a3a9 100644 --- a/testcases/t/201-config-parser.t +++ b/testcases/t/201-config-parser.t @@ -369,40 +369,6 @@ is(parser_calls($config), $expected, 'force_display_urgency_hint ok'); -################################################################################ -# delay_exit_on_zero_displays -################################################################################ - -is(parser_calls('delay_exit_on_zero_displays 300'), - "cfg_delay_exit_on_zero_displays(300)\n", - 'delay_exit_on_zero_displays ok'); - -is(parser_calls('delay_exit_on_zero_displays 500 ms'), - "cfg_delay_exit_on_zero_displays(500)\n", - 'delay_exit_on_zero_displays ok'); - -is(parser_calls('delay_exit_on_zero_displays 700ms'), - "cfg_delay_exit_on_zero_displays(700)\n", - 'delay_exit_on_zero_displays ok'); - -$config = <<'EOT'; -delay_exit_on_zero_displays 300 -delay_exit_on_zero_displays 500 ms -delay_exit_on_zero_displays 700ms -delay_exit_on_zero_displays 700 -EOT - -$expected = <<'EOT'; -cfg_delay_exit_on_zero_displays(300) -cfg_delay_exit_on_zero_displays(500) -cfg_delay_exit_on_zero_displays(700) -cfg_delay_exit_on_zero_displays(700) -EOT - -is(parser_calls($config), - $expected, - 'delay_exit_on_zero_displays ok'); - ################################################################################ # workspace ################################################################################ @@ -475,7 +441,7 @@ client.focused #4c7899 #285577 #ffffff #2e9ef4 EOT my $expected_all_tokens = <<'EOT'; -ERROR: CONFIG: Expected one of these tokens: , '#', 'set', 'bindsym', 'bindcode', 'bind', 'bar', 'font', 'mode', 'floating_minimum_size', 'floating_maximum_size', 'floating_modifier', 'default_orientation', 'workspace_layout', 'new_window', 'new_float', 'hide_edge_borders', 'for_window', 'assign', 'no_focus', 'focus_follows_mouse', 'mouse_warping', 'force_focus_wrapping', 'force_xinerama', 'force-xinerama', 'workspace_auto_back_and_forth', 'fake_outputs', 'fake-outputs', 'force_display_urgency_hint', 'delay_exit_on_zero_displays', 'focus_on_window_activation', 'show_marks', 'workspace', 'ipc_socket', 'ipc-socket', 'restart_state', 'popup_during_fullscreen', 'exec_always', 'exec', 'client.background', 'client.focused_inactive', 'client.focused', 'client.unfocused', 'client.urgent', 'client.placeholder' +ERROR: CONFIG: Expected one of these tokens: , '#', 'set', 'bindsym', 'bindcode', 'bind', 'bar', 'font', 'mode', 'floating_minimum_size', 'floating_maximum_size', 'floating_modifier', 'default_orientation', 'workspace_layout', 'new_window', 'new_float', 'hide_edge_borders', 'for_window', 'assign', 'no_focus', 'focus_follows_mouse', 'mouse_warping', 'force_focus_wrapping', 'force_xinerama', 'force-xinerama', 'workspace_auto_back_and_forth', 'fake_outputs', 'fake-outputs', 'force_display_urgency_hint', 'focus_on_window_activation', 'show_marks', 'workspace', 'ipc_socket', 'ipc-socket', 'restart_state', 'popup_during_fullscreen', 'exec_always', 'exec', 'client.background', 'client.focused_inactive', 'client.focused', 'client.unfocused', 'client.urgent', 'client.placeholder' EOT my $expected_end = <<'EOT';