X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Frandr.c;h=96cc880abcf5c359b09a3816b50c61e12c535c74;hb=5f52c78aa04326c25c1f178c3612c4b5613b5f85;hp=4a33458cfbb254b320923670bfca25c38f55af01;hpb=1585d942eac06ddf141c479c90262d0bae4f8cc4;p=i3%2Fi3 diff --git a/src/randr.c b/src/randr.c index 4a33458c..96cc880a 100644 --- a/src/randr.c +++ b/src/randr.c @@ -21,7 +21,6 @@ /* While a clean namespace is usually a pretty good thing, we really need * to use shorter names than the whole xcb_randr_* default names. */ typedef xcb_randr_get_crtc_info_reply_t crtc_info; -typedef xcb_randr_mode_info_t mode_info; typedef xcb_randr_get_screen_resources_current_reply_t resources_reply; /* Pointer to the result of the query for primary output */ @@ -143,14 +142,58 @@ Output *get_output_most(direction_t direction, Output *current) { return candidate; } +/* + * Gets the output which is the next one in the given direction. + * + */ +Output *get_output_next(direction_t direction, Output *current) { + Output *output, *candidate = NULL; + + TAILQ_FOREACH(output, &outputs, outputs) { + if (!output->active) + continue; + + if (((direction == D_UP) || (direction == D_DOWN)) && + (current->rect.x != output->rect.x)) + continue; + + if (((direction == D_LEFT) || (direction == D_RIGHT)) && + (current->rect.y != output->rect.y)) + continue; + + switch (direction) { + case D_UP: + if (output->rect.y < current->rect.y && + (!candidate || output->rect.y < candidate->rect.y)) + candidate = output; + break; + case D_DOWN: + if (output->rect.y > current->rect.y && + (!candidate || output->rect.y > candidate->rect.y)) + candidate = output; + break; + case D_LEFT: + if (output->rect.x < current->rect.x && + (!candidate || output->rect.x > candidate->rect.x)) + candidate = output; + break; + case D_RIGHT: + if (output->rect.x > current->rect.x && + (!candidate || output->rect.x < candidate->rect.x)) + candidate = output; + break; + } + } + + return candidate; +} + /* * Disables RandR support by creating exactly one output with the size of the * X11 screen. * */ void disable_randr(xcb_connection_t *conn) { - xcb_screen_t *root_screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data; - DLOG("RandR extension unusable, disabling.\n"); Output *s = scalloc(sizeof(Output)); @@ -198,6 +241,7 @@ void output_init_con(Output *output) { con->name = sstrdup(output->name); con->type = CT_OUTPUT; con->layout = L_OUTPUT; + con_fix_percent(croot); } con->rect = output->rect; output->con = con; @@ -224,6 +268,7 @@ void output_init_con(Output *output) { match->insert_where = M_BELOW; TAILQ_INSERT_TAIL(&(topdock->swallow_head), match, matches); + FREE(topdock->name); topdock->name = sstrdup("topdock"); asprintf(&name, "[i3 con] top dockarea %s", con->name); @@ -237,6 +282,7 @@ void output_init_con(Output *output) { DLOG("adding main content container\n"); Con *content = con_new(NULL, NULL); content->type = CT_CON; + FREE(content->name); content->name = sstrdup("content"); asprintf(&name, "[i3 con] content %s", con->name); @@ -256,6 +302,7 @@ void output_init_con(Output *output) { match->insert_where = M_BELOW; TAILQ_INSERT_TAIL(&(bottomdock->swallow_head), match, matches); + FREE(bottomdock->name); bottomdock->name = sstrdup("bottomdock"); asprintf(&name, "[i3 con] bottom dockarea %s", con->name); @@ -315,7 +362,7 @@ void init_ws_for_output(Output *output, Con *content) { if (visible && (previous = TAILQ_NEXT(workspace, focused))) { LOG("Switching to previously used workspace \"%s\" on output \"%s\"\n", previous->name, workspace_out->name); - workspace_show(previous->name); + workspace_show(previous); } con_detach(workspace); @@ -342,7 +389,7 @@ void init_ws_for_output(Output *output, Con *content) { if (!visible) { visible = TAILQ_FIRST(&(content->nodes_head)); focused = content; - workspace_show(visible->name); + workspace_show(visible); } return; } @@ -355,7 +402,7 @@ void init_ws_for_output(Output *output, Con *content) { LOG("Initializing first assigned workspace \"%s\" for output \"%s\"\n", assignment->name, assignment->output); focused = content; - workspace_show(assignment->name); + workspace_show_by_name(assignment->name); return; } @@ -363,40 +410,75 @@ void init_ws_for_output(Output *output, Con *content) { DLOG("Now adding a workspace\n"); /* add a workspace to this output */ + Con *out, *current; + bool exists = true; Con *ws = con_new(NULL, NULL); ws->type = CT_WORKSPACE; - /* get the next unused workspace number */ - DLOG("Getting next unused workspace\n"); - int c = 0; - bool exists = true; - while (exists) { - Con *out, *current, *child; + /* try the configured workspace bindings first to find a free name */ + Binding *bind; + TAILQ_FOREACH(bind, bindings, bindings) { + DLOG("binding with command %s\n", bind->command); + if (strlen(bind->command) < strlen("workspace ") || + strncasecmp(bind->command, "workspace", strlen("workspace")) != 0) + continue; + DLOG("relevant command = %s\n", bind->command); + char *target = bind->command + strlen("workspace "); + /* We check if this is the workspace next/prev command. Beware: The + * workspace names "next" and "prev" are OK, so we check before + * stripping the double quotes */ + if (strncasecmp(target, "next", strlen("next")) == 0 || + strncasecmp(target, "prev", strlen("prev")) == 0) + continue; + if (*target == '"') + target++; + FREE(ws->name); + ws->name = strdup(target); + if (ws->name[strlen(ws->name)-1] == '"') + ws->name[strlen(ws->name)-1] = '\0'; + DLOG("trying name *%s*\n", ws->name); - c++; + current = NULL; + TAILQ_FOREACH(out, &(croot->nodes_head), nodes) + GREP_FIRST(current, output_get_content(out), !strcasecmp(child->name, ws->name)); + + exists = (current != NULL); + if (!exists) { + /* Set ->num to the number of the workspace, if the name actually + * is a number or starts with a number */ + char *endptr = NULL; + long parsed_num = strtol(ws->name, &endptr, 10); + if (parsed_num == LONG_MIN || + parsed_num == LONG_MAX || + parsed_num < 0 || + endptr == ws->name) + ws->num = -1; + else ws->num = parsed_num; + LOG("Used number %d for workspace with name %s\n", ws->num, ws->name); - FREE(ws->name); - asprintf(&(ws->name), "%d", c); + break; + } + } - exists = false; - TAILQ_FOREACH(out, &(croot->nodes_head), nodes) { - TAILQ_FOREACH(current, &(out->nodes_head), nodes) { - if (current->type != CT_CON) - continue; + if (exists) { + /* get the next unused workspace number */ + DLOG("Getting next unused workspace by number\n"); + int c = 0; + while (exists) { + c++; - TAILQ_FOREACH(child, &(current->nodes_head), nodes) { - if (strcasecmp(child->name, ws->name) != 0) - continue; + FREE(ws->name); + asprintf(&(ws->name), "%d", c); - exists = true; - break; - } - } - } + current = NULL; + TAILQ_FOREACH(out, &(croot->nodes_head), nodes) + GREP_FIRST(current, output_get_content(out), !strcasecmp(child->name, ws->name)); + exists = (current != NULL); - DLOG("result for ws %s / %d: exists = %d\n", ws->name, c, exists); + DLOG("result for ws %s / %d: exists = %d\n", ws->name, c, exists); + } + ws->num = c; } - ws->num = c; con_attach(ws, content, false); asprintf(&name, "[i3 con] workspace %s", ws->name); @@ -708,7 +790,7 @@ void randr_query_outputs() { } DLOG("destroying disappearing con %p\n", output->con); - tree_close(output->con, DONT_KILL_WINDOW, true); + tree_close(output->con, DONT_KILL_WINDOW, true, false); DLOG("Done. Should be fine now\n"); output->con = NULL; }