add initial randr support and adjust xinerama support
This commit is contained in:
		
							
								
								
									
										7
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,12 +1,7 @@ | |||||||
| CC	?= gcc | CC	?= gcc | ||||||
| STRIP ?= strip | STRIP ?= strip | ||||||
| CFLAGS = -std=c99 -fshort-wchar -Os | CFLAGS = -std=c99 -fshort-wchar -Os | ||||||
| LDFLAGS = -lxcb | LDFLAGS = -lxcb -lxcb-xinerama -lxcb-randr | ||||||
| XINERAMA ?= 0 |  | ||||||
| ifneq "$(XINERAMA)" "0" |  | ||||||
| 	LDFLAGS += -lxcb-xinerama |  | ||||||
| 	CFLAGS  += -DXINERAMA=${XINERAMA} |  | ||||||
| endif |  | ||||||
| CFDEBUG = -g3 -pedantic -Wall -Wunused-parameter -Wlong-long\ | CFDEBUG = -g3 -pedantic -Wall -Wunused-parameter -Wlong-long\ | ||||||
| 		  -Wsign-conversion -Wconversion -Wimplicit-function-declaration | 		  -Wsign-conversion -Wconversion -Wimplicit-function-declaration | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										262
									
								
								bar.c
									
									
									
									
									
								
							
							
						
						
									
										262
									
								
								bar.c
									
									
									
									
									
								
							| @@ -8,9 +8,8 @@ | |||||||
| #include <getopt.h> | #include <getopt.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
| #include <xcb/xcb.h> | #include <xcb/xcb.h> | ||||||
| #if XINERAMA |  | ||||||
| #include <xcb/xinerama.h> | #include <xcb/xinerama.h> | ||||||
| #endif | #include <xcb/randr.h> | ||||||
|  |  | ||||||
| #include "config.h" | #include "config.h" | ||||||
|  |  | ||||||
| @@ -58,13 +57,10 @@ static fontset_item_t   *sel_font = NULL; | |||||||
|  |  | ||||||
| static screen_t         *screens; | static screen_t         *screens; | ||||||
| static int              num_screens; | static int              num_screens; | ||||||
|  | static int              randr_event = -1; | ||||||
| static const unsigned   palette[] = {COLOR0,COLOR1,COLOR2,COLOR3,COLOR4,COLOR5,COLOR6,COLOR7,COLOR8,COLOR9,BACKGROUND,FOREGROUND}; | static const unsigned   palette[] = {COLOR0,COLOR1,COLOR2,COLOR3,COLOR4,COLOR5,COLOR6,COLOR7,COLOR8,COLOR9,BACKGROUND,FOREGROUND}; | ||||||
|  |  | ||||||
| #if XINERAMA |  | ||||||
| static const char *control_characters = "fbulcsr"; | static const char *control_characters = "fbulcsr"; | ||||||
| #else |  | ||||||
| static const char *control_characters = "fbulcr"; |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| static inline void | static inline void | ||||||
| xcb_set_bg (int i) | xcb_set_bg (int i) | ||||||
| @@ -137,8 +133,9 @@ draw_char (screen_t *screen, int x, int align, wchar_t ch) | |||||||
|             (xcb_char2b_t *)&ch); |             (xcb_char2b_t *)&ch); | ||||||
|  |  | ||||||
|     /* Draw the underline */ |     /* Draw the underline */ | ||||||
|     if (BAR_UNDERLINE_HEIGHT)  |     if (BAR_UNDERLINE_HEIGHT) { | ||||||
|         xcb_fill_rect (underl_gc, x + screen->x, BAR_UNDERLINE*(BAR_HEIGHT-BAR_UNDERLINE_HEIGHT), ch_width, BAR_UNDERLINE_HEIGHT); |         xcb_fill_rect (underl_gc, x + screen->x, BAR_UNDERLINE*(BAR_HEIGHT-BAR_UNDERLINE_HEIGHT), ch_width, BAR_UNDERLINE_HEIGHT); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return ch_width; |     return ch_width; | ||||||
| } | } | ||||||
| @@ -153,7 +150,6 @@ parse (char *text) | |||||||
|     screen_t *screen = &screens[0]; |     screen_t *screen = &screens[0]; | ||||||
|  |  | ||||||
|     xcb_fill_rect (clear_gc, 0, 0, bar_width, BAR_HEIGHT); |     xcb_fill_rect (clear_gc, 0, 0, bar_width, BAR_HEIGHT); | ||||||
|  |  | ||||||
|     for (;;) { |     for (;;) { | ||||||
|         if (*p == '\0') |         if (*p == '\0') | ||||||
|             return; |             return; | ||||||
| @@ -174,8 +170,9 @@ parse (char *text) | |||||||
|                         xcb_set_ud (isdigit(*p) ? (*p)-'0' : 10); |                         xcb_set_ud (isdigit(*p) ? (*p)-'0' : 10); | ||||||
|                         p++; |                         p++; | ||||||
|                         break; |                         break; | ||||||
| #if XINERAMA |  | ||||||
|                     case 's': |                     case 's': | ||||||
|  |                         if (num_screens == 1) | ||||||
|  |                             break; | ||||||
|                         if ((*p) == 'r') { |                         if ((*p) == 'r') { | ||||||
|                             screen = &screens[num_screens - 1]; |                             screen = &screens[num_screens - 1]; | ||||||
|                         } else if ((*p) == 'l') { |                         } else if ((*p) == 'l') { | ||||||
| @@ -202,7 +199,6 @@ parse (char *text) | |||||||
|                         pos_x = 0; |                         pos_x = 0; | ||||||
|                         p++; |                         p++; | ||||||
|                         break; |                         break; | ||||||
| #endif |  | ||||||
|                     case 'l':  |                     case 'l':  | ||||||
|                         align = ALIGN_L;  |                         align = ALIGN_L;  | ||||||
|                         pos_x = 0;  |                         pos_x = 0;  | ||||||
| @@ -215,6 +211,8 @@ parse (char *text) | |||||||
|                         align = ALIGN_R;  |                         align = ALIGN_R;  | ||||||
|                         pos_x = 0;  |                         pos_x = 0;  | ||||||
|                         break; |                         break; | ||||||
|  | 		    default: | ||||||
|  | 			break; | ||||||
|                 } |                 } | ||||||
|         } else { /* utf-8 -> ucs-2 */ |         } else { /* utf-8 -> ucs-2 */ | ||||||
|             wchar_t t; |             wchar_t t; | ||||||
| @@ -349,21 +347,152 @@ set_ewmh_atoms () | |||||||
|     xcb_change_property (c, XCB_PROP_MODE_REPLACE, win, atom_list[NET_WM_STRUT], XCB_ATOM_CARDINAL, 32, 4, strut); |     xcb_change_property (c, XCB_PROP_MODE_REPLACE, win, atom_list[NET_WM_STRUT], XCB_ATOM_CARDINAL, 32, 4, strut); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int | ||||||
|  | get_xinerama_outputs(xcb_window_t w, screen_t **spp) | ||||||
|  | { | ||||||
|  |     int i, num = 0; | ||||||
|  |     screen_t *ret; | ||||||
|  |     xcb_generic_error_t *err; | ||||||
|  |     xcb_xinerama_query_screens_cookie_t xinerama_query; | ||||||
|  |     xcb_xinerama_query_screens_reply_t *xinerama_reply; | ||||||
|  |     xcb_xinerama_screen_info_t *xinerama_info; | ||||||
|  |     xcb_xinerama_is_active_cookie_t xia_query; | ||||||
|  |     xcb_xinerama_is_active_reply_t *xia_reply; | ||||||
|  |  | ||||||
|  |     xia_query = xcb_xinerama_is_active(c); | ||||||
|  |     xia_reply = xcb_xinerama_is_active_reply(c, xia_query, &err); | ||||||
|  |  | ||||||
|  |     if (xia_reply && xia_reply->state) { | ||||||
|  |         free(xia_reply); | ||||||
|  |         xinerama_query = xcb_xinerama_query_screens(c); | ||||||
|  |         xinerama_reply = xcb_xinerama_query_screens_reply(c, xinerama_query, &err); | ||||||
|  |         if (err != NULL || xinerama_reply == NULL) { | ||||||
|  |             fprintf(stderr, "xinerama_query_screens failed\n"); | ||||||
|  |             return 0; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         num = xcb_xinerama_query_screens_screen_info_length(xinerama_reply); | ||||||
|  |         xinerama_info = xcb_xinerama_query_screens_screen_info(xinerama_reply); | ||||||
|  |         ret = calloc (num_screens, sizeof(screen_t)); | ||||||
|  |         if (ret == NULL) | ||||||
|  |             exit (1); | ||||||
|  |  | ||||||
|  |         for (int i = num_screens-1; i >= 0; i--) { | ||||||
|  |             ret[i].x = xinerama_info[i].x_org; | ||||||
|  |             ret[i].width = xinerama_info[i].width; | ||||||
|  |         } | ||||||
|  |         free(xinerama_reply); | ||||||
|  |  | ||||||
|  |         *spp = ret; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return num; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct rect { | ||||||
|  |     uint32_t x; | ||||||
|  |     uint32_t y; | ||||||
|  |     uint32_t width; | ||||||
|  |     uint32_t height; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | int | ||||||
|  | get_randr_outputs(xcb_window_t w, screen_t **spp) | ||||||
|  | { | ||||||
|  |     int i, j, num, cnt = 0; | ||||||
|  |     screen_t *s; | ||||||
|  |     xcb_generic_error_t *err; | ||||||
|  |     xcb_randr_get_screen_resources_current_cookie_t rres_query; | ||||||
|  |     xcb_randr_get_screen_resources_current_reply_t *rres_reply; | ||||||
|  |     xcb_randr_output_t *outputs; | ||||||
|  |  | ||||||
|  |     rres_query = xcb_randr_get_screen_resources_current(c, w); | ||||||
|  |     rres_reply = xcb_randr_get_screen_resources_current_reply(c, rres_query, &err); | ||||||
|  |     if (rres_reply == NULL || err != NULL) { | ||||||
|  |         fprintf(stderr, "Failed to get current randr screen resources\n"); | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     num = xcb_randr_get_screen_resources_current_outputs_length(rres_reply); | ||||||
|  |     outputs = xcb_randr_get_screen_resources_current_outputs(rres_reply); | ||||||
|  |     struct rect temp[num]; | ||||||
|  |  | ||||||
|  |     /* use all outputs connected to a crtc */ | ||||||
|  |     for (i = 0; i < num; i++) { | ||||||
|  |         xcb_randr_get_output_info_cookie_t output_cookie; | ||||||
|  |         xcb_randr_get_output_info_reply_t *output_reply; | ||||||
|  |         xcb_randr_get_crtc_info_cookie_t crtc_cookie; | ||||||
|  |         xcb_randr_get_crtc_info_reply_t *crtc_reply; | ||||||
|  |  | ||||||
|  |         output_cookie = xcb_randr_get_output_info(c, outputs[i], | ||||||
|  |                                                   rres_reply->config_timestamp); | ||||||
|  |         output_reply = xcb_randr_get_output_info_reply(c, output_cookie, &err); | ||||||
|  |         if (err != NULL || output_reply == NULL || output_reply->crtc == XCB_NONE) { | ||||||
|  |             temp[i].width = 0; | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |         crtc_cookie = xcb_randr_get_crtc_info(c, output_reply->crtc, | ||||||
|  |                                               rres_reply->config_timestamp); | ||||||
|  |         crtc_reply = xcb_randr_get_crtc_info_reply(c, crtc_cookie, &err); | ||||||
|  |         if (err != NULL || crtc_reply == NULL) { | ||||||
|  |             fprintf(stderr, "Failed to get randr crtc info\n"); | ||||||
|  |             temp[i].width = 0; | ||||||
|  |             free(output_reply); | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |         temp[i].x = crtc_reply->x; | ||||||
|  |         temp[i].y = crtc_reply->y; | ||||||
|  |         temp[i].width = crtc_reply->width; | ||||||
|  |         temp[i].height = crtc_reply->height; | ||||||
|  |         free(crtc_reply); | ||||||
|  |         free(output_reply); | ||||||
|  |         cnt++; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* check for clones */ | ||||||
|  |     for (i = 0; i < num; i++) { | ||||||
|  |         if (temp[i].width == 0) | ||||||
|  |             continue; | ||||||
|  |         for (j = 0; j < num; j++) { | ||||||
|  |             if (i == j || temp[j].width == 0 || temp[i].x != temp[j].x || temp[i].y != temp[j].y) | ||||||
|  |                 continue; | ||||||
|  |             temp[i].width = (temp[i].width < temp[j].width) ? temp[i].width : temp[j].width; | ||||||
|  |             temp[i].height = (temp[i].height < temp[j].height) ? temp[i].height : temp[j].height; | ||||||
|  |             temp[j].width = 0; | ||||||
|  |             cnt--; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (cnt < 1) { | ||||||
|  |         fprintf(stderr, "No usable randr outputs\n"); | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     s = calloc(cnt, sizeof(screen_t)); | ||||||
|  |     if (s == NULL) | ||||||
|  |         exit(1); | ||||||
|  |  | ||||||
|  |     for (i = j = 0; i < num && j < cnt; i++) | ||||||
|  |         if (temp[i].width) { | ||||||
|  |             s[j].x = temp[i].x; | ||||||
|  |             s[j++].width = temp[i].width; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     *spp = s; | ||||||
|  |  | ||||||
|  |     return cnt; | ||||||
|  | } | ||||||
|  |  | ||||||
| void | void | ||||||
| init (void) | init (void) | ||||||
| { | { | ||||||
|     xcb_screen_t *scr; |     xcb_screen_t *scr; | ||||||
|     xcb_window_t root; |     xcb_window_t root; | ||||||
|  |     screen_t *temp; | ||||||
|     int y; |     int y; | ||||||
|     int right_bar_offset; |     int right_bar_offset; | ||||||
|  |     xcb_generic_error_t *err; | ||||||
| #if XINERAMA |     const xcb_query_extension_reply_t *ext_reply; | ||||||
|     xcb_generic_error_t* err = NULL; |  | ||||||
|     xcb_xinerama_query_screens_reply_t *xinerama_reply; |  | ||||||
|     xcb_xinerama_query_screens_cookie_t xinerama_query; |  | ||||||
|     xcb_xinerama_screen_info_iterator_t xinerama_iter; |  | ||||||
|     screen_t *cur_screen; |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|     /* Connect to X */ |     /* Connect to X */ | ||||||
|     c = xcb_connect (NULL, NULL); |     c = xcb_connect (NULL, NULL); | ||||||
| @@ -385,62 +514,61 @@ init (void) | |||||||
|         exit (1); |         exit (1); | ||||||
|  |  | ||||||
|     /* Generate a list of screens */ |     /* Generate a list of screens */ | ||||||
| #if XINERAMA |     num_screens = 0; | ||||||
|     xinerama_query = xcb_xinerama_query_screens_unchecked (c); |     if ((ext_reply = xcb_get_extension_data(c, &xcb_randr_id)) && ext_reply->present) { | ||||||
|     xinerama_reply = xcb_xinerama_query_screens_reply (c, xinerama_query, &err); |         num_screens = get_randr_outputs(root, &screens); | ||||||
|     if (err != NULL || xinerama_reply == NULL) |         randr_event = ext_reply->first_event; | ||||||
|         exit (1); |     } | ||||||
|  |     else if ((ext_reply = xcb_get_extension_data(c, &xcb_xinerama_id)) && ext_reply->present) | ||||||
|  |         num_screens = get_xinerama_outputs(root, &screens); | ||||||
|  |  | ||||||
|     xinerama_iter = xcb_xinerama_query_screens_screen_info_iterator (xinerama_reply); | #if 0 | ||||||
|  |     if (num_screens) { | ||||||
|  |         /* Add BAR_OFFSET to the last screen */ | ||||||
|  |         right_bar_offset = scr->width_in_pixels - bar_width - BAR_OFFSET; | ||||||
|  |         for (cur_screen = &screens[num_screens-1]; cur_screen >= screens; xcb_xinerama_screen_info_next (&xinerama_iter), cur_screen--) { | ||||||
|  |             cur_screen->width = xinerama_iter.data->width; | ||||||
|  |             if (right_bar_offset > 0) { | ||||||
|  |                 if (right_bar_offset >= cur_screen->width) { | ||||||
|  |                     /* Remove the screen */ | ||||||
|  |                     num_screens--; | ||||||
|  |                     right_bar_offset -= cur_screen->width; | ||||||
|  |                 } else { | ||||||
|  |                     cur_screen->width -= right_bar_offset; | ||||||
|  |                     right_bar_offset = 0; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|     num_screens = xinerama_iter.rem; |             cur_screen->x = xinerama_iter.data->x_org - BAR_OFFSET; | ||||||
|     screens = calloc (num_screens, sizeof(screen_t)); |             if (cur_screen->x < 0) { | ||||||
|  |                 /* First screen */ | ||||||
|     if (screens == NULL) |                 cur_screen->x = 0; | ||||||
|         exit (1); |                 break; | ||||||
|  |  | ||||||
|     /* Add BAR_OFFSET to the last screen */ |  | ||||||
|     right_bar_offset = scr->width_in_pixels - bar_width - BAR_OFFSET; |  | ||||||
|     for (cur_screen = &screens[num_screens-1]; cur_screen >= screens; xcb_xinerama_screen_info_next (&xinerama_iter), cur_screen--) { |  | ||||||
|         cur_screen->width = xinerama_iter.data->width; |  | ||||||
|         if (right_bar_offset > 0) { |  | ||||||
|             if (right_bar_offset >= cur_screen->width) { |  | ||||||
|                 /* Remove the screen */ |  | ||||||
|                 num_screens--; |  | ||||||
|                 right_bar_offset -= cur_screen->width; |  | ||||||
|             } else { |  | ||||||
|                 cur_screen->width -= right_bar_offset; |  | ||||||
|                 right_bar_offset = 0; |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |         /* Remove BAR_OFFSET from the first screen */ | ||||||
|         cur_screen->x = xinerama_iter.data->x_org - BAR_OFFSET; |         cur_screen->width -= BAR_OFFSET; | ||||||
|         if (cur_screen->x < 0) { |         /* Shift */ | ||||||
|             /* First screen */ |         if (cur_screen > screens) { | ||||||
|             cur_screen->x = 0; |             memmove (screens, cur_screen, sizeof(screen_t) * num_screens); | ||||||
|             break; |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         /* Reallocate */ | ||||||
|  |         screens = realloc (screens, num_screens); | ||||||
|  |         if (screens == NULL) | ||||||
|  |             exit (1); | ||||||
|     } |     } | ||||||
|     free(xinerama_reply); |     else | ||||||
|  |  | ||||||
|     /* Remove BAR_OFFSET from the first screen */ |  | ||||||
|     cur_screen->width -= BAR_OFFSET; |  | ||||||
|  |  | ||||||
|     /* Shift */ |  | ||||||
|     if (cur_screen > screens) { |  | ||||||
|         memmove (screens, cur_screen, sizeof(screen_t) * num_screens); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* Reallocate */ |  | ||||||
|     screens = realloc (screens, num_screens); |  | ||||||
|     if (screens == NULL) |  | ||||||
|         exit (1); |  | ||||||
| #else |  | ||||||
|     num_screens = 1; |  | ||||||
|     screens = calloc(1, sizeof(screen_t)); |  | ||||||
|     screens[0].x = 0; |  | ||||||
|     screens[0].width = bar_width; |  | ||||||
| #endif | #endif | ||||||
|  |     if (num_screens == 0) | ||||||
|  |     { | ||||||
|  |         num_screens = 1; | ||||||
|  |         screens = calloc(1, sizeof(screen_t)); | ||||||
|  |         if (screens == NULL) | ||||||
|  |             exit(1); | ||||||
|  |         screens[0].x = 0; | ||||||
|  |         screens[0].width = bar_width; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /* Create the main window */ |     /* Create the main window */ | ||||||
|     win = xcb_generate_id (c); |     win = xcb_generate_id (c); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user