i3
|
00001 /* 00002 * vim:ts=4:sw=4:expandtab 00003 * 00004 * i3 - an improved dynamic tiling window manager 00005 * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE) 00006 * 00007 * This is LEGACY code (we support RandR, which can do much more than 00008 * Xinerama), but necessary for the poor users of the nVidia binary 00009 * driver which does not support RandR in 2011 *sigh*. 00010 * 00011 */ 00012 #include "all.h" 00013 00014 #include <xcb/xinerama.h> 00015 00016 00017 static int num_screens; 00018 00019 /* 00020 * Looks in outputs for the Output whose start coordinates are x, y 00021 * 00022 */ 00023 static Output *get_screen_at(int x, int y) { 00024 Output *output; 00025 TAILQ_FOREACH(output, &outputs, outputs) 00026 if (output->rect.x == x && output->rect.y == y) 00027 return output; 00028 00029 return NULL; 00030 } 00031 00032 /* 00033 * Gets the Xinerama screens and converts them to virtual Outputs (only one screen for two 00034 * Xinerama screen which are configured in clone mode) in the given screenlist 00035 * 00036 */ 00037 static void query_screens(xcb_connection_t *conn) { 00038 xcb_xinerama_query_screens_reply_t *reply; 00039 xcb_xinerama_screen_info_t *screen_info; 00040 00041 reply = xcb_xinerama_query_screens_reply(conn, xcb_xinerama_query_screens_unchecked(conn), NULL); 00042 if (!reply) { 00043 ELOG("Couldn't get Xinerama screens\n"); 00044 return; 00045 } 00046 screen_info = xcb_xinerama_query_screens_screen_info(reply); 00047 int screens = xcb_xinerama_query_screens_screen_info_length(reply); 00048 00049 for (int screen = 0; screen < screens; screen++) { 00050 Output *s = get_screen_at(screen_info[screen].x_org, screen_info[screen].y_org); 00051 if (s != NULL) { 00052 DLOG("Re-used old Xinerama screen %p\n", s); 00053 /* This screen already exists. We use the littlest screen so that the user 00054 can always see the complete workspace */ 00055 s->rect.width = min(s->rect.width, screen_info[screen].width); 00056 s->rect.height = min(s->rect.height, screen_info[screen].height); 00057 } else { 00058 s = scalloc(sizeof(Output)); 00059 sasprintf(&(s->name), "xinerama-%d", num_screens); 00060 DLOG("Created new Xinerama screen %s (%p)\n", s->name, s); 00061 s->active = true; 00062 s->rect.x = screen_info[screen].x_org; 00063 s->rect.y = screen_info[screen].y_org; 00064 s->rect.width = screen_info[screen].width; 00065 s->rect.height = screen_info[screen].height; 00066 /* We always treat the screen at 0x0 as the primary screen */ 00067 if (s->rect.x == 0 && s->rect.y == 0) 00068 TAILQ_INSERT_HEAD(&outputs, s, outputs); 00069 else TAILQ_INSERT_TAIL(&outputs, s, outputs); 00070 output_init_con(s); 00071 init_ws_for_output(s, output_get_content(s->con)); 00072 num_screens++; 00073 } 00074 00075 DLOG("found Xinerama screen: %d x %d at %d x %d\n", 00076 screen_info[screen].width, screen_info[screen].height, 00077 screen_info[screen].x_org, screen_info[screen].y_org); 00078 } 00079 00080 free(reply); 00081 00082 if (num_screens == 0) { 00083 ELOG("No screens found. Please fix your setup. i3 will exit now.\n"); 00084 exit(0); 00085 } 00086 } 00087 00088 /* 00089 * We have just established a connection to the X server and need the initial Xinerama 00090 * information to setup workspaces for each screen. 00091 * 00092 */ 00093 void xinerama_init(void) { 00094 if (!xcb_get_extension_data(conn, &xcb_xinerama_id)->present) { 00095 DLOG("Xinerama extension not found, disabling.\n"); 00096 disable_randr(conn); 00097 } else { 00098 xcb_xinerama_is_active_reply_t *reply; 00099 reply = xcb_xinerama_is_active_reply(conn, xcb_xinerama_is_active(conn), NULL); 00100 00101 if (reply == NULL || !reply->state) { 00102 DLOG("Xinerama is not active (in your X-Server), disabling.\n"); 00103 disable_randr(conn); 00104 } else 00105 query_screens(conn); 00106 00107 FREE(reply); 00108 } 00109 00110 #if 0 00111 Output *output; 00112 Workspace *ws; 00113 /* Just go through each active output and associate one workspace */ 00114 TAILQ_FOREACH(output, &outputs, outputs) { 00115 ws = get_first_workspace_for_output(output); 00116 initialize_output(conn, output, ws); 00117 } 00118 #endif 00119 }