Convert fancy status and menus to Xft

This commit is contained in:
Ray Chason
2026-08-19 09:37:41 +03:00
committed by Pasi Kallinen
parent 9e57c85b16
commit 7c9cf20d1d
5 changed files with 109 additions and 12 deletions
+1 -1
View File
@@ -551,7 +551,7 @@ extern void X11_new_color(Widget w, Pixel pixel, XftColor *color);
/* ### winlabel.c ### */ /* ### winlabel.c ### */
/* Functions for management of enhanced labels */ /* Functions for management of enhanced labels */
extern void X11_wrap_widget(Widget); extern void X11_wrap_widget(Widget, int);
extern void X11_update_label(Widget); extern void X11_update_label(Widget);
extern void X11_set_attrs(Widget, unsigned); extern void X11_set_attrs(Widget, unsigned);
extern void X11_set_highlight(Widget, boolean); extern void X11_set_highlight(Widget, boolean);
+103 -6
View File
@@ -28,8 +28,13 @@ typedef struct WidgetData {
boolean highlight; boolean highlight;
/* Fonts for italic, bold and bold-italic */ /* Fonts for italic, bold and bold-italic */
#ifdef USE_XFT
int win_type;
XftFont *vfont[4];
#else /* !USE_XFT */
XFontStruct *font[4]; /* To use the fonts */ XFontStruct *font[4]; /* To use the fonts */
XFontStruct *font_ptr[4]; /* To free the fonts */ XFontStruct *font_ptr[4]; /* To free the fonts */
#endif /* ?USE_XFT */
/* Percentage bar */ /* Percentage bar */
unsigned percent; unsigned percent;
@@ -57,7 +62,7 @@ static WidgetData *get_widget_data(Widget w);
* attribute flags and a percentage bar. * attribute flags and a percentage bar.
*/ */
void void
X11_wrap_widget(Widget w) X11_wrap_widget(Widget w, int win_type)
{ {
/* We shouldn't use this for anything other than labels and subclasses /* We shouldn't use this for anything other than labels and subclasses
of labels */ of labels */
@@ -79,10 +84,16 @@ X11_wrap_widget(Widget w)
WidgetData *data = add_widget(w); WidgetData *data = add_widget(w);
/* Copy resources from the created widget */ /* Copy resources from the created widget */
#ifdef USE_XFT
data->win_type = win_type;
allocate_font(w, data, 0);
#else /* !USE_XFT */
Cardinal num_args2 = 0; Cardinal num_args2 = 0;
Arg args2[1]; Arg args2[1];
XtSetArg(args2[num_args2], XtNfont, &data->font[0]); num_args2++; XtSetArg(args2[num_args2], XtNfont, &data->font[0]); num_args2++;
XtGetValues(w, args2, num_args2); XtGetValues(w, args2, num_args2);
nhUse(win_type);
#endif /* ?USE_XFT */
/* Create the pixmap for the first time */ /* Create the pixmap for the first time */
update_label(w, data); update_label(w, data);
@@ -184,7 +195,11 @@ update_label(Widget w, WidgetData *data)
font_idx |= font_italic; font_idx |= font_italic;
allocate_font(w, data, font_idx); allocate_font(w, data, font_idx);
} }
#ifdef USE_XFT
XftFont *vfont = data->vfont[font_idx];
#else
XFontStruct *font = data->font[font_idx]; XFontStruct *font = data->font[font_idx];
#endif
String label; String label;
Boolean sens; /* Make dim if not sensitive */ Boolean sens; /* Make dim if not sensitive */
@@ -222,11 +237,17 @@ update_label(Widget w, WidgetData *data)
} }
/* Get the width of the line */ /* Get the width of the line */
#ifdef USE_XFT
XGlyphInfo extents;
XftTextExtents8(display, vfont, (const FcChar8*) (label + i), line2, &extents);
int lwidth = extents.width - extents.x;
#else
int lwidth = XTextWidth(font, label + i, line2); int lwidth = XTextWidth(font, label + i, line2);
#endif
/* Update pixmap dimensions */ /* Update pixmap dimensions */
width = max(lwidth, width); width = max(lwidth, width);
height += font->ascent + font->descent; ++height;
/* Advance to next line */ /* Advance to next line */
i += line1; i += line1;
@@ -236,7 +257,14 @@ update_label(Widget w, WidgetData *data)
} }
/* Always size for at least one line */ /* Always size for at least one line */
height = max(height, font->ascent + font->descent); height = max(height, 1);
/* Convert height to pixels */
#ifdef USE_XFT
height *= vfont->height;
#else
height *= font->ascent + font->descent;
#endif
} else { } else {
num_args = 0; num_args = 0;
XtSetArg(args[num_args], XtNwidth, &width); num_args++; XtSetArg(args[num_args], XtNwidth, &width); num_args++;
@@ -285,11 +313,20 @@ update_label(Widget w, WidgetData *data)
if ((attrs & HL_BLINK) && X11_blink) { if ((attrs & HL_BLINK) && X11_blink) {
values.foreground = values.background; values.foreground = values.background;
} }
#ifdef USE_XFT
Visual *visual = DefaultVisualOfScreen(screen);
Colormap cmap = DefaultColormapOfScreen(screen);
XftDraw *draw = XftDrawCreate(display, new_pixmap, visual, cmap);
XftColor fgcolor, bgcolor;
X11_new_color(w, values.foreground, &fgcolor);
X11_new_color(w, values.background, &bgcolor);
#else /* !USE_XFT */
values.font = font->fid; values.font = font->fid;
values.function = GXcopy; values.function = GXcopy;
GC ggc = XtGetGC(w, GC ggc = XtGetGC(w,
GCFunction | GCForeground | GCBackground | GCFont, GCFunction | GCForeground | GCBackground | GCFont,
&values); &values);
#endif /* ?USE_XFT */
if (pass == 1) { if (pass == 1) {
/* Percent bar will occupy this area */ /* Percent bar will occupy this area */
XRectangle clip = { XRectangle clip = {
@@ -298,18 +335,34 @@ update_label(Widget w, WidgetData *data)
.width = width * data->percent / 100, .width = width * data->percent / 100,
.height = height .height = height
}; };
#ifdef USE_XFT
XftDrawSetClipRectangles(draw, 0, 0, &clip, 1);
#else /* !USE_XFT */
XSetClipRectangles(display, ggc, 0, 0, &clip, 1, Unsorted); XSetClipRectangles(display, ggc, 0, 0, &clip, 1, Unsorted);
#endif /* ?USE_XFT */
} }
/* Draw a border for inverse and highlight together */ /* Draw a border for inverse and highlight together */
/* Otherwise, fill with the background color */ /* Otherwise, fill with the background color */
#ifdef USE_XFT
if (!((attrs & HL_INVERSE) && data->highlight)) {
XftDrawRect(draw, &bgcolor, 0, 0, width, height);
} else {
XftDrawRect(draw, &fgcolor, 0, 0, width, height);
}
#else /* !USE_XFT */
if (!((attrs & HL_INVERSE) && data->highlight)) { if (!((attrs & HL_INVERSE) && data->highlight)) {
XSetForeground(display, ggc, values.background); XSetForeground(display, ggc, values.background);
} }
XFillRectangle(display, new_pixmap, ggc, 0, 0, width, height); XFillRectangle(display, new_pixmap, ggc, 0, 0, width, height);
XSetForeground(display, ggc, values.foreground); XSetForeground(display, ggc, values.foreground);
#endif /* ?USE_XFT */
#ifdef USE_XFT
int y = vfont->ascent;
#else /* !USE_XFT */
int y = font->max_bounds.ascent; int y = font->max_bounds.ascent;
#endif /* ?USE_XFT */
size_t i = 0; size_t i = 0;
while (label[i] != '\0') { while (label[i] != '\0') {
size_t line1 = strcspn(label + i, "\n"); size_t line1 = strcspn(label + i, "\n");
@@ -320,7 +373,13 @@ update_label(Widget w, WidgetData *data)
} }
/* Get the width of the line */ /* Get the width of the line */
#ifdef USE_XFT
XGlyphInfo extents;
XftTextExtents8(display, vfont, (const FcChar8*) (label + i), line2, &extents);
int lwidth = extents.width - extents.x;
#else
int lwidth = XTextWidth(font, label + i, line2); int lwidth = XTextWidth(font, label + i, line2);
#endif
/* Place the line horizontally */ /* Place the line horizontally */
int x = 0; int x = 0;
@@ -339,18 +398,32 @@ update_label(Widget w, WidgetData *data)
} }
/* Render the line */ /* Render the line */
#ifdef USE_XFT
XftDrawRect(draw, &bgcolor, x, y - vfont->ascent, lwidth, vfont->height);
XftDrawString8(draw, &fgcolor, vfont, x, y,
(const FcChar8 *) (label + i), line2);
#else
XDrawImageString(display, new_pixmap, ggc, XDrawImageString(display, new_pixmap, ggc,
x, y, x, y,
label + i, line2); label + i, line2);
#endif
/* Draw the underline if requested */ /* Draw the underline if requested */
if (attrs & HL_ULINE) { if (attrs & HL_ULINE) {
#ifdef USE_XFT
XftDrawRect(draw, &fgcolor, x, y, lwidth, 1);
#else
XDrawLine(display, new_pixmap, ggc, XDrawLine(display, new_pixmap, ggc,
x, y, x, y,
x + lwidth - 1, y); x + lwidth - 1, y);
#endif
} }
#ifdef USE_XFT
y += vfont->height;
#else
y += font->ascent + font->descent; y += font->ascent + font->descent;
#endif
/* Advance to next line */ /* Advance to next line */
i += line1; i += line1;
@@ -361,10 +434,23 @@ update_label(Widget w, WidgetData *data)
/* Ensure a one-pixel border if both inverse and highlight */ /* Ensure a one-pixel border if both inverse and highlight */
if ((attrs & HL_INVERSE) && data->highlight) { if ((attrs & HL_INVERSE) && data->highlight) {
#ifdef USE_XFT
XftDrawRect(draw, &fgcolor, 0, 0, width, 1);
XftDrawRect(draw, &fgcolor, 0, height-1, width, 1);
XftDrawRect(draw, &fgcolor, 0, 0, 1, height);
XftDrawRect(draw, &fgcolor, 0, height-1, 1, height);
#else
XDrawRectangle(display, new_pixmap, ggc, 0, 0, width-1, height-1); XDrawRectangle(display, new_pixmap, ggc, 0, 0, width-1, height-1);
#endif
} }
#ifdef USE_XFT
XftColorFree(display, visual, cmap, &fgcolor);
XftColorFree(display, visual, cmap, &bgcolor);
XftDrawDestroy(draw);
#else
XtReleaseGC(w, ggc); XtReleaseGC(w, ggc);
#endif
/* Set up to display the percent bar on the second pass */ /* Set up to display the percent bar on the second pass */
if (data->percent == 0) { if (data->percent == 0) {
@@ -377,8 +463,6 @@ update_label(Widget w, WidgetData *data)
/* Update the pixmap */ /* Update the pixmap */
num_args = 0; num_args = 0;
XtSetArg(args[num_args], XtNbitmap, new_pixmap); num_args++; XtSetArg(args[num_args], XtNbitmap, new_pixmap); num_args++;
//XtSetArg(args[num_args], XtNwidth, width); num_args++;
//XtSetArg(args[num_args], XtNheight, height); num_args++;
XtSetValues(w, args, num_args); XtSetValues(w, args, num_args);
if (data->pixmap != 0) { if (data->pixmap != 0) {
XFreePixmap(display, data->pixmap); XFreePixmap(display, data->pixmap);
@@ -390,8 +474,13 @@ update_label(Widget w, WidgetData *data)
static void static void
allocate_font(Widget w, WidgetData *data, unsigned font_idx) allocate_font(Widget w, WidgetData *data, unsigned font_idx)
{ {
#ifdef USE_XFT
static const unsigned attrs[4] = {
0, HL_BOLD, HL_ITALIC, HL_BOLD | HL_ITALIC
};
data->vfont[font_idx] = X11_new_font(w, attrs[font_idx], data->win_type);
#else
Display *display = XtDisplay(w); Display *display = XtDisplay(w);
XFontStruct *font1 = (font_idx == (font_bold | font_italic)) XFontStruct *font1 = (font_idx == (font_bold | font_italic))
? data->font[font_bold] ? data->font[font_bold]
: data->font[0]; : data->font[0];
@@ -401,6 +490,7 @@ allocate_font(Widget w, WidgetData *data, unsigned font_idx)
data->font[font_idx] = data->font_ptr[font_idx] data->font[font_idx] = data->font_ptr[font_idx]
? data->font_ptr[font_idx] ? data->font_ptr[font_idx]
: font1; : font1;
#endif
} }
/* Free any allocated fonts */ /* Free any allocated fonts */
@@ -409,11 +499,18 @@ free_fonts(Widget w, WidgetData *data)
{ {
Display *display = XtDisplay(w); Display *display = XtDisplay(w);
for (unsigned i = 0; i < 4; ++i) { for (unsigned i = 0; i < 4; ++i) {
#ifdef USE_XFT
if (data->vfont[i] != NULL) {
XftFontClose(display, data->vfont[i]);
}
data->vfont[i] = NULL;
#else
if (data->font_ptr[i] != NULL) { if (data->font_ptr[i] != NULL) {
XFreeFont(display, data->font_ptr[i]); XFreeFont(display, data->font_ptr[i]);
} }
data->font[i] = NULL; data->font[i] = NULL;
data->font_ptr[i] = NULL; data->font_ptr[i] = NULL;
#endif
} }
} }
+1 -1
View File
@@ -1362,7 +1362,7 @@ menu_create_entries(struct xwindow *wp, struct menu *curr_menu)
? commandWidgetClass ? commandWidgetClass
: labelWidgetClass, : labelWidgetClass,
wp->w, args, num_args); wp->w, args, num_args);
X11_wrap_widget(curr->w); X11_wrap_widget(curr->w, NHW_MENU);
X11_set_attrs(curr->w, 0x1 << attr); X11_set_attrs(curr->w, 0x1 << attr);
if (canpick) if (canpick)
+2 -2
View File
@@ -2274,7 +2274,7 @@ create_widget(Widget parent, struct X_status_value *sv, int sv_index)
: "dlevel", : "dlevel",
labelWidgetClass, parent, labelWidgetClass, parent,
args, num_args); args, num_args);
X11_wrap_widget(sv->w); X11_wrap_widget(sv->w, NHW_STATUS);
break; break;
case SV_NAME: { case SV_NAME: {
char buf[BUFSZ]; char buf[BUFSZ];
@@ -2311,7 +2311,7 @@ create_widget(Widget parent, struct X_status_value *sv, int sv_index)
XtSetArg(args[num_args], XtNinternalHeight, 0); num_args++; XtSetArg(args[num_args], XtNinternalHeight, 0); num_args++;
sv->w = XtCreateManagedWidget(sv->name, labelWidgetClass, parent, sv->w = XtCreateManagedWidget(sv->name, labelWidgetClass, parent,
args, num_args); args, num_args);
X11_wrap_widget(sv->w); X11_wrap_widget(sv->w, NHW_STATUS);
break; break;
} }
default: default:
+2 -2
View File
@@ -57,7 +57,7 @@ create_value(Widget parent, const char *name_value)
num_args++; num_args++;
name = name =
XtCreateManagedWidget(WNAME, labelWidgetClass, form, args, num_args); XtCreateManagedWidget(WNAME, labelWidgetClass, form, args, num_args);
X11_wrap_widget(name); X11_wrap_widget(name, NHW_STATUS);
num_args = 0; num_args = 0;
XtSetArg(args[num_args], XtNjustify, XtJustifyRight); XtSetArg(args[num_args], XtNjustify, XtJustifyRight);
@@ -70,7 +70,7 @@ create_value(Widget parent, const char *name_value)
num_args++; num_args++;
Widget value = XtCreateManagedWidget(WVALUE, labelWidgetClass, form, args, Widget value = XtCreateManagedWidget(WVALUE, labelWidgetClass, form, args,
num_args); num_args);
X11_wrap_widget(value); X11_wrap_widget(value, NHW_STATUS);
return form; return form;
} }