From e5c77b711da030210a1465eb2be4fba4db6b9b6c Mon Sep 17 00:00:00 2001 From: geommer Date: Mon, 2 May 2016 14:02:54 +0200 Subject: [PATCH] A more sane? implementation for variable width feature --- include/yabar.h | 13 +++ src/ya_draw.c | 225 +++++++++++++++++++++++++++++++++++++----------- src/ya_exec.c | 59 +++++++++---- src/ya_parse.c | 4 + 4 files changed, 235 insertions(+), 66 deletions(-) diff --git a/include/yabar.h b/include/yabar.h index 125d7fa..242a411 100644 --- a/include/yabar.h +++ b/include/yabar.h @@ -62,6 +62,12 @@ extern char *strdup(const char *s); //to suppress implicit decleration warning f #define GET_MAX(A, B) ((A) > (B) ? (A) : (B)) +#define DRAW_TEXT(blk) if((blk->attr & BLKA_VAR_WIDTH)) \ + ya_draw_text_var_width(blk);\ + else \ + ya_draw_pango_text(blk); + + enum { A_LEFT =0, A_CENTER=1, @@ -304,6 +310,8 @@ struct yabar_gen_info { xcb_ewmh_connection_t *ewmh; xcb_window_t curwin; //current window xcb_window_t lstwin; //last window + uint32_t curws; + uint32_t lstws; ya_ewmh_blk *ewmh_blk; #endif //YA_INTERNAL_EWMH }; @@ -336,4 +344,9 @@ void ya_handle_prop_notify(xcb_property_notify_event_t *ep); cairo_surface_t * ya_draw_graphics(ya_block_t *blk); void ya_redraw_bar(ya_bar_t *bar); void ya_resetup_bar(ya_block_t *blk); +void ya_draw_text_var_width(ya_block_t * blk); +void ya_get_text_max_width(ya_block_t *blk); +void ya_draw_bar_var(ya_block_t *blk); +void ya_inherit_bar_bgcol(ya_block_t *blk); +void ya_draw_bar_curwin(ya_bar_t *bar); #endif /*YABAR_H*/ diff --git a/src/ya_draw.c b/src/ya_draw.c index 8171c78..a1a2a1c 100644 --- a/src/ya_draw.c +++ b/src/ya_draw.c @@ -128,6 +128,7 @@ void ya_create_block(ya_block_t *blk) { blk->bar->win, blk_width, blk->bar->height); blk->gc = xcb_generate_id(ya.c); xcb_create_gc(ya.c, blk->gc, blk->pixmap, XCB_GC_FOREGROUND, (const uint32_t[]){blk->bgcolor}); + //ya_inherit_bar_bgcol(blk); } /* @@ -173,6 +174,7 @@ void ya_create_bar(ya_bar_t * bar) { bar->gc = xcb_generate_id(ya.c); xcb_create_gc(ya.c, bar->gc, bar->win, XCB_GC_FOREGROUND, (const uint32_t[]){bar->bgcolor}); #endif //YA_NOWIN_COL + ya_draw_bar_curwin(bar); ya_setup_ewmh(bar); } @@ -197,6 +199,8 @@ xcb_visualtype_t * ya_get_visualtype() { * Here is how the text buffer of a block is rendered on the screen */ void ya_draw_pango_text(struct ya_block *blk) { + if((blk->bar->attr & BARA_REDRAW)) + ya_inherit_bar_bgcol(blk); //First override the block area with its background color in order to not draw the new text above the old one. xcb_poly_fill_rectangle(ya.c, blk->pixmap, blk->gc, 1, (const xcb_rectangle_t[]) { {0,0,blk->width, blk->bar->height} }); cairo_surface_t *surface = cairo_xcb_surface_create(ya.c, blk->pixmap, ya.visualtype, blk->width, blk->bar->height); @@ -244,25 +248,17 @@ void ya_draw_pango_text(struct ya_block *blk) { pango_layout_set_auto_dir(layout, false); pango_layout_set_height(layout, blk->bar->height); -#ifdef YA_VAR_WIDTH - int ht; - //Get the width that text can be drawn comfortably and put it in curwidth member. - pango_layout_get_pixel_size(layout, &blk->curwidth, &ht); - if(SHOULD_REDRAW(blk)) { - //Now if the bar should be redrawn due to a modified text width, we free pango and cairo memory and then do - //a total redraw for the bar. - xcb_flush(ya.c); - g_object_unref(layout); - g_object_unref(context); +/* cairo_destroy(cr); cairo_surface_destroy(surface); ya_resetup_bar(blk); return; } #else +*/ int wd, ht; pango_layout_get_pixel_size(layout, &wd, &ht); -#endif +//#endif pango_layout_set_width(layout, blk->width * PANGO_SCALE); pango_layout_set_wrap(layout, PANGO_WRAP_WORD); @@ -496,9 +492,37 @@ cairo_surface_t * ya_draw_graphics(ya_block_t *blk) { * Redraw the entire bar */ #ifdef YA_NOWIN_COL -void ya_redraw_bar(ya_bar_t *bar) { +inline void ya_inherit_bar_bgcol(ya_block_t *blk) { + //if (ya.curwin == ya.lstwin) + // return; + uint32_t col = 0x0; + //If there is no current window, set color to bgcolor_none + //Otherwise set it to the normal bar background color + if(ya.curwin == XCB_NONE) + col = blk->bar->bgcolor_none; + else + col = blk->bar->bgcolor; +#ifdef YA_DYN_COL + if(!(blk->attr & BLKA_BGCOLOR)) { + if((!(blk->attr & BLKA_DIRTY_COL))) { + blk->bgcolor = col; + blk->bgcolor_old = col; + xcb_change_gc(ya.c, blk->gc, XCB_GC_FOREGROUND, (const uint32_t[]){col}); + } + else { + blk->bgcolor_old = col; + } + } +#else + if(!(blk->attr & BLKA_BGCOLOR)) { + blk->bgcolor = col; + xcb_change_gc(ya.c, blk->gc, XCB_GC_FOREGROUND, (const uint32_t[]){col}); + } +#endif //YA_DYN_COL +} + +inline void ya_draw_bar_curwin(ya_bar_t *bar) { uint32_t col = 0x0; - ya_block_t *blk; //If there is no current window, set color to bgcolor_none //Otherwise set it to the normal bar background color if(ya.curwin == XCB_NONE) @@ -506,34 +530,27 @@ void ya_redraw_bar(ya_bar_t *bar) { else col = bar->bgcolor; xcb_change_gc(ya.c, bar->gc, XCB_GC_FOREGROUND, (const uint32_t[]){col}); - xcb_poly_fill_rectangle(ya.c, bar->win, bar->gc, 1, (const xcb_rectangle_t[]) { {0,0,bar->width, bar->height} }); - xcb_flush(ya.c); - for(int i=0; i<3; i++) { - if((blk = bar->curblk[i])) { - for(;blk;blk = blk->next_blk) { - //For blocks that have no background color, inherit the background color - //for the bar. -#ifdef YA_DYN_COL - if(!(blk->attr & BLKA_BGCOLOR)) { - if((!(blk->attr & BLKA_DIRTY_COL))) { - blk->bgcolor = col; - blk->bgcolor_old = col; - xcb_change_gc(ya.c, blk->gc, XCB_GC_FOREGROUND, (const uint32_t[]){col}); - } - else { - blk->bgcolor_old = col; - } - } -#else - if(!(blk->attr & BLKA_BGCOLOR)) { - blk->bgcolor = col; - xcb_change_gc(ya.c, blk->gc, XCB_GC_FOREGROUND, (const uint32_t[]){col}); - } -#endif //YA_DYN_COL - ya_draw_pango_text(blk); + xcb_poly_fill_rectangle(ya.c, bar->win, + bar->gc, 1, + (const xcb_rectangle_t[]) { {0,0,bar->width, bar->height} }); +} + +void ya_redraw_bar(ya_bar_t *bar) { + bar->attr |= BARA_REDRAW; + ya_draw_bar_curwin(bar); + + for(int i=0; i<3;i++) { + for(ya_block_t *blk = bar->curblk[i]; blk; blk = blk->next_blk) { + if((blk->attr & BLKA_VAR_WIDTH) && (i!=A_RIGHT)) { + ya_draw_text_var_width(blk); + break; } + else + ya_draw_pango_text(blk); } } + + bar->attr &= ~BARA_REDRAW; } #endif //YA_NOWIN_COL @@ -581,20 +598,8 @@ void ya_set_width_resetup(ya_block_t *blk) { } blk->curwidth = GET_MIN(width_init, maxw); blk->bar->occupied_width[blk->align] = blk->curwidth + othw; -} -/* - *Calculate the correct shift of blocks and then redraw the bar. - */ -void ya_resetup_bar(ya_block_t *blk) { - //Lock the bar! - //occupied_width member will be modified after calculating the maximum - //allowed size of block width using ya_set_width_resetup() - pthread_mutex_lock(&blk->bar->mutex); - blk->bar->attr |= BARA_REDRAW; - ya_set_width_resetup(blk); int delta = blk->curwidth - blk->width; - blk->width = blk->curwidth; switch(blk->align) { case A_LEFT: for(ya_block_t *curblk = blk->next_blk;curblk; curblk = curblk->next_blk) { @@ -614,8 +619,126 @@ void ya_resetup_bar(ya_block_t *blk) { } break; } + blk->width = blk->curwidth; +} + +/* + *Calculate the correct shift of blocks and then redraw the bar. + */ +void ya_resetup_bar(ya_block_t *blk) { + //Lock the bar! + //occupied_width member will be modified after calculating the maximum + //allowed size of block width using ya_set_width_resetup() +#ifdef YA_MUTEX + pthread_mutex_lock(&blk->bar->mutex); +#endif + ya_set_width_resetup(blk); ya_redraw_bar(blk->bar); - blk->bar->attr &= ~BARA_REDRAW; +#ifdef YA_MUTEX pthread_mutex_unlock(&blk->bar->mutex); +#endif +} + + +void ya_draw_text_var_width(ya_block_t * blk) { + ya_get_text_max_width(blk); + if (blk->curwidth == blk->width) { + ya_draw_pango_text(blk); + return; + } + ya_draw_bar_var(blk); + ya_set_width_resetup(blk); + switch(blk->align) { + case A_LEFT: + for(ya_block_t *curblk = blk; curblk; curblk = curblk->next_blk) { + ya_draw_pango_text(curblk); + } + break; + case A_CENTER: + for(ya_block_t *curblk = blk->bar->curblk[A_CENTER]; curblk; curblk = curblk->next_blk) { + ya_draw_pango_text(curblk); + } + break; + case A_RIGHT: + for(ya_block_t *curblk = blk; curblk; curblk = curblk->prev_blk) { + ya_draw_pango_text(curblk); + } + break; + } +} + +void ya_draw_bar_var(ya_block_t *blk) { + int start =0, end=0; + int scrw = blk->bar->mon->pos.width; + switch(blk->align) { + case A_LEFT: + start = blk->shift; + if(blk->bar->curblk[1]) { + end = (scrw - blk->bar->occupied_width[1])/2; + } + else if (blk->bar->curblk[2]) { + end = scrw - blk->bar->occupied_width[2]; + } + else { + end = scrw; + } + break; + case A_CENTER: + start = (scrw - blk->bar->occupied_width[1])/2; + end = (scrw + blk->bar->occupied_width[1])/2; + break; + case A_RIGHT: + if(blk->bar->curblk[1]) { + start = (scrw + blk->bar->occupied_width[1])/2; + } + else if (blk->bar->curblk[0]) { + start = blk->bar->occupied_width[0]; + } + else + start = 0; + end = blk->shift + blk->width; + break; + } + xcb_poly_fill_rectangle(ya.c, blk->bar->win, + blk->bar->gc, 1, + (const xcb_rectangle_t[]) { {start,0, end-start, blk->bar->height} }); +} + +void ya_get_text_max_width(ya_block_t *blk) { + cairo_surface_t *surface = cairo_xcb_surface_create(ya.c, + blk->pixmap, ya.visualtype, + blk->width, blk->bar->height); + cairo_t *cr = cairo_create(surface); + PangoContext *context = pango_cairo_create_context(cr); + PangoLayout *layout = pango_layout_new(context); + pango_layout_set_font_description(layout, blk->bar->desc); + +#ifdef YA_DYN_COL + //Start drawing text at strbuf member, where !Y COLORS Y! config ends + if (!(blk->attr & BLKA_MARKUP_PANGO)) + pango_layout_set_text(layout, blk->strbuf, strlen(blk->strbuf)); + else + pango_layout_set_markup(layout, blk->strbuf, strlen(blk->strbuf)); +#else + if (!(blk->attr & BLKA_MARKUP_PANGO)) + pango_layout_set_text(layout, blk->buf, strlen(blk->buf)); + else + pango_layout_set_markup(layout, blk->buf, strlen(blk->buf)); +#endif + //pango_layout_set_alignment(layout, blk->justify); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + pango_layout_set_auto_dir(layout, false); + + //pango_layout_set_height(layout, blk->bar->height); + int ht; + //Get the width that text can be drawn comfortably and put it in curwidth member. + pango_layout_get_pixel_size(layout, &blk->curwidth, &ht); + cairo_surface_flush(surface); + xcb_flush(ya.c); + + g_object_unref(layout); + g_object_unref(context); + cairo_destroy(cr); + cairo_surface_destroy(surface); } #endif //YA_VAR_WIDTH diff --git a/src/ya_exec.c b/src/ya_exec.c index e48ddb0..7f488c6 100644 --- a/src/ya_exec.c +++ b/src/ya_exec.c @@ -51,26 +51,34 @@ inline static void ya_exec_intern_ewmh_blk(ya_block_t *blk) { #ifdef YA_MUTEX pthread_mutex_lock(&blk->mutex); #endif +#ifdef YA_VAR_WIDTH + DRAW_TEXT(blk); +#else ya_draw_pango_text(blk); +#endif //YA_VAR_WIDTH #ifdef YA_MUTEX pthread_mutex_unlock(&blk->mutex); #endif break; } case YA_INT_WORKSPACE: { - uint32_t current_desktop; - xcb_get_property_cookie_t ck = xcb_ewmh_get_current_desktop(ya.ewmh, 0); - xcb_ewmh_get_current_desktop_reply(ya.ewmh, ck, ¤t_desktop, NULL); + //uint32_t current_desktop; + //xcb_get_property_cookie_t ck = xcb_ewmh_get_current_desktop(ya.ewmh, 0); + //xcb_ewmh_get_current_desktop_reply(ya.ewmh, ck, ¤t_desktop, NULL); if(blk->internal->option[0]==NULL) - sprintf(blk->buf, "%u", current_desktop+1); + sprintf(blk->buf, "%u", ya.curws+1); else { - ya_copy_buf_from_index(blk, current_desktop); + ya_copy_buf_from_index(blk, ya.curws); } #ifdef YA_MUTEX pthread_mutex_lock(&blk->mutex); #endif +#ifdef YA_VAR_WIDTH + DRAW_TEXT(blk); +#else ya_draw_pango_text(blk); +#endif //YA_VAR_WIDTH #ifdef YA_MUTEX pthread_mutex_unlock(&blk->mutex); #endif @@ -108,7 +116,11 @@ static void ya_exec_redir_once(ya_block_t *blk) { #ifdef YA_MUTEX pthread_mutex_lock(&blk->mutex); #endif +#ifdef YA_VAR_WIDTH + DRAW_TEXT(blk); +#else ya_draw_pango_text(blk); +#endif //YA_VAR_WIDTH #ifdef YA_MUTEX pthread_mutex_unlock(&blk->mutex); #endif @@ -151,7 +163,11 @@ static void ya_exec_redir_period(ya_block_t *blk) { #ifdef YA_MUTEX pthread_mutex_lock(&blk->mutex); #endif +#ifdef YA_VAR_WIDTH + DRAW_TEXT(blk); +#else ya_draw_pango_text(blk); +#endif //YA_VAR_WIDTH #ifdef YA_MUTEX pthread_mutex_unlock(&blk->mutex); #endif @@ -196,7 +212,11 @@ static void ya_exec_redir_persist(ya_block_t *blk) { #ifdef YA_MUTEX pthread_mutex_lock(&blk->mutex); #endif +#ifdef YA_VAR_WIDTH + DRAW_TEXT(blk); +#else ya_draw_pango_text(blk); +#endif //YA_VAR_WIDTH #ifdef YA_MUTEX pthread_mutex_unlock(&blk->mutex); #endif @@ -385,10 +405,13 @@ void ya_init() { ya.lstwin = XCB_NONE; uint32_t evm = XCB_EVENT_MASK_PROPERTY_CHANGE; - xcb_get_property_cookie_t prop_ck = xcb_ewmh_get_active_window(ya.ewmh, 0); - xcb_ewmh_get_active_window_reply(ya.ewmh, prop_ck, &ya.curwin, NULL); xcb_change_window_attributes(ya.c, ya.curwin, XCB_CW_EVENT_MASK, &evm); xcb_change_window_attributes(ya.c, ya.scr->root, XCB_CW_EVENT_MASK, &evm); + xcb_get_property_cookie_t prop_ck = xcb_ewmh_get_active_window(ya.ewmh, 0); + xcb_ewmh_get_active_window_reply(ya.ewmh, prop_ck, &ya.curwin, NULL); + xcb_get_property_cookie_t ws_ck = xcb_ewmh_get_current_desktop(ya.ewmh, 0); + xcb_ewmh_get_current_desktop_reply(ya.ewmh, ws_ck, &ya.curws, NULL); + fprintf(stderr, "WINNN = %x DESK= %x\n", ya.curwin, ya.curws); #endif //YA_INTERNAL_EWMH ya_config_parse(); @@ -398,15 +421,16 @@ void ya_init() { * After yabar initialization, we create a thread for each block. */ void ya_execute() { - ya_bar_t *curbar; - ya_block_t *curblk; - curbar = ya.curbar; + ya_bar_t *curbar = ya.curbar; + ya_block_t *curblk = NULL; #ifdef YA_INTERNAL_EWMH if(ya.ewmh_blk) { for(;ya.ewmh_blk->prev_ewblk; ya.ewmh_blk = ya.ewmh_blk->prev_ewblk); - //ya_ewmh_blk *ewmh_blk = ya.ewmh_blk; - //for(;ewmh_blk; ewmh_blk = ewmh_blk->next_ewblk) - // ya_exec_intern_ewmh_blk(ewmh_blk->blk); + ya_ewmh_blk *ewmh_blk = ya.ewmh_blk; + for(;ewmh_blk; ewmh_blk = ewmh_blk->next_ewblk) { + fprintf(stderr, "H %s\n", ewmh_blk->blk->name); + ya_exec_intern_ewmh_blk(ewmh_blk->blk); + } } #endif //YA_INTERNAL_EWMH for(; curbar->prev_bar; curbar = curbar->prev_bar); @@ -471,8 +495,12 @@ void ya_handle_prop_notify(xcb_property_notify_event_t *ep) { uint32_t pr_ev_val = XCB_EVENT_MASK_PROPERTY_CHANGE; ya_ewmh_blk *ewblk; if(ep->atom == ya.ewmh->_NET_ACTIVE_WINDOW) { - xcb_get_property_cookie_t prop_ck = xcb_ewmh_get_active_window(ya.ewmh, 0); - xcb_ewmh_get_active_window_reply(ya.ewmh, prop_ck, &ya.curwin, NULL); + xcb_get_property_cookie_t win_ck = xcb_ewmh_get_active_window(ya.ewmh, 0); + xcb_ewmh_get_active_window_reply(ya.ewmh, win_ck, &ya.curwin, NULL); + + xcb_get_property_cookie_t ws_ck = xcb_ewmh_get_current_desktop(ya.ewmh, 0); + xcb_ewmh_get_current_desktop_reply(ya.ewmh, ws_ck, &ya.curws, NULL); + if (ya.curwin != ya.lstwin) { xcb_change_window_attributes(ya.c, ya.lstwin, XCB_CW_EVENT_MASK, &no_ev_val); xcb_change_window_attributes(ya.c, ya.curwin, XCB_CW_EVENT_MASK, &pr_ev_val); @@ -503,5 +531,6 @@ void ya_handle_prop_notify(xcb_property_notify_event_t *ep) { ya_exec_intern_ewmh_blk(ewblk->blk); } ya.lstwin = ya.curwin; + ya.lstws = ya.curws; } #endif //YA_INTERNAL_EWMH diff --git a/src/ya_parse.c b/src/ya_parse.c index 21eb904..3264d07 100644 --- a/src/ya_parse.c +++ b/src/ya_parse.c @@ -87,6 +87,7 @@ static void ya_copy_blk_members(ya_block_t *dstb, ya_block_t *srcb) { dstb->internal->option[i] = srcb->internal->option[i]; dstb->internal->index = srcb->internal->index; } +#ifdef YA_ICON if((srcb->attr & BLKA_ICON)) { dstb->img = calloc(1, sizeof(blk_img_t)); strncpy(dstb->img->path, srcb->img->path, CFILELEN); @@ -95,6 +96,7 @@ static void ya_copy_blk_members(ya_block_t *dstb, ya_block_t *srcb) { dstb->img->scale_w = srcb->img->scale_w; dstb->img->scale_h = srcb->img->scale_h; } +#endif //YA_ICON } static int ya_inherit_bar(ya_bar_t *dstb, const char *srcname, bool inherit_all, ya_bar_t **inherit_bar) { @@ -372,6 +374,8 @@ inline static void ya_setup_ewmh_intern_blk(ya_block_t *blk) { case YA_INT_TITLE: blk->attr |= BLKA_INTERN_X_EV; break; + default: + return; } cur = calloc(1, sizeof(ya_ewmh_blk)); cur->blk = blk;