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