i3
xinerama.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 * This is LEGACY code (we support RandR, which can do much more than
8 * Xinerama), but necessary for the poor users of the nVidia binary
9 * driver which does not support RandR in 2011 *sigh*.
10 *
11 */
12#include "all.h"
13
14#include <xcb/xinerama.h>
15
16static int num_screens;
17
18/*
19 * Looks in outputs for the Output whose start coordinates are x, y
20 *
21 */
22static Output *get_screen_at(unsigned int x, unsigned int y) {
23 Output *output;
25 if (output->rect.x == x && output->rect.y == y)
26 return output;
27
28 return NULL;
29}
30
31/*
32 * Gets the Xinerama screens and converts them to virtual Outputs (only one screen for two
33 * Xinerama screen which are configured in clone mode) in the given screenlist
34 *
35 */
36static void query_screens(xcb_connection_t *conn) {
37 xcb_xinerama_query_screens_reply_t *reply;
38 xcb_xinerama_screen_info_t *screen_info;
39
40 reply = xcb_xinerama_query_screens_reply(conn, xcb_xinerama_query_screens_unchecked(conn), NULL);
41 if (!reply) {
42 ELOG("Couldn't get Xinerama screens\n");
43 return;
44 }
45 screen_info = xcb_xinerama_query_screens_screen_info(reply);
46 int screens = xcb_xinerama_query_screens_screen_info_length(reply);
47
48 for (int screen = 0; screen < screens; screen++) {
49 Output *s = get_screen_at(screen_info[screen].x_org, screen_info[screen].y_org);
50 if (s != NULL) {
51 DLOG("Re-used old Xinerama screen %p\n", s);
52 /* This screen already exists. We use the littlest screen so that the user
53 can always see the complete workspace */
54 s->rect.width = min(s->rect.width, screen_info[screen].width);
55 s->rect.height = min(s->rect.height, screen_info[screen].height);
56 } else {
57 s = scalloc(1, sizeof(Output));
58 struct output_name *output_name = scalloc(1, sizeof(struct output_name));
59 sasprintf(&output_name->name, "xinerama-%d", num_screens);
62 DLOG("Created new Xinerama screen %s (%p)\n", output_primary_name(s), s);
63 s->active = true;
64 s->rect.x = screen_info[screen].x_org;
65 s->rect.y = screen_info[screen].y_org;
66 s->rect.width = screen_info[screen].width;
67 s->rect.height = screen_info[screen].height;
68 /* We always treat the screen at 0x0 as the primary screen */
69 if (s->rect.x == 0 && s->rect.y == 0)
71 else
76 }
77
78 DLOG("found Xinerama screen: %d x %d at %d x %d\n",
79 screen_info[screen].width, screen_info[screen].height,
80 screen_info[screen].x_org, screen_info[screen].y_org);
81 }
82
83 free(reply);
84
85 if (num_screens == 0) {
86 ELOG("No screens found. Please fix your setup. i3 will exit now.\n");
87 exit(EXIT_SUCCESS);
88 }
89}
90
91/*
92 * This creates the root_output (borrowed from randr.c) and uses it
93 * as the sole output for this session.
94 *
95 */
96static void use_root_output(xcb_connection_t *conn) {
98 s->active = true;
102}
103
104/*
105 * We have just established a connection to the X server and need the initial Xinerama
106 * information to setup workspaces for each screen.
107 *
108 */
109void xinerama_init(void) {
110 if (!xcb_get_extension_data(conn, &xcb_xinerama_id)->present) {
111 DLOG("Xinerama extension not found, using root output.\n");
113 } else {
114 xcb_xinerama_is_active_reply_t *reply;
115 reply = xcb_xinerama_is_active_reply(conn, xcb_xinerama_is_active(conn), NULL);
116
117 if (reply == NULL || !reply->state) {
118 DLOG("Xinerama is not active (in your X-Server), using root output.\n");
120 } else
122
123 FREE(reply);
124 }
125}
char * output_primary_name(Output *output)
Retrieves the primary name of an output.
Definition: output.c:51
int min(int a, int b)
Definition: util.c:27
static Output * get_screen_at(unsigned int x, unsigned int y)
Definition: xinerama.c:22
static void use_root_output(xcb_connection_t *conn)
Definition: xinerama.c:96
static int num_screens
Definition: xinerama.c:16
static void query_screens(xcb_connection_t *conn)
Definition: xinerama.c:36
void xinerama_init(void)
We have just established a connection to the X server and need the initial Xinerama information to se...
Definition: xinerama.c:109
#define y(x,...)
Definition: commands.c:21
void init_ws_for_output(Output *output)
Initializes at least one workspace for this output, trying the following steps until there is at leas...
Definition: randr.c:434
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:326
struct outputs_head outputs
Definition: randr.c:21
Output * create_root_output(xcb_connection_t *conn)
Creates an output covering the root window.
Definition: randr.c:304
xcb_connection_t * conn
XCB connection and root screen.
Definition: main.c:44
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:347
#define SLIST_INIT(head)
Definition: queue.h:127
#define SLIST_INSERT_HEAD(head, elm, field)
Definition: queue.h:138
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:376
#define TAILQ_INSERT_HEAD(head, elm, field)
Definition: queue.h:366
#define DLOG(fmt,...)
Definition: libi3.h:104
#define ELOG(fmt,...)
Definition: libi3.h:99
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...
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 FREE(pointer)
Definition: util.h:47
uint32_t height
Definition: data.h:179
uint32_t x
Definition: data.h:176
uint32_t y
Definition: data.h:177
uint32_t width
Definition: data.h:178
char * name
Definition: data.h:380
An Output is a physical output on your graphics driver.
Definition: data.h:393
names_head
List of names for the output.
Definition: data.h:411
bool active
Whether the output is currently active (has a CRTC attached with a valid mode)
Definition: data.h:399
Rect rect
x, y, width, height
Definition: data.h:417