randr: use root window in case of no randr outputs
This patch introduces a root output covering the root window. It is used in two cases: 1. RandR is not available. In this case, the previous behaviour of creating a single output covering the root window is preserved. 2. RandR is available, but there is no active output. In this case, the root output is enabled and will be the only active output. If any RandR output becomes available, the root output will be disabled again. Existing mechanisms for migrating workspaces will just work without modification. I've carefully slipped in a global variable `Output root_output` representing that output. Fixes #926 and #1489
This commit is contained in:
parent
c87b256200
commit
78decb565a
|
@ -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);
|
||||
|
|
79
src/randr.c
79
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
|
||||
|
@ -72,6 +73,21 @@ Output *get_first_output(void) {
|
|||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the active (!) output which contains the coordinates x, y or NULL
|
||||
* if there is no output which contains these coordinates.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -588,6 +599,8 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id,
|
|||
/*
|
||||
* (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;
|
||||
|
@ -602,9 +615,6 @@ void 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;
|
||||
|
||||
/* 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);
|
||||
|
@ -613,10 +623,9 @@ void 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);
|
||||
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);
|
||||
|
@ -638,6 +647,16 @@ void 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) {
|
||||
|
@ -779,11 +798,6 @@ void 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)
|
||||
|
@ -819,11 +833,12 @@ 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();
|
||||
|
||||
if (event_base != NULL)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue