From f7a93ed8e4c83946c526f7df842cb36141bbf1fe Mon Sep 17 00:00:00 2001 From: Thomas Adam Date: Fri, 24 Jun 2016 00:24:17 +0100 Subject: [PATCH] decor: allow window borders separate colours Augment the existing BorderColorset and HilightBorderColorset styles to allow up to eight numbers, each will reference existing colorset definitions which will then apply to each of the window borders. This patch has been around for almost ten years, and although it should probably be factored into a decor rewrite, I fail to see when/if that's ever going to happen, so given the impact of this change, it may well go in. Documentation in "man fvwm3style". --- doc/fvwm3_manpage_source.adoc | 27 ++- fvwm/borders.c | 400 +++++++++++++++++++++++++++------- fvwm/fvwm.h | 26 ++- fvwm/fvwm3.c | 11 +- fvwm/screen.h | 3 + fvwm/style.c | 152 +++++++++---- fvwm/style.h | 18 +- 7 files changed, 495 insertions(+), 142 deletions(-) diff --git a/doc/fvwm3_manpage_source.adoc b/doc/fvwm3_manpage_source.adoc index 43e9b0a7a..03795f736 100644 --- a/doc/fvwm3_manpage_source.adoc +++ b/doc/fvwm3_manpage_source.adoc @@ -5459,11 +5459,30 @@ work exactly like _ForeColor_, _BackColor_ and _Colorset_ but are used only if the window has the focus. These styles replace the old commands *HilightColor* and _HilightColorset_. + -_BorderColorset_ takes the colorset number as its sole argument and -overrides the colors set by _Color_ or _Colorset_. for the window -border. To stop using a colorset, the argument is omitted. +_BorderColorset_ takes eight positive integers as its arguments and will +apply the given colorsets to the eight individual components of the window +border. + -The _HilightBorderColorset_ style option works similarly to +For backwards compatibility, if one integer is supplied, that is applied to +all window border components. ++ +The border is split up into the following definitions, and is the same order as +the colorsets which will be applied to the border. ++ +.... + North, North East, East, South East, South, South West, West, North West +.... ++ +_North_, _East_, _South_, and _West_ refer to the top, left, bottom, and right +sides of the window border. ++ +_NE_, _SE_, _SW_, and _NW_ refer to the window handles. ++ +*NOTE*: due to how window handles are rendered, there is no way to make one +complete edge of a window the same color as defined by either _North_, _South_, +_East_, or _West_. ++ +The _HilightBorderColorset_ style option works the same as _BorderColorset_ but is used when the window has the focus. + !_IconTitle_ disables displaying icon labels while the opposite diff --git a/fvwm/borders.c b/fvwm/borders.c index fcc54a53b..99ce0be39 100644 --- a/fvwm/borders.c +++ b/fvwm/borders.c @@ -113,15 +113,19 @@ typedef struct typedef struct { int relief_width; - GC relief_gc; - GC shadow_gc; - Pixel fore_color; - Pixel back_color; - int cs; - int border_cs; /* for UseBorderStyle */ + GC relief_gc[BP_SIZE]; + GC shadow_gc[BP_SIZE]; + + Pixel fore_color[BP_SIZE]; + Pixel back_color[BP_SIZE]; + + int cs[BP_SIZE]; + int border_cs[BP_SIZE]; /* for UseBorderStyle */ int bg_border_cs; /* for UseBorderStyle */ Pixmap back_pixmap; - XSetWindowAttributes attributes; + + XSetWindowAttributes attributes[BP_SIZE]; + unsigned long valuemask; Pixmap texture_pixmap; int texture_pixmap_width; @@ -319,11 +323,11 @@ static void get_common_decorations( Bool do_change_gcs) { DecorFace *df; - color_quad *draw_colors; + color_quad *draw_colors[BP_SIZE]; df = border_get_border_style(t, has_focus); cd->bg_border_cs = -1; - cd->cs = -1; + if (has_focus) { /* are we using textured borders? */ @@ -345,13 +349,57 @@ static void get_common_decorations( cd->back_pixmap = Scr.gray_pixmap; if (is_border) { - draw_colors = &(t->border_hicolors); - cd->cs = t->border_cs_hi; + draw_colors[BP_NORTH] = &t->border_hicolors[BP_NORTH]; + cd->cs[BP_NORTH] = t->border_cs_hi[BP_NORTH]; + + draw_colors[BP_SOUTH] = &t->border_hicolors[BP_SOUTH]; + cd->cs[BP_SOUTH] = t->border_cs_hi[BP_SOUTH]; + + draw_colors[BP_EAST] = &t->border_hicolors[BP_EAST]; + cd->cs[BP_EAST] = t->border_cs_hi[BP_EAST]; + + draw_colors[BP_WEST] = &t->border_hicolors[BP_WEST]; + cd->cs[BP_WEST] = t->border_cs_hi[BP_WEST]; + + /* handles */ + draw_colors[BP_NE] = &t->border_hicolors[BP_NE]; + cd->cs[BP_NE] = t->border_cs_hi[BP_NE]; + + draw_colors[BP_SE] = &t->border_hicolors[BP_SE]; + cd->cs[BP_SE] = t->border_cs_hi[BP_SE]; + + draw_colors[BP_SW] = &t->border_hicolors[BP_SW]; + cd->cs[BP_SW] = t->border_cs_hi[BP_SW]; + + draw_colors[BP_NW] = &t->border_hicolors[BP_NW]; + cd->cs[BP_NW] = t->border_cs_hi[BP_NW]; } else { - draw_colors = &(t->hicolors); - cd->cs = t->cs_hi; + draw_colors[BP_NORTH] = &(t->hicolors); + cd->cs[BP_NORTH] = t->cs_hi; + + draw_colors[BP_SOUTH] = &(t->hicolors); + cd->cs[BP_SOUTH] = t->cs_hi; + + draw_colors[BP_EAST] = &(t->hicolors); + cd->cs[BP_EAST] = t->cs_hi; + + draw_colors[BP_WEST] = &(t->hicolors); + cd->cs[BP_WEST] = t->cs_hi; + + /* handles */ + draw_colors[BP_NW] = &(t->hicolors); + cd->cs[BP_NW] = t->cs_hi; + + draw_colors[BP_NE] = &(t->hicolors); + cd->cs[BP_NE] = t->cs_hi; + + draw_colors[BP_SW] = &(t->hicolors); + cd->cs[BP_SW] = t->cs_hi; + + draw_colors[BP_SE] = &(t->hicolors); + cd->cs[BP_SE] = t->cs_hi; } } else @@ -381,46 +429,126 @@ static void get_common_decorations( } if (is_border) { - draw_colors = &(t->border_colors); - cd->cs = t->border_cs; + draw_colors[BP_NORTH] = &t->border_colors[BP_NORTH]; + cd->cs[BP_NORTH] = t->border_cs[BP_NORTH]; + + draw_colors[BP_SOUTH] = &t->border_colors[BP_SOUTH]; + cd->cs[BP_SOUTH] = t->border_cs[BP_SOUTH]; + + draw_colors[BP_EAST] = &t->border_colors[BP_EAST]; + cd->cs[BP_EAST] = t->border_cs[BP_EAST]; + + draw_colors[BP_WEST] = &t->border_colors[BP_WEST]; + cd->cs[BP_WEST] = t->border_cs[BP_WEST]; + + /* handles */ + draw_colors[BP_NE] = &t->border_colors[BP_NE]; + cd->cs[BP_NE] = t->border_cs[BP_NE]; + + draw_colors[BP_SE] = &t->border_colors[BP_SE]; + cd->cs[BP_SE] = t->border_cs[BP_SE]; + + draw_colors[BP_SW] = &t->border_colors[BP_SW]; + cd->cs[BP_SW] = t->border_cs[BP_SW]; + + draw_colors[BP_NW] = &t->border_colors[BP_NW]; + cd->cs[BP_NW] = t->border_cs[BP_NW]; } else { - draw_colors = &(t->colors); - cd->cs = t->cs; + draw_colors[BP_NORTH] = &(t->colors); + cd->cs[BP_NORTH] = t->cs; + + draw_colors[BP_SOUTH] = &(t->colors); + cd->cs[BP_SOUTH] = t->cs; + + draw_colors[BP_EAST] = &(t->colors); + cd->cs[BP_EAST] = t->cs; + + draw_colors[BP_WEST] = &(t->colors); + cd->cs[BP_WEST] = t->cs; + + /* handles */ + draw_colors[BP_NW] = &(t->colors); + cd->cs[BP_NW] = t->cs; + + draw_colors[BP_NE] = &(t->colors); + cd->cs[BP_NE] = t->cs; + + draw_colors[BP_SW] = &(t->colors); + cd->cs[BP_SW] = t->cs; + + draw_colors[BP_SE] = &(t->colors); + cd->cs[BP_SE] = t->cs; } } - cd->fore_color = draw_colors->fore; - cd->back_color = draw_colors->back; + cd->fore_color[BP_NORTH] = draw_colors[BP_NORTH]->fore; + cd->back_color[BP_NORTH] = draw_colors[BP_NORTH]->back; + cd->fore_color[BP_SOUTH] = draw_colors[BP_SOUTH]->fore; + cd->back_color[BP_SOUTH] = draw_colors[BP_SOUTH]->back; + cd->fore_color[BP_EAST] = draw_colors[BP_EAST]->fore; + cd->back_color[BP_EAST] = draw_colors[BP_EAST]->back; + cd->fore_color[BP_WEST] = draw_colors[BP_WEST]->fore; + cd->back_color[BP_WEST] = draw_colors[BP_WEST]->back; + + cd->fore_color[BP_NW] = draw_colors[BP_NW]->fore; + cd->back_color[BP_NW] = draw_colors[BP_NW]->back; + cd->fore_color[BP_NE] = draw_colors[BP_NE]->fore; + cd->back_color[BP_NE] = draw_colors[BP_NE]->back; + cd->fore_color[BP_SE] = draw_colors[BP_SE]->fore; + cd->back_color[BP_SE] = draw_colors[BP_SE]->back; + cd->fore_color[BP_SW] = draw_colors[BP_SW]->fore; + cd->back_color[BP_SW] = draw_colors[BP_SW]->back; + if (do_change_gcs) { - Globalgcv.foreground = draw_colors->hilight; + int i = 0; Globalgcm = GCForeground; - XChangeGC(dpy, Scr.ScratchGC1, Globalgcm, &Globalgcv); - Globalgcv.foreground = draw_colors->shadow; - XChangeGC(dpy, Scr.ScratchGC2, Globalgcm, &Globalgcv); - cd->relief_gc = Scr.ScratchGC1; - cd->shadow_gc = Scr.ScratchGC2; + + for (i = 0; i < BP_SIZE; i++) { + Globalgcv.foreground = draw_colors[i]->hilight; + XChangeGC(dpy, Scr.ScratchBGC[i], Globalgcm, &Globalgcv); + + Globalgcv.foreground = draw_colors[i]->shadow; + XChangeGC(dpy, Scr.ScratchBGC2[i], Globalgcm, + &Globalgcv); + + cd->relief_gc[i] = Scr.ScratchBGC[i]; + cd->shadow_gc[i] = Scr.ScratchBGC2[i]; + } } /* MWMBorder style means thin 3d effects */ - cd->relief_width = (HAS_MWM_BORDER(t) ? 1 : 2); + cd->relief_width = (HAS_MWM_BORDER(t) ? 2 : 2); if (cd->texture_pixmap) { - cd->attributes.background_pixmap = cd->texture_pixmap; + int i = 0; + + for (i = 0; i < BP_SIZE; i++) + cd->attributes[i].background_pixmap = cd->texture_pixmap; cd->valuemask = CWBackPixmap; } else { if (Pdepth < 2) { - cd->attributes.background_pixmap = cd->back_pixmap; + int i = 0; + + for (i = 0; i < BP_SIZE; i++) { + cd->attributes[i].background_pixmap = + cd->back_pixmap; + } cd->valuemask = CWBackPixmap; } else { - cd->attributes.background_pixel = cd->back_color; + int i = 0; + + for (i = 0; i < BP_SIZE; i++) { + cd->attributes[i].background_pixel = + cd->back_color[i]; + } cd->valuemask = CWBackPixel; } } @@ -431,7 +559,10 @@ static void get_common_decorations( } else { - cd->notex_attributes.background_pixel = cd->back_color; + /* Just take the first color -- it'll be the same for the + * others. + */ + cd->notex_attributes.background_pixel = cd->back_color[0]; cd->notex_valuemask = CWBackPixel; } @@ -790,7 +921,7 @@ static window_parts border_get_tb_parts_to_draw( static void border_get_border_gcs( draw_border_gcs *ret_gcs, common_decorations_type *cd, FvwmWindow *fw, - Bool do_hilight) + Bool do_hilight, window_parts part) { static GC transparent_gc = None; DecorFaceStyle *borderstyle; @@ -814,17 +945,92 @@ static void border_get_border_gcs( { is_reversed = True; } - if (is_reversed) - { - ret_gcs->shadow = cd->relief_gc; - ret_gcs->relief = cd->shadow_gc; - } - else - { - ret_gcs->relief = cd->relief_gc; - ret_gcs->shadow = cd->shadow_gc; - } + switch ( part ) + { + case PART_BORDER_N: + if( is_reversed ) + { + ret_gcs->shadow = cd->relief_gc[BP_NORTH]; + ret_gcs->relief = cd->shadow_gc[BP_NORTH]; + } else { + ret_gcs->relief = cd->relief_gc[BP_NORTH]; + ret_gcs->shadow = cd->shadow_gc[BP_NORTH]; + } + break; + case PART_BORDER_S: + if( is_reversed ) + { + ret_gcs->shadow = cd->relief_gc[BP_SOUTH]; + ret_gcs->relief = cd->shadow_gc[BP_SOUTH]; + } else { + ret_gcs->relief = cd->relief_gc[BP_SOUTH]; + ret_gcs->shadow = cd->shadow_gc[BP_SOUTH]; + } + break; + case PART_BORDER_E: + if( is_reversed ) + { + ret_gcs->shadow = cd->relief_gc[BP_EAST]; + ret_gcs->relief = cd->shadow_gc[BP_EAST]; + } else { + ret_gcs->relief = cd->relief_gc[BP_EAST]; + ret_gcs->shadow = cd->shadow_gc[BP_EAST]; + } + break; + case PART_BORDER_W: + if( is_reversed ) + { + ret_gcs->shadow = cd->relief_gc[BP_WEST]; + ret_gcs->relief = cd->shadow_gc[BP_WEST]; + } else { + ret_gcs->relief = cd->relief_gc[BP_WEST]; + ret_gcs->shadow = cd->shadow_gc[BP_WEST]; + } + break; + case PART_BORDER_NW: + if( is_reversed ) + { + ret_gcs->shadow = cd->relief_gc[BP_NW]; + ret_gcs->relief = cd->shadow_gc[BP_NW]; + } else { + ret_gcs->relief = cd->relief_gc[BP_NW]; + ret_gcs->shadow = cd->shadow_gc[BP_NW]; + } + break; + case PART_BORDER_NE: + if( is_reversed ) + { + ret_gcs->shadow = cd->relief_gc[BP_NE]; + ret_gcs->relief = cd->shadow_gc[BP_NE]; + } else { + ret_gcs->relief = cd->relief_gc[BP_NE]; + ret_gcs->shadow = cd->shadow_gc[BP_NE]; + } + break; + case PART_BORDER_SW: + if( is_reversed ) + { + ret_gcs->shadow = cd->relief_gc[BP_SW]; + ret_gcs->relief = cd->shadow_gc[BP_SW]; + } else { + ret_gcs->relief = cd->relief_gc[BP_SW]; + ret_gcs->shadow = cd->shadow_gc[BP_SW]; + } + break; + case PART_BORDER_SE: + if( is_reversed ) + { + ret_gcs->shadow = cd->relief_gc[BP_SE]; + ret_gcs->relief = cd->shadow_gc[BP_SE]; + } else { + ret_gcs->relief = cd->relief_gc[BP_SE]; + ret_gcs->shadow = cd->shadow_gc[BP_SE]; + } + break; + default: + break; + } return; } @@ -921,9 +1127,9 @@ static void border_fetch_mwm_layout( ret_size_descr->w_hiout = 2; ret_size_descr->w_trout = 0; ret_size_descr->w_trin = 0; - ret_size_descr->w_shin = 1; + ret_size_descr->w_shin = 2; ret_size_descr->w_din = 0; - ret_size_descr->sum = 3; + ret_size_descr->sum = 4; ret_size_descr->trim = ret_size_descr->sum - fw->boundary_width + 1; check_remove_inset(borderstyle, ret_size_descr); trim_border_layout(fw, borderstyle, ret_size_descr); @@ -1126,12 +1332,13 @@ static void border_draw_x_mark( } if (do_draw_shadow) { - x1 = x + k; + //x1 = x + k; + x1 = x; y1 = y - 1 - k; } else { - x1 = x; + x1 = x - k; y1 = y + k; } x2 = x1 + length; @@ -1282,9 +1489,11 @@ static void border_fill_pixmap_background( valuemask |= GCForeground | GCClipMask | GCClipXOrigin | GCClipYOrigin; XChangeGC(dpy, Scr.BordersGC, valuemask, &xgcv); - XFillRectangle( + + XFillRectangle( dpy, dest_pix, Scr.BordersGC, dest_g->x, dest_g->y, dest_g->width - dest_g->x, dest_g->height - dest_g->y); + return; } @@ -1332,8 +1541,8 @@ static void border_fill_pixmap_background( if (do_tile == False) { /* pixmap, offset stored in dest_g->x/y */ - xgcv.foreground = cd->fore_color; - xgcv.background = cd->back_color; + xgcv.foreground = cd->fore_color[0]; + xgcv.background = cd->back_color[0]; valuemask |= GCForeground|GCBackground; XChangeGC(dpy, Scr.BordersGC, valuemask, &xgcv); PGraphicsRenderPixmaps( @@ -1348,8 +1557,8 @@ static void border_fill_pixmap_background( else { /* tiled pixmap */ - xgcv.foreground = cd->fore_color; - xgcv.background = cd->back_color; + xgcv.foreground = cd->fore_color[0]; + xgcv.background = cd->back_color[0]; valuemask |= GCForeground|GCBackground; XChangeGC(dpy, Scr.BordersGC, valuemask, &xgcv); PGraphicsRenderPixmaps( @@ -1444,7 +1653,7 @@ static void border_get_frame_pixmap( static void border_get_border_background( pixmap_background_type *bg, common_decorations_type *cd, - rectangle *part_g, rectangle *relative_g, int *free_bg_pixmap, Window w) + rectangle *part_g, rectangle *relative_g, int *free_bg_pixmap, Window w, window_parts part) { *free_bg_pixmap = False; @@ -1510,9 +1719,37 @@ static void border_get_border_background( else { bg->flags.use_pixmap = 0; - bg->pixel = cd->attributes.background_pixel; - } + switch ( part ) + { + case PART_BORDER_N: + bg->pixel = cd->attributes[BP_NORTH].background_pixel; + break; + case PART_BORDER_S: + bg->pixel = cd->attributes[BP_SOUTH].background_pixel; + break; + case PART_BORDER_E: + bg->pixel = cd->attributes[BP_EAST].background_pixel; + break; + case PART_BORDER_W: + bg->pixel = cd->attributes[BP_WEST].background_pixel; + break; + case PART_BORDER_NW: + bg->pixel = cd->attributes[BP_NW].background_pixel; + break; + case PART_BORDER_NE: + bg->pixel = cd->attributes[BP_NE].background_pixel; + break; + case PART_BORDER_SW: + bg->pixel = cd->attributes[BP_SW].background_pixel; + break; + case PART_BORDER_SE: + bg->pixel = cd->attributes[BP_SE].background_pixel; + break; + default: + break; + } + } return; } @@ -1542,7 +1779,7 @@ static void border_draw_one_border_part( relative_g.x = part_g.x; relative_g.y = part_g.y; border_get_border_background( - &bg, cd, &part_g, &relative_g, &free_bg_pixmap, w); + &bg, cd, &part_g, &relative_g, &free_bg_pixmap, w, part); if (cd->texture_pixmap) { switch (part) @@ -1629,7 +1866,7 @@ static void border_draw_all_border_parts( border_get_border_relief_size_descr(&br->relief, fw, do_hilight); border_get_border_marks_descr(cd, br, fw); /* fetch the gcs used to draw the border */ - border_get_border_gcs(&br->gcs, cd, fw, do_hilight); + //border_get_border_gcs(&br->gcs, cd, fw, do_hilight); /* draw everything in a big loop */ draw_parts &= (PART_FRAME | PART_HANDLES); draw_handles = (draw_parts & PART_HANDLES); @@ -1638,11 +1875,12 @@ static void border_draw_all_border_parts( { if (part & draw_parts) { - border_draw_one_border_part( - cd, fw, &br->sidebar_g, frame_g, br, part, - draw_handles, - (pressed_parts & part) ? True : False, - do_clear); + border_get_border_gcs(&br->gcs, cd, fw, do_hilight, part); + border_draw_one_border_part( + cd, fw, &br->sidebar_g, frame_g, br, part, + draw_handles, + (pressed_parts & part) ? True : False, + do_clear); } } @@ -1663,23 +1901,23 @@ static void border_draw_vector_to_pixmap( if (coords->use_fgbg == 1) { - Globalgcv.foreground = cd->fore_color; + Globalgcv.foreground = cd->fore_color[0]; Globalgcm = GCForeground; XChangeGC(dpy, Scr.ScratchGC3, Globalgcm, &Globalgcv); - Globalgcv.foreground = cd->back_color; + Globalgcv.foreground = cd->back_color[0]; XChangeGC(dpy, Scr.ScratchGC4, Globalgcm, &Globalgcv); gcs[3] = Scr.ScratchGC3; /* @3 is fg */ gcs[2] = Scr.ScratchGC4; /* @2 is bg */ } if (is_toggled) { - gcs[0] = cd->relief_gc; - gcs[1] = cd->shadow_gc; + gcs[0] = cd->relief_gc[0]; + gcs[1] = cd->shadow_gc[0]; } else { - gcs[0] = cd->shadow_gc; - gcs[1] = cd->relief_gc; + gcs[0] = cd->shadow_gc[0]; + gcs[1] = cd->relief_gc[0]; } for (i = 1; i < coords->num; i++) { @@ -2740,7 +2978,7 @@ static void border_draw_decor_to_pixmap( } else { - border = HAS_MWM_BORDER(fw) ? 1 : 2; + border = HAS_MWM_BORDER(fw) ? 2 : 2; } dest_g.width = w_g->width; dest_g.height = w_g->height; @@ -2781,7 +3019,7 @@ static void border_draw_decor_to_pixmap( if (cd->cs >= 0) { bg.pixmap.fra.mask |= FRAM_HAVE_ICON_CSET; - bg.pixmap.fra.colorset = &Colorset[cd->cs]; + bg.pixmap.fra.colorset = &Colorset[cd->cs[0]]; } } else @@ -3244,15 +3482,15 @@ static void border_set_button_pixmap( button_g = &td->layout.button_g[button]; bs = td->tbstate.bstate[button]; df = &TB_STATE(GetDecor(fw, buttons[button]))[bs]; - rgc = td->cd->relief_gc; - sgc = td->cd->shadow_gc; + rgc = td->cd->relief_gc[0]; + sgc = td->cd->shadow_gc[0]; /* prepare background, either from the window colour or from the * border style */ if (!DFS_USE_BORDER_STYLE(df->style)) { /* fill with the button background colour */ bg.flags.use_pixmap = 0; - bg.pixel = td->cd->back_color; + bg.pixel = td->cd->back_color[0]; pix_g.x = 0; pix_g.y = 0; pix_g.width = button_g->width; @@ -3269,7 +3507,7 @@ static void border_set_button_pixmap( relative_g.x = button_g->x; relative_g.y = button_g->y; border_get_border_background( - &bg, td->cd, button_g, &relative_g, &free_bg_pixmap, w); + &bg, td->cd, button_g, &relative_g, &free_bg_pixmap, w, PART_NONE); bg.pixmap.g.x = 0; bg.pixmap.g.y = 0; /* set the geometry for drawing the Tiled pixmap; @@ -3519,7 +3757,7 @@ static void border_draw_title_mono( has_vt = HAS_VERTICAL_TITLE(fw); XFillRectangle( - dpy, dest_pix, td->cd->relief_gc, + dpy, dest_pix, td->cd->relief_gc[0], td->offset - 2, 0, td->length+4, fw->title_thickness); if (fw->visible_name != (char *)NULL) { @@ -3622,15 +3860,15 @@ static void border_get_titlebar_draw_descr( /* prepare the gcs and variables */ if (td->tbstate.is_title_pressed) { - tdd->rgc = td->cd->shadow_gc; - tdd->sgc = td->cd->relief_gc; + tdd->rgc = td->cd->shadow_gc[0]; + tdd->sgc = td->cd->relief_gc[0]; } else { - tdd->rgc = td->cd->relief_gc; - tdd->sgc = td->cd->shadow_gc; + tdd->rgc = td->cd->relief_gc[0]; + tdd->sgc = td->cd->shadow_gc[0]; } - NewFontAndColor(fw->title_font, td->cd->fore_color, td->cd->back_color); + NewFontAndColor(fw->title_font, td->cd->fore_color[0], td->cd->back_color[0]); tdd->tstyle = &TB_STATE( GetDecor(fw, titlebar))[td->tbstate.tstate].style; tdd->df = &TB_STATE(GetDecor(fw, titlebar))[td->tbstate.tstate]; @@ -3658,7 +3896,7 @@ static void border_get_titlebar_draw_descr( } if (td->cd->cs >= 0) { - tdd->fstr.colorset = &Colorset[td->cd->cs]; + tdd->fstr.colorset = &Colorset[td->cd->cs[0]]; tdd->fstr.flags.has_colorset = 1; } tdd->fstr.gc = Scr.TitleGC; @@ -3682,7 +3920,7 @@ static void border_set_title_pixmap( { /* fill with the button background colour */ bg.flags.use_pixmap = 0; - bg.pixel = td->cd->back_color; + bg.pixel = td->cd->back_color[0]; pix_g.x = 0; pix_g.y = 0; pix_g.width = td->layout.title_g.width; @@ -3713,7 +3951,7 @@ static void border_set_title_pixmap( relative_g.y = td->layout.title_g.y; border_get_border_background( &bg, td->cd, &td->layout.title_g, &relative_g, - &free_bg_pixmap, w); + &free_bg_pixmap, w, PART_NONE); bg.pixmap.g.x = 0; bg.pixmap.g.y = 0; /* set the geometry for drawing the Tiled pixmap; diff --git a/fvwm/fvwm.h b/fvwm/fvwm.h index dfd8d5b0f..412f4ba86 100644 --- a/fvwm/fvwm.h +++ b/fvwm/fvwm.h @@ -185,6 +185,19 @@ typedef struct int bottom; } ewmh_strut; +enum border_part_cardinals +{ + BP_NORTH = 0, + BP_NE, + BP_EAST, + BP_SE, + BP_SOUTH, + BP_SW, + BP_WEST, + BP_NW, + BP_SIZE +}; + typedef struct { /* common flags (former flags in bits 0-12) */ @@ -620,8 +633,8 @@ typedef struct window_style char *back_color_name_hi; int colorset; int colorset_hi; - int border_colorset; - int border_colorset_hi; + int border_colorset[BP_SIZE]; + int border_colorset_hi[BP_SIZE]; int icon_title_colorset; int icon_title_colorset_hi; int icon_background_colorset; @@ -836,13 +849,14 @@ typedef struct FvwmWindow int number_cmap_windows; color_quad colors; color_quad hicolors; - color_quad border_colors; - color_quad border_hicolors; + color_quad border_colors[BP_SIZE]; + color_quad border_hicolors[BP_SIZE]; int cs; int cs_hi; - int border_cs; - int border_cs_hi; + int border_cs[BP_SIZE]; + int border_cs_hi[BP_SIZE]; + int icon_title_cs; int icon_title_cs_hi; int icon_background_cs; diff --git a/fvwm/fvwm3.c b/fvwm/fvwm3.c index 5d20ce244..4d6c7ad9e 100644 --- a/fvwm/fvwm3.c +++ b/fvwm/fvwm3.c @@ -1045,6 +1045,7 @@ static void CreateGCs(void) { XGCValues gcv; unsigned long gcm; + int i; /* create scratch GC's */ gcm = GCFunction|GCLineWidth; @@ -1055,7 +1056,15 @@ static void CreateGCs(void) Scr.ScratchGC2 = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, &gcv); Scr.ScratchGC3 = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, &gcv); Scr.ScratchGC4 = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, &gcv); - Scr.TitleGC = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, &gcv); + + for (i = 0; i < BP_SIZE; i++) { + Scr.ScratchBGC[i] = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, + &gcv); + Scr.ScratchBGC2[i] = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, + &gcv); + } + + Scr.TitleGC = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, &gcv); Scr.BordersGC = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, &gcv); Scr.TransMaskGC = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, &gcv); Scr.ScratchMonoPixmap = XCreatePixmap(dpy, Scr.Root, 1, 1, 1); diff --git a/fvwm/screen.h b/fvwm/screen.h index 3f47f7020..be8189258 100644 --- a/fvwm/screen.h +++ b/fvwm/screen.h @@ -383,6 +383,9 @@ typedef struct ScreenInfo GC ScratchGC2; GC ScratchGC3; GC ScratchGC4; + GC ScratchBGC[BP_SIZE]; + GC ScratchBGC2[BP_SIZE]; + GC TitleGC; GC BordersGC; diff --git a/fvwm/style.c b/fvwm/style.c index 99a4db36d..e54d8e5b8 100644 --- a/fvwm/style.c +++ b/fvwm/style.c @@ -39,6 +39,8 @@ /* ---------------------------- local definitions -------------------------- */ #define SAFEFREE( p ) {if (p) {free(p);(p)=NULL;}} +#define BS_BC 0 +#define BS_BC_HI 1 /* ---------------------------- local macros ------------------------------- */ @@ -50,6 +52,8 @@ /* ---------------------------- forward declarations ----------------------- */ +static int style_set_border_colorset(window_style *, char *, int); + /* ---------------------------- local variables ---------------------------- */ /* list of window names with attributes */ @@ -669,13 +673,21 @@ static void merge_styles( } if (add_style->flags.use_border_colorset) { - SSET_BORDER_COLORSET( - *merged_style, SGET_BORDER_COLORSET(*add_style)); + int i, cs; + + for (i = 0; i < BP_SIZE; i++) { + cs = SGET_BORDER_COLORSET(*add_style, i); + SSET_BORDER_COLORSET(*merged_style, i, cs); + } } if (add_style->flags.use_border_colorset_hi) { - SSET_BORDER_COLORSET_HI( - *merged_style,SGET_BORDER_COLORSET_HI(*add_style)); + int i, cs; + + for (i = 0; i < BP_SIZE; i++) { + cs = SGET_BORDER_COLORSET_HI(*add_style, i); + SSET_BORDER_COLORSET_HI(*merged_style, i, cs); + } } if (add_style->flags.use_icon_title_colorset) { @@ -2096,6 +2108,51 @@ static char *style_parse_icon_fill_style( return rest; } +static int style_set_border_colorset(window_style *ps, char *rest, int type) +{ + int vals[BP_SIZE]; + int this_many; + int this_cs; + int upto = 0; + int just_one = 0; + + this_many = GetIntegerArguments(rest, &rest, vals, BP_SIZE); + + if (this_many == 1) { + just_one = 1; + this_many = BP_SIZE; + } + + if (this_many < 2 && this_many > 8) + return 1; + + for (upto = 0; upto < this_many; upto++) { + this_cs = just_one ? vals[0] : vals[upto]; + + if (this_cs < 0) + return 1; + + if (type == BS_BC) + SSET_BORDER_COLORSET(*ps, upto, this_cs); + else + SSET_BORDER_COLORSET_HI(*ps, upto, this_cs); + + alloc_colorset(this_cs); + } + + if (type == BS_BC) { + ps->flags.use_border_colorset = 1; + ps->flag_mask.use_border_colorset = 1; + ps->change_mask.use_border_colorset = 1; + } else { + ps->flags.use_border_colorset_hi = 1; + ps->flag_mask.use_border_colorset_hi = 1; + ps->change_mask.use_border_colorset_hi = 1; + } + + return 0; +} + static Bool style_parse_one_style_option( char *token, char *rest, char **ret_rest, char *prefix, window_style *ps, icon_boxes **cur_ib) @@ -2234,13 +2291,13 @@ static Bool style_parse_one_style_option( } else if (StrEquals(token, "BorderColorset")) { - *val = -1; - GetIntegerArguments(rest, &rest, val, 1); - SSET_BORDER_COLORSET(*ps, *val); - alloc_colorset(*val); - ps->flags.use_border_colorset = (*val >= 0); - ps->flag_mask.use_border_colorset = 1; - ps->change_mask.use_border_colorset = 1; + if (style_set_border_colorset(ps, rest, BS_BC) != 0) { + fvwm_debug(__func__, "BorderColorset can only " + "contain positive integers, and have <= 8 " + "value, and have <= 8 " + "values: %s", rest); + break; + } } else if (StrEquals(token, "BottomTitleRotated")) { @@ -2867,15 +2924,14 @@ static Bool style_parse_one_style_option( } else if (StrEquals(token, "HilightBorderColorset")) { - *val = -1; - GetIntegerArguments(rest, &rest, val, 1); - SSET_BORDER_COLORSET_HI(*ps, *val); - alloc_colorset(*val); - ps->flags.use_border_colorset_hi = (*val >= 0); - ps->flag_mask.use_border_colorset_hi = 1; - ps->change_mask.use_border_colorset_hi = 1; + if (style_set_border_colorset(ps, rest, BS_BC_HI) != 0) { + fvwm_debug(__func__, "HilightBorderColorset can " + "only contain positive integers, and have " + " <= 8 values: %s", rest); + break; + } } - else if (StrEquals(token, "HilightIconTitleColorset")) + else if (StrEquals(token, "HilightIconTitleColorset")) { *val = -1; GetIntegerArguments(rest, &rest, val, 1); @@ -5315,15 +5371,13 @@ void update_style_colorset(int colorset) temp->change_mask.use_colorset_hi = 1; Scr.flags.do_need_window_update = 1; } - if (SUSE_BORDER_COLORSET(&temp->flags) && - SGET_BORDER_COLORSET(*temp) == colorset) + if (SUSE_BORDER_COLORSET(&temp->flags)) { temp->has_style_changed = 1; temp->change_mask.use_border_colorset = 1; Scr.flags.do_need_window_update = 1; } - if (SUSE_BORDER_COLORSET_HI(&temp->flags) && - SGET_BORDER_COLORSET_HI(*temp) == colorset) + if (SUSE_BORDER_COLORSET_HI(&temp->flags)) { temp->has_style_changed = 1; temp->change_mask.use_border_colorset_hi = 1; @@ -5393,18 +5447,26 @@ void update_window_color_style(FvwmWindow *fw, window_style *pstyle) } if (SUSE_BORDER_COLORSET(&pstyle->flags)) { - cs = SGET_BORDER_COLORSET(*pstyle); - fw->border_cs = cs; - fw->border_colors.hilight = Colorset[cs].hilite; - fw->border_colors.shadow = Colorset[cs].shadow; - fw->border_colors.back = Colorset[cs].bg; + int i; + + for (i = 0; i < BP_SIZE; i++) { + cs = SGET_BORDER_COLORSET(*pstyle, i); + fw->border_cs[i] = cs; + fw->border_colors[i].hilight = Colorset[cs].hilite; + fw->border_colors[i].shadow = Colorset[cs].shadow; + fw->border_colors[i].back = Colorset[cs].bg; + } } else { - fw->border_cs = -1; - fw->border_colors.hilight = fw->colors.hilight; - fw->border_colors.shadow = fw->colors.shadow; - fw->border_colors.back = fw->colors.back; + int i; + + for (i = 0; i < BP_SIZE; i++) { + fw->border_cs[i] = -1; + fw->border_colors[i].hilight = fw->colors.hilight; + fw->border_colors[i].shadow = fw->colors.shadow; + fw->border_colors[i].back = fw->colors.back; + } } } @@ -5447,18 +5509,26 @@ void update_window_color_hi_style(FvwmWindow *fw, window_style *pstyle) } if (SUSE_BORDER_COLORSET_HI(&pstyle->flags)) { - cs = SGET_BORDER_COLORSET_HI(*pstyle); - fw->border_cs_hi = cs; - fw->border_hicolors.hilight = Colorset[cs].hilite; - fw->border_hicolors.shadow = Colorset[cs].shadow; - fw->border_hicolors.back = Colorset[cs].bg; + int i; + + for (i = 0; i < BP_SIZE; i++) { + cs = SGET_BORDER_COLORSET_HI(*pstyle, i); + fw->border_cs_hi[i] = cs; + fw->border_hicolors[i].hilight = Colorset[cs].hilite; + fw->border_hicolors[i].shadow = Colorset[cs].shadow; + fw->border_hicolors[i].back = Colorset[cs].bg; + } } else { - fw->border_cs_hi = -1; - fw->border_hicolors.hilight = fw->hicolors.hilight; - fw->border_hicolors.shadow = fw->hicolors.shadow; - fw->border_hicolors.back = fw->hicolors.back; + int i; + + for (i = 0; i < BP_SIZE; i++) { + fw->border_cs_hi[i] = -1; + fw->border_hicolors[i].hilight = fw->colors.hilight; + fw->border_hicolors[i].shadow = fw->colors.shadow; + fw->border_hicolors[i].back = fw->colors.back; + } } } diff --git a/fvwm/style.h b/fvwm/style.h index f2593a477..c99cb3929 100644 --- a/fvwm/style.h +++ b/fvwm/style.h @@ -454,20 +454,20 @@ ((s).colorset) #define SSET_COLORSET(s,x) \ ((s).colorset = (x)) -#define SSET_BORDER_COLORSET(s,x) \ - ((s).border_colorset = (x)) -#define SGET_BORDER_COLORSET(s) \ - ((s).border_colorset) #define SGET_COLORSET_HI(s) \ ((s).colorset_hi) #define SSET_COLORSET_HI(s,x) \ ((s).colorset_hi = (x)) -#define SGET_BORDER_COLORSET_HI(s) \ - ((s).border_colorset_hi) -#define SSET_BORDER_COLORSET_HI(s,x) \ - ((s).border_colorset_hi = (x)) +#define SSET_BORDER_COLORSET(s,p,x) \ + ((s).border_colorset[(p)] = (x)) +#define SGET_BORDER_COLORSET(s, p) \ + ((s).border_colorset[(p)]) +#define SGET_BORDER_COLORSET_HI(s,p) \ + ((s).border_colorset_hi[(p)]) +#define SSET_BORDER_COLORSET_HI(s,p,x) \ + ((s).border_colorset_hi[(p)] = (x)) #define SSET_ICON_TITLE_COLORSET(s,x) \ - ((s).icon_title_colorset = (x)) + ((s).icon_title_colorset = (x)) #define SGET_ICON_TITLE_COLORSET(s) \ ((s).icon_title_colorset) #define SSET_ICON_TITLE_COLORSET_HI(s,x) \