]> git.sur5r.net Git - i3/i3/blob - src/fake_outputs.c
Merge branch 'release-4.16.1'
[i3/i3] / src / fake_outputs.c
1 /*
2  * vim:ts=4:sw=4:expandtab
3  *
4  * i3 - an improved dynamic tiling window manager
5  * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
6  *
7  * Faking outputs is useful in pathological situations (like network X servers
8  * which don’t support multi-monitor in a useful way) and for our testsuite.
9  *
10  */
11 #include "all.h"
12
13 static int num_screens;
14
15 /*
16  * Looks in outputs for the Output whose start coordinates are x, y
17  *
18  */
19 static Output *get_screen_at(unsigned int x, unsigned int y) {
20     Output *output;
21     TAILQ_FOREACH(output, &outputs, outputs)
22     if (output->rect.x == x && output->rect.y == y)
23         return output;
24
25     return NULL;
26 }
27
28 /*
29  * Creates outputs according to the given specification.
30  * The specification must be in the format wxh+x+y, for example 1024x768+0+0,
31  * optionally followed by 'P' to indicate a primary output,
32  * with multiple outputs separated by commas:
33  *   1900x1200+0+0P,1280x1024+1900+0
34  *
35  */
36 void fake_outputs_init(const char *output_spec) {
37     const char *walk = output_spec;
38     unsigned int x, y, width, height;
39     int chars_consumed;
40     while (sscanf(walk, "%ux%u+%u+%u%n", &width, &height, &x, &y, &chars_consumed) == 4) {
41         walk += chars_consumed;
42         bool primary = false;
43         if (*walk == 'P') {
44             primary = true;
45             walk++;
46         }
47         if (*walk == ',')
48             walk++; /* Skip delimiter */
49         DLOG("Parsed output as width = %u, height = %u at (%u, %u)%s\n",
50              width, height, x, y, primary ? " (primary)" : "");
51
52         Output *new_output = get_screen_at(x, y);
53         if (new_output != NULL) {
54             DLOG("Re-used old output %p\n", new_output);
55             /* This screen already exists. We use the littlest screen so that the user
56                can always see the complete workspace */
57             new_output->rect.width = min(new_output->rect.width, width);
58             new_output->rect.height = min(new_output->rect.height, height);
59         } else {
60             struct output_name *output_name = scalloc(1, sizeof(struct output_name));
61             new_output = scalloc(1, sizeof(Output));
62             sasprintf(&(output_name->name), "fake-%d", num_screens);
63             SLIST_INIT(&(new_output->names_head));
64             SLIST_INSERT_HEAD(&(new_output->names_head), output_name, names);
65             DLOG("Created new fake output %s (%p)\n", output_primary_name(new_output), new_output);
66             new_output->active = true;
67             new_output->rect.x = x;
68             new_output->rect.y = y;
69             new_output->rect.width = width;
70             new_output->rect.height = height;
71             /* We always treat the screen at 0x0 as the primary screen */
72             if (new_output->rect.x == 0 && new_output->rect.y == 0)
73                 TAILQ_INSERT_HEAD(&outputs, new_output, outputs);
74             else
75                 TAILQ_INSERT_TAIL(&outputs, new_output, outputs);
76             output_init_con(new_output);
77             init_ws_for_output(new_output, output_get_content(new_output->con));
78             num_screens++;
79         }
80         new_output->primary = primary;
81     }
82
83     if (num_screens == 0) {
84         ELOG("No screens found. Please fix your setup. i3 will exit now.\n");
85         exit(0);
86     }
87 }