X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Frandr.c;h=a4a0f6fd6d36fe7c626d836e7bc23d8c34573cdb;hb=9613a0744ddf39adef664b424671cc3246763ab1;hp=267d6e41bf307628c058653325d94100888c7ad4;hpb=34a5bbb7e9779a7576fdd1e41dd677248c23749d;p=i3%2Fi3 diff --git a/src/randr.c b/src/randr.c index 267d6e41..a4a0f6fd 100644 --- a/src/randr.c +++ b/src/randr.c @@ -38,8 +38,8 @@ static bool randr_disabled = false; static Output *get_output_by_id(xcb_randr_output_t id) { Output *output; TAILQ_FOREACH(output, &outputs, outputs) - if (output->id == id) - return output; + if (output->id == id) + return output; return NULL; } @@ -51,9 +51,9 @@ static Output *get_output_by_id(xcb_randr_output_t id) { Output *get_output_by_name(const char *name) { Output *output; TAILQ_FOREACH(output, &outputs, outputs) - if (output->active && - strcasecmp(output->name, name) == 0) - return output; + if (output->active && + strcasecmp(output->name, name) == 0) + return output; return NULL; } @@ -66,8 +66,8 @@ Output *get_first_output(void) { Output *output; TAILQ_FOREACH(output, &outputs, outputs) - if (output->active) - return output; + if (output->active) + return output; die("No usable outputs available.\n"); } @@ -77,13 +77,13 @@ Output *get_first_output(void) { * if there is no output which contains these coordinates. * */ -Output *get_output_containing(int x, int y) { +Output *get_output_containing(unsigned int x, unsigned int y) { Output *output; TAILQ_FOREACH(output, &outputs, outputs) { if (!output->active) continue; DLOG("comparing x=%d y=%d with x=%d and y=%d width %d height %d\n", - x, y, output->rect.x, output->rect.y, output->rect.width, output->rect.height); + x, y, output->rect.x, output->rect.y, output->rect.width, output->rect.height); if (x >= output->rect.x && x < (output->rect.x + output->rect.width) && y >= output->rect.y && y < (output->rect.y + output->rect.height)) return output; @@ -93,15 +93,54 @@ Output *get_output_containing(int x, int y) { } /* - * Gets the output which is the last one in the given direction, for example - * the output on the most bottom when direction == D_DOWN, the output most - * right when direction == D_RIGHT and so on. + * In contained_by_output, we check if any active output contains part of the container. + * We do this by checking if the output rect is intersected by the Rect. + * This is the 2-dimensional counterpart of get_output_containing. + * Since we don't actually need the outputs intersected by the given Rect (There could + * be many), we just return true or false for convenience. + * + */ +bool contained_by_output(Rect rect) { + Output *output; + int lx = rect.x, uy = rect.y; + int rx = rect.x + rect.width, by = rect.y + rect.height; + TAILQ_FOREACH(output, &outputs, outputs) { + if (!output->active) + continue; + DLOG("comparing x=%d y=%d with x=%d and y=%d width %d height %d\n", + rect.x, rect.y, output->rect.x, output->rect.y, output->rect.width, output->rect.height); + if (rx >= (int)output->rect.x && lx <= (int)(output->rect.x + output->rect.width) && + by >= (int)output->rect.y && uy <= (int)(output->rect.y + output->rect.height)) + return true; + } + return false; +} + +/* + * Like get_output_next with close_far == CLOSEST_OUTPUT, but wraps. * - * This function always returns a output. + * For example if get_output_next(D_DOWN, x, FARTHEST_OUTPUT) = NULL, then + * get_output_next_wrap(D_DOWN, x) will return the topmost output. + * + * This function always returns a output: if no active outputs can be found, + * current itself is returned. * */ -Output *get_output_most(direction_t direction, Output *current) { - Output *best = get_output_next(direction, current, FARTHEST_OUTPUT); +Output *get_output_next_wrap(direction_t direction, Output *current) { + Output *best = get_output_next(direction, current, CLOSEST_OUTPUT); + /* If no output can be found, wrap */ + if (!best) { + direction_t opposite; + if (direction == D_RIGHT) + opposite = D_LEFT; + else if (direction == D_LEFT) + opposite = D_RIGHT; + else if (direction == D_DOWN) + opposite = D_UP; + else + opposite = D_DOWN; + best = get_output_next(opposite, current, FARTHEST_OUTPUT); + } if (!best) best = current; DLOG("current = %s, best = %s\n", current->name, best->name); @@ -111,12 +150,19 @@ Output *get_output_most(direction_t direction, Output *current) { /* * Gets the output which is the next one in the given direction. * + * If close_far == CLOSEST_OUTPUT, then the output next to the current one will + * selected. If close_far == FARTHEST_OUTPUT, the output which is the last one + * in the given direction will be selected. + * + * NULL will be returned when no active outputs are present in the direction + * specified (note that “current” counts as such an output). + * */ Output *get_output_next(direction_t direction, Output *current, output_close_far_t close_far) { Rect *cur = &(current->rect), *other; Output *output, - *best = NULL; + *best = NULL; TAILQ_FOREACH(output, &outputs, outputs) { if (!output->active) continue; @@ -124,18 +170,18 @@ Output *get_output_next(direction_t direction, Output *current, output_close_far other = &(output->rect); if ((direction == D_RIGHT && other->x > cur->x) || - (direction == D_LEFT && other->x < cur->x)) { + (direction == D_LEFT && other->x < cur->x)) { /* Skip the output when it doesn’t overlap the other one’s y * coordinate at all. */ if ((other->y + other->height) <= cur->y || - (cur->y + cur->height) <= other->y) + (cur->y + cur->height) <= other->y) continue; } else if ((direction == D_DOWN && other->y > cur->y) || - (direction == D_UP && other->y < cur->y)) { + (direction == D_UP && other->y < cur->y)) { /* Skip the output when it doesn’t overlap the other one’s x * coordinate at all. */ if ((other->x + other->width) <= cur->x || - (cur->x + cur->width) <= other->x) + (cur->x + cur->width) <= other->x) continue; } else continue; @@ -150,9 +196,9 @@ Output *get_output_next(direction_t direction, Output *current, output_close_far /* Is this output better (closer to the current output) than our * current best bet? */ if ((direction == D_RIGHT && other->x < best->rect.x) || - (direction == D_LEFT && other->x > best->rect.x) || - (direction == D_DOWN && other->y < best->rect.y) || - (direction == D_UP && other->y > best->rect.y)) { + (direction == D_LEFT && other->x > best->rect.x) || + (direction == D_DOWN && other->y < best->rect.y) || + (direction == D_UP && other->y > best->rect.y)) { best = output; continue; } @@ -160,9 +206,9 @@ Output *get_output_next(direction_t direction, Output *current, output_close_far /* Is this output better (farther to the current output) than our * current best bet? */ if ((direction == D_RIGHT && other->x > best->rect.x) || - (direction == D_LEFT && other->x < best->rect.x) || - (direction == D_DOWN && other->y > best->rect.y) || - (direction == D_UP && other->y < best->rect.y)) { + (direction == D_LEFT && other->x < best->rect.x) || + (direction == D_DOWN && other->y > best->rect.y) || + (direction == D_UP && other->y < best->rect.y)) { best = output; continue; } @@ -316,8 +362,8 @@ void init_ws_for_output(Output *output, Con *content) { /* check if this workspace actually exists */ Con *workspace = NULL, *out; TAILQ_FOREACH(out, &(croot->nodes_head), nodes) - GREP_FIRST(workspace, output_get_content(out), - !strcasecmp(child->name, assignment->name)); + GREP_FIRST(workspace, output_get_content(out), + !strcasecmp(child->name, assignment->name)); if (workspace == NULL) continue; @@ -356,9 +402,9 @@ void init_ws_for_output(Output *output, Con *content) { Con *floating_con; TAILQ_FOREACH(floating_con, &(workspace->floating_head), floating_windows) - /* NB: We use output->con here because content is not yet rendered, + /* NB: We use output->con here because content is not yet rendered, * so it has a rect of {0, 0, 0, 0}. */ - floating_fix_coordinates(floating_con, &(ws_out_content->rect), &(output->con->rect)); + floating_fix_coordinates(floating_con, &(ws_out_content->rect), &(output->con->rect)); con_detach(workspace); con_attach(workspace, content, false); @@ -481,8 +527,8 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id, new->primary = (primary && primary->output == id); FREE(new->name); sasprintf(&new->name, "%.*s", - xcb_randr_get_output_info_name_length(output), - xcb_randr_get_output_info_name(output)); + xcb_randr_get_output_info_name_length(output), + xcb_randr_get_output_info_name(output)); DLOG("found output with name %s\n", new->name); @@ -493,7 +539,8 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id, if (!existing) { if (new->primary) TAILQ_INSERT_HEAD(&outputs, new, outputs); - else TAILQ_INSERT_TAIL(&outputs, new, outputs); + else + TAILQ_INSERT_TAIL(&outputs, new, outputs); } else if (new->active) new->to_be_disabled = true; return; @@ -520,7 +567,7 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id, } DLOG("mode: %dx%d+%d+%d\n", new->rect.width, new->rect.height, - new->rect.x, new->rect.y); + new->rect.x, new->rect.y); /* If we don’t need to change an existing output or if the output * does not exist in the first place, the case is simple: we either @@ -529,7 +576,8 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id, if (!existing) { if (new->primary) TAILQ_INSERT_HEAD(&outputs, new, outputs); - else TAILQ_INSERT_TAIL(&outputs, new, outputs); + else + TAILQ_INSERT_TAIL(&outputs, new, outputs); } return; } @@ -563,7 +611,8 @@ void randr_query_outputs(void) { if ((primary = xcb_randr_get_output_primary_reply(conn, pcookie, NULL)) == NULL) ELOG("Could not get RandR primary output\n"); - else DLOG("primary output is %08x\n", primary->output); + 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; @@ -595,7 +644,7 @@ void randr_query_outputs(void) { if (!output->active || output->to_be_disabled) continue; DLOG("output %p / %s, position (%d, %d), checking for clones\n", - output, output->name, output->rect.x, output->rect.y); + output, output->name, output->rect.x, output->rect.y); for (other = output; other != TAILQ_END(&outputs); @@ -608,7 +657,7 @@ void randr_query_outputs(void) { continue; DLOG("output %p has the same position, his mode = %d x %d\n", - other, other->rect.width, other->rect.height); + other, other->rect.width, other->rect.height); uint32_t width = min(other->rect.width, output->rect.width); uint32_t height = min(other->rect.height, output->rect.height); @@ -623,8 +672,8 @@ void randr_query_outputs(void) { other->to_be_disabled = true; DLOG("new output mode %d x %d, other mode %d x %d\n", - output->rect.width, output->rect.height, - other->rect.width, other->rect.height); + output->rect.width, output->rect.height, + other->rect.width, other->rect.height); } } @@ -683,7 +732,7 @@ void randr_query_outputs(void) { DLOG("Fixing the coordinates of floating containers\n"); Con *floating_con; TAILQ_FOREACH(floating_con, &(current->floating_head), floating_windows) - floating_fix_coordinates(floating_con, &(output->con->rect), &(first->con->rect)); + floating_fix_coordinates(floating_con, &(output->con->rect), &(first->con->rect)); DLOG("Done, next\n"); } DLOG("re-attached all workspaces\n"); @@ -777,16 +826,17 @@ void randr_init(int *event_base) { if (!extreply->present) { disable_randr(conn); return; - } else randr_query_outputs(); + } else + randr_query_outputs(); if (event_base != NULL) *event_base = extreply->first_event; xcb_randr_select_input(conn, root, - XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE | - XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE | - XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE | - XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY); + XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE | + XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE | + XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE | + XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY); xcb_flush(conn); }