Codebase list i3-gaps / 36cd905 src / fake_outputs.c
36cd905

Tree @36cd905 (Download .tar.gz)

fake_outputs.c @36cd905raw · history · blame

/*
 * vim:ts=4:sw=4:expandtab
 *
 * i3 - an improved dynamic tiling window manager
 * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
 *
 * Faking outputs is useful in pathological situations (like network X servers
 * which don’t support multi-monitor in a useful way) and for our testsuite.
 *
 */
#include "all.h"

static int num_screens;

/*
 * Looks in outputs for the Output whose start coordinates are x, y
 *
 */
static Output *get_screen_at(unsigned int x, unsigned int y) {
    Output *output;
    TAILQ_FOREACH (output, &outputs, outputs) {
        if (output->rect.x == x && output->rect.y == y) {
            return output;
        }
    }

    return NULL;
}

/*
 * Creates outputs according to the given specification.
 * The specification must be in the format wxh+x+y, for example 1024x768+0+0,
 * optionally followed by 'P' to indicate a primary output,
 * with multiple outputs separated by commas:
 *   1900x1200+0+0P,1280x1024+1900+0
 *
 */
void fake_outputs_init(const char *output_spec) {
    const char *walk = output_spec;
    unsigned int x, y, width, height;
    int chars_consumed;
    while (sscanf(walk, "%ux%u+%u+%u%n", &width, &height, &x, &y, &chars_consumed) == 4) {
        walk += chars_consumed;
        bool primary = false;
        if (*walk == 'P') {
            primary = true;
            walk++;
        }
        if (*walk == ',')
            walk++; /* Skip delimiter */
        DLOG("Parsed output as width = %u, height = %u at (%u, %u)%s\n",
             width, height, x, y, primary ? " (primary)" : "");

        Output *new_output = get_screen_at(x, y);
        if (new_output != NULL) {
            DLOG("Re-used old output %p\n", new_output);
            /* This screen already exists. We use the littlest screen so that the user
               can always see the complete workspace */
            new_output->rect.width = min(new_output->rect.width, width);
            new_output->rect.height = min(new_output->rect.height, height);
        } else {
            struct output_name *output_name = scalloc(1, sizeof(struct output_name));
            new_output = scalloc(1, sizeof(Output));
            sasprintf(&(output_name->name), "fake-%d", num_screens);
            SLIST_INIT(&(new_output->names_head));
            SLIST_INSERT_HEAD(&(new_output->names_head), output_name, names);
            DLOG("Created new fake output %s (%p)\n", output_primary_name(new_output), new_output);
            new_output->active = true;
            new_output->rect.x = x;
            new_output->rect.y = y;
            new_output->rect.width = width;
            new_output->rect.height = height;
            /* We always treat the screen at 0x0 as the primary screen */
            if (new_output->rect.x == 0 && new_output->rect.y == 0)
                TAILQ_INSERT_HEAD(&outputs, new_output, outputs);
            else
                TAILQ_INSERT_TAIL(&outputs, new_output, outputs);
            output_init_con(new_output);
            init_ws_for_output(new_output);
            num_screens++;
        }
        new_output->primary = primary;
    }

    if (num_screens == 0) {
        ELOG("No screens found. Please fix your setup. i3 will exit now.\n");
        exit(EXIT_FAILURE);
    }
}