@ -54,6 +54,13 @@ struct status_block {
char * name , * instance ;
bool separator ;
int separator_block_width ;
// Airblader features
uint32_t background ;
uint32_t border ;
int border_top ;
int border_bottom ;
int border_left ;
int border_right ;
} ;
list_t * status_line = NULL ;
@ -397,7 +404,185 @@ void bar_ipc_init(int outputi, const char *bar_id) {
ipc_update_workspaces ( ) ;
}
/**
* Renders a sharp line of any width and height .
*
* The line is drawn from ( x , y ) to ( x + width , y + height ) where width / height is 0
* if the line has a width / height of one pixel , respectively .
*/
void render_sharp_line ( cairo_t * cairo , uint32_t color , double x , double y , double width , double height ) {
cairo_set_source_u32 ( cairo , color ) ;
if ( width > 1 & & height > 1 ) {
cairo_rectangle ( cairo , x , y , width , height ) ;
cairo_fill ( cairo ) ;
} else {
if ( width = = 1 ) {
x + = 0.5 ;
height + = y ;
width = x ;
}
if ( height = = 1 ) {
y + = 0.5 ;
width + = x ;
height = y ;
}
cairo_move_to ( cairo , x , y ) ;
cairo_set_line_width ( cairo , 1.0 ) ;
cairo_line_to ( cairo , width , height ) ;
cairo_stroke ( cairo ) ;
}
}
void render_block ( struct status_block * block , double * x , bool edge ) {
int width , height ;
get_text_size ( window , & width , & height , " %s " , block - > full_text ) ;
int textwidth = width ;
double block_width = width ;
if ( width < block - > min_width ) {
width = block - > min_width ;
}
* x - = width ;
if ( block - > border ! = 0 & & block - > border_left > 0 ) {
* x - = ( block - > border_left + margin ) ;
block_width + = block - > border_left + margin ;
}
if ( block - > border ! = 0 & & block - > border_right > 0 ) {
* x - = ( block - > border_right + margin ) ;
block_width + = block - > border_right + margin ;
}
// Add separator
if ( ! edge ) {
* x - = block - > separator_block_width ;
} else {
* x - = margin ;
}
double pos = * x ;
// render background
if ( block - > background ! = 0x0 ) {
cairo_set_source_u32 ( window - > cairo , block - > background ) ;
cairo_rectangle ( window - > cairo , pos - 0.5 , 1 , block_width , window - > height - 2 ) ;
cairo_fill ( window - > cairo ) ;
}
// render top border
if ( block - > border ! = 0 & & block - > border_top > 0 ) {
render_sharp_line ( window - > cairo , block - > border ,
pos - 0.5 ,
1 ,
block_width ,
block - > border_top ) ;
}
// render bottom border
if ( block - > border ! = 0 & & block - > border_bottom > 0 ) {
render_sharp_line ( window - > cairo , block - > border ,
pos - 0.5 ,
window - > height - 1 - block - > border_bottom ,
block_width ,
block - > border_bottom ) ;
}
// render left border
if ( block - > border ! = 0 & & block - > border_left > 0 ) {
render_sharp_line ( window - > cairo , block - > border ,
pos - 0.5 ,
1 ,
block - > border_left ,
window - > height - 2 ) ;
pos + = block - > border_left + margin ;
}
// render text
double offset = 0 ;
if ( strncmp ( block - > align , " left " , 5 ) = = 0 ) {
offset = pos ;
} else if ( strncmp ( block - > align , " right " , 5 ) = = 0 ) {
offset = pos + width - textwidth ;
} else if ( strncmp ( block - > align , " center " , 6 ) = = 0 ) {
offset = pos + ( width - textwidth ) / 2 ;
}
cairo_move_to ( window - > cairo , offset , margin ) ;
cairo_set_source_u32 ( window - > cairo , block - > color ) ;
pango_printf ( window , " %s " , block - > full_text ) ;
pos + = width ;
// render right border
if ( block - > border ! = 0 & & block - > border_right > 0 ) {
pos + = margin ;
render_sharp_line ( window - > cairo , block - > border ,
pos - 0.5 ,
1 ,
block - > border_right ,
window - > height - 2 ) ;
pos + = block - > border_right ;
}
// render separator
// TODO: Handle custom separator
if ( ! edge & & block - > separator ) {
cairo_set_source_u32 ( window - > cairo , colors . separator ) ;
cairo_set_line_width ( window - > cairo , 1 ) ;
cairo_move_to ( window - > cairo , pos + block - > separator_block_width / 2 , margin ) ;
cairo_line_to ( window - > cairo , pos + block - > separator_block_width / 2 , window - > height - margin ) ;
cairo_stroke ( window - > cairo ) ;
}
}
void render_workspace_button ( struct workspace * ws , double * x ) {
int width , height ;
get_text_size ( window , & width , & height , " %s " , ws - > name ) ;
struct box_colors box_colors ;
if ( ws - > urgent ) {
box_colors = colors . urgent_workspace ;
} else if ( ws - > focused ) {
box_colors = colors . focused_workspace ;
} else if ( ws - > visible ) {
box_colors = colors . active_workspace ;
} else {
box_colors = colors . inactive_workspace ;
}
// background
cairo_set_source_u32 ( window - > cairo , box_colors . background ) ;
cairo_rectangle ( window - > cairo , * x , 1.5 , width + ws_hor_padding * 2 - 1 ,
height + ws_ver_padding * 2 ) ;
cairo_fill ( window - > cairo ) ;
// border
cairo_set_source_u32 ( window - > cairo , box_colors . border ) ;
cairo_rectangle ( window - > cairo , * x , 1.5 , width + ws_hor_padding * 2 - 1 ,
height + ws_ver_padding * 2 ) ;
cairo_stroke ( window - > cairo ) ;
// text
cairo_set_source_u32 ( window - > cairo , box_colors . text ) ;
cairo_move_to ( window - > cairo , ( int ) * x + ws_hor_padding , margin ) ;
pango_printf ( window , " %s " , ws - > name ) ;
* x + = width + ws_hor_padding * 2 + ws_spacing ;
}
void render ( ) {
int i ;
// Clear
cairo_save ( window - > cairo ) ;
cairo_set_operator ( window - > cairo , CAIRO_OPERATOR_CLEAR ) ;
@ -417,49 +602,13 @@ void render() {
cairo_move_to ( window - > cairo , window - > width - margin - width , margin ) ;
pango_printf ( window , " %s " , line ) ;
} else if ( protocol = = I3BAR & & status_line ) {
int i , blockpos ;
int moved = 0 ;
bool corner = true ;
double pos = window - > width - 0.5 ;
bool edge = true ;
for ( i = status_line - > length - 1 ; i > = 0 ; - - i ) {
struct status_block * block = status_line - > items [ i ] ;
if ( block - > full_text & & block - > full_text [ 0 ] ) {
get_text_size ( window , & width , & height , " %s " , block - > full_text ) ;
int textwidth = width ;
if ( width < block - > min_width ) {
width = block - > min_width ;
}
moved + = width + block - > separator_block_width ;
blockpos = window - > width - margin - moved ;
int offset = 0 ;
if ( strncmp ( block - > align , " left " , 5 ) = = 0 ) {
offset = blockpos ;
}
else if ( strncmp ( block - > align , " right " , 5 ) = = 0 ) {
offset = blockpos + width - textwidth ;
}
else if ( strncmp ( block - > align , " center " , 6 ) = = 0 ) {
offset = blockpos + ( width - textwidth ) / 2 ;
}
cairo_move_to ( window - > cairo , offset , margin ) ;
cairo_set_source_u32 ( window - > cairo , block - > color ) ;
pango_printf ( window , " %s " , block - > full_text ) ;
if ( corner ) {
corner = false ;
} else if ( block - > separator ) {
cairo_set_source_u32 ( window - > cairo , colors . separator ) ;
cairo_set_line_width ( window - > cairo , 1 ) ;
cairo_move_to ( window - > cairo , blockpos + width
+ block - > separator_block_width / 2 , margin ) ;
cairo_line_to ( window - > cairo , blockpos + width
+ block - > separator_block_width / 2 , window - > height - margin ) ;
cairo_stroke ( window - > cairo ) ;
}
render_block ( block , & pos , edge ) ;
edge = false ;
}
}
}
@ -467,34 +616,9 @@ void render() {
// Workspaces
cairo_set_line_width ( window - > cairo , 1.0 ) ;
double x = 0.5 ;
int i ;
for ( i = 0 ; i < workspaces - > length ; + + i ) {
struct workspace * ws = workspaces - > items [ i ] ;
get_text_size ( window , & width , & height , " %s " , ws - > name ) ;
struct box_colors box_colors ;
if ( ws - > urgent ) {
box_colors = colors . urgent_workspace ;
} else if ( ws - > focused ) {
box_colors = colors . focused_workspace ;
} else if ( ws - > visible ) {
box_colors = colors . active_workspace ;
} else {
box_colors = colors . inactive_workspace ;
}
cairo_set_source_u32 ( window - > cairo , box_colors . background ) ;
cairo_rectangle ( window - > cairo , x , 1.5 , width + ws_hor_padding * 2 - 1 , height + ws_ver_padding * 2 ) ;
cairo_fill ( window - > cairo ) ;
cairo_set_source_u32 ( window - > cairo , box_colors . border ) ;
cairo_rectangle ( window - > cairo , x , 1.5 , width + ws_hor_padding * 2 - 1 , height + ws_ver_padding * 2 ) ;
cairo_stroke ( window - > cairo ) ;
cairo_set_source_u32 ( window - > cairo , box_colors . text ) ;
cairo_move_to ( window - > cairo , ( int ) x + ws_hor_padding , margin ) ;
pango_printf ( window , " %s " , ws - > name ) ;
x + = width + ws_hor_padding * 2 + ws_spacing ;
render_workspace_button ( ws , & x ) ;
}
}
@ -543,6 +667,8 @@ void parse_json(const char *text) {
for ( i = 0 ; i < json_object_array_length ( results ) ; + + i ) {
json_object * full_text , * short_text , * color , * min_width , * align , * urgent ;
json_object * name , * instance , * separator , * separator_block_width ;
json_object * background , * border , * border_top , * border_bottom ;
json_object * border_left , * border_right ;
json_object * json = json_object_array_get_idx ( results , i ) ;
if ( ! json ) {
@ -559,6 +685,12 @@ void parse_json(const char *text) {
json_object_object_get_ex ( json , " instance " , & instance ) ;
json_object_object_get_ex ( json , " separator " , & separator ) ;
json_object_object_get_ex ( json , " separator_block_width " , & separator_block_width ) ;
json_object_object_get_ex ( json , " background " , & background ) ;
json_object_object_get_ex ( json , " border " , & border ) ;
json_object_object_get_ex ( json , " border_top " , & border_top ) ;
json_object_object_get_ex ( json , " border_bottom " , & border_bottom ) ;
json_object_object_get_ex ( json , " border_left " , & border_left ) ;
json_object_object_get_ex ( json , " border_right " , & border_right ) ;
struct status_block * new = malloc ( sizeof ( struct status_block ) ) ;
memset ( new , 0 , sizeof ( struct status_block ) ) ;
@ -623,6 +755,43 @@ void parse_json(const char *text) {
new - > separator_block_width = 9 ; // i3bar spec
}
// Airblader features
if ( background ) {
new - > background = parse_color ( json_object_get_string ( background ) ) ;
} else {
new - > background = 0x0 ; // transparent
}
if ( border ) {
new - > border = parse_color ( json_object_get_string ( border ) ) ;
} else {
new - > border = 0x0 ; // transparent
}
if ( border_top ) {
new - > border_top = json_object_get_int ( border_top ) ;
} else {
new - > border_top = 1 ;
}
if ( border_bottom ) {
new - > border_bottom = json_object_get_int ( border_bottom ) ;
} else {
new - > border_bottom = 1 ;
}
if ( border_left ) {
new - > border_left = json_object_get_int ( border_left ) ;
} else {
new - > border_left = 1 ;
}
if ( border_right ) {
new - > border_right = json_object_get_int ( border_right ) ;
} else {
new - > border_right = 1 ;
}
list_add ( status_line , new ) ;
}