10 monitor_t *make_monitor(xcb_rectangle_t rect)
12 monitor_t *m = malloc(sizeof(monitor_t));
13 snprintf(m->name, sizeof(m->name), "%s%02d", DEFAULT_MON_NAME, ++monitor_uid);
14 m->prev = m->next = NULL;
15 m->desk = m->last_desk = NULL;
17 m->top_padding = m->right_padding = m->bottom_padding = m->left_padding = 0;
22 monitor_t *find_monitor(char *name)
24 for (monitor_t *m = mon_head; m != NULL; m = m->next)
25 if (streq(m->name, name))
30 monitor_t *get_monitor_by_id(xcb_randr_output_t id)
32 for (monitor_t *m = mon_head; m != NULL; m = m->next)
38 monitor_t *add_monitor(xcb_rectangle_t rect)
40 monitor_t *m = make_monitor(rect);
54 void remove_monitor(monitor_t *m)
56 while (m->desk_head != NULL)
57 remove_desktop(m, m->desk_head);
58 monitor_t *prev = m->prev;
59 monitor_t *next = m->next;
73 monitor_t *mm = (last_mon == NULL ? (prev == NULL ? next : prev) : last_mon);
75 focus_node(mm, mm->desk, mm->desk->focus);
86 void merge_monitors(monitor_t *ms, monitor_t *md)
88 PRINTF("merge %s into %s\n", ms->name, md->name);
90 desktop_t *d = ms->desk_head;
92 desktop_t *next = d->next;
93 transfer_desktop(ms, md, d);
98 void swap_monitors(monitor_t *m1, monitor_t *m2)
100 if (m1 == NULL || m2 == NULL || m1 == m2)
105 else if (mon_head == m2)
109 else if (mon_tail == m2)
112 monitor_t *p1 = m1->prev;
113 monitor_t *n1 = m1->next;
114 monitor_t *p2 = m2->prev;
115 monitor_t *n2 = m2->next;
117 if (p1 != NULL && p1 != m2)
119 if (n1 != NULL && n1 != m2)
121 if (p2 != NULL && p2 != m1)
123 if (n2 != NULL && n2 != m1)
126 m1->prev = p2 == m1 ? m2 : p2;
127 m1->next = n2 == m1 ? m2 : n2;
128 m2->prev = p1 == m2 ? m1 : p1;
129 m2->next = n1 == m2 ? m1 : n1;
131 ewmh_update_wm_desktops();
132 ewmh_update_desktop_names();
133 ewmh_update_current_desktop();
137 bool import_monitors(void)
139 PUTS("import monitors");
140 xcb_randr_get_screen_resources_current_reply_t *sres = xcb_randr_get_screen_resources_current_reply(dpy, xcb_randr_get_screen_resources_current(dpy, root), NULL);
144 int len = xcb_randr_get_screen_resources_current_outputs_length(sres);
145 xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_current_outputs(sres);
147 xcb_randr_get_output_info_cookie_t cookies[len];
148 for (int i = 0; i < len; i++)
149 cookies[i] = xcb_randr_get_output_info(dpy, outputs[i], XCB_CURRENT_TIME);
151 for (monitor_t *m = mon_head; m != NULL; m = m->next)
154 monitor_t *mm = NULL;
155 unsigned int num = 0;
157 for (int i = 0; i < len; i++) {
158 xcb_randr_get_output_info_reply_t *info = xcb_randr_get_output_info_reply(dpy, cookies[i], NULL);
159 if (info != NULL && info->crtc != XCB_NONE) {
161 xcb_randr_get_crtc_info_reply_t *cir = xcb_randr_get_crtc_info_reply(dpy, xcb_randr_get_crtc_info(dpy, info->crtc, XCB_CURRENT_TIME), NULL);
163 xcb_rectangle_t rect = (xcb_rectangle_t) {cir->x, cir->y, cir->width, cir->height};
164 mm = get_monitor_by_id(outputs[i]);
166 mm->rectangle = rect;
167 for (desktop_t *d = mm->desk_head; d != NULL; d = d->next)
168 for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root))
169 fit_monitor(mm, n->client);
170 arrange(mm, mm->desk);
172 PRINTF("update monitor %s (0x%X)\n", mm->name, mm->id);
174 mm = add_monitor(rect);
175 char *name = (char *)xcb_randr_get_output_info_name(info);
176 size_t name_len = MIN(sizeof(mm->name), (size_t)xcb_randr_get_output_info_name_length(info));
177 strncpy(mm->name, name, name_len);
178 mm->name[name_len] = '\0';
180 PRINTF("add monitor %s (0x%X)\n", mm->name, mm->id);
189 /* initially focus the primary monitor and add the first desktop to it */
190 xcb_randr_get_output_primary_reply_t *gpo = xcb_randr_get_output_primary_reply(dpy, xcb_randr_get_output_primary(dpy, root), NULL);
192 pri_mon = get_monitor_by_id(gpo->output);
193 if (!running && pri_mon != NULL) {
196 add_desktop(pri_mon, make_desktop(NULL));
197 ewmh_update_current_desktop();
202 /* add one desktop to each new monitor */
203 for (monitor_t *m = mon_head; m != NULL; m = m->next)
204 if (m->desk == NULL && (running || pri_mon == NULL || m != pri_mon))
205 add_desktop(m, make_desktop(NULL));
207 /* merge and remove disconnected monitors */
208 monitor_t *m = mon_head;
210 monitor_t *next = m->next;
212 PRINTF("remove monitor %s (0x%X)\n", m->name, m->id);
213 merge_monitors(m, mm);
220 update_motion_recorder();
221 return (num_monitors > 0);