i3
fake_outputs.c
Go to the documentation of this file.
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 }
int sasprintf(char **strp, const char *fmt,...)
Safe-wrapper around asprintf which exits if it returns -1 (meaning that there is no more memory avail...
#define TAILQ_INSERT_HEAD(head, elm, field)
Definition: queue.h:366
struct outputs_head outputs
Definition: randr.c:21
#define SLIST_INIT(head)
Definition: queue.h:127
#define ELOG(fmt,...)
Definition: libi3.h:99
void fake_outputs_init(const char *output_spec)
Creates outputs according to the given specification.
Definition: fake_outputs.c:36
uint32_t width
Definition: data.h:129
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:376
void init_ws_for_output(Output *output, Con *content)
Initializes at least one workspace for this output, trying the following steps until there is at leas...
Definition: randr.c:399
static int num_screens
Definition: fake_outputs.c:13
int min(int a, int b)
Definition: util.c:27
void output_init_con(Output *output)
Initializes a CT_OUTPUT Con (searches existing ones from inplace restart before) to use for the given...
Definition: randr.c:291
uint32_t x
Definition: data.h:149
uint32_t x
Definition: data.h:127
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:347
Con * output_get_content(Con *output)
Returns the output container below the given output container.
Definition: output.c:16
void * scalloc(size_t num, size_t size)
Safe-wrapper around calloc which exits if malloc returns NULL (meaning that there is no more memory a...
char * name
Definition: data.h:353
uint32_t y
Definition: data.h:150
#define SLIST_INSERT_HEAD(head, elm, field)
Definition: queue.h:138
An Output is a physical output on your graphics driver.
Definition: data.h:366
uint32_t height
Definition: data.h:152
uint32_t width
Definition: data.h:151
bool primary
Definition: data.h:378
uint32_t y
Definition: data.h:128
uint32_t height
Definition: data.h:130
#define DLOG(fmt,...)
Definition: libi3.h:104
Con * con
Pointer to the Con which represents this output.
Definition: data.h:387
static Output * get_screen_at(unsigned int x, unsigned int y)
Definition: fake_outputs.c:19
names_head
List of names for the output.
Definition: data.h:384
Rect rect
x, y, width, height
Definition: data.h:390
char * output_primary_name(Output *output)
Retrieves the primary name of an output.
Definition: output.c:51
bool active
Whether the output is currently active (has a CRTC attached with a valid mode)
Definition: data.h:372
xcb_randr_get_output_primary_reply_t * primary
Definition: randr.c:18