diff --git a/installer/orioninstall-gui.c b/installer/orioninstall-gui.c index a9ebf66..b034f62 100644 --- a/installer/orioninstall-gui.c +++ b/installer/orioninstall-gui.c @@ -126,6 +126,7 @@ typedef struct { Display *dpy; int scr; Window win; + Pixmap buf; /* double-buffer — all drawing goes here, then blit */ GC gc; Colormap cmap; Visual *vis; @@ -195,12 +196,12 @@ static void xftcol(Ins *s, unsigned long rgb, XftColor *out) { static void fill_rect(Ins *s, int x, int y, int w, int h, unsigned long rgb) { XSetForeground(s->dpy, s->gc, mkcolor(s, rgb)); - XFillRectangle(s->dpy, s->win, s->gc, x, y, w, h); + XFillRectangle(s->dpy, s->buf, s->gc, x, y, w, h); } static void draw_line(Ins *s, int x1, int y1, int x2, int y2, unsigned long rgb) { XSetForeground(s->dpy, s->gc, mkcolor(s, rgb)); - XDrawLine(s->dpy, s->win, s->gc, x1, y1, x2, y2); + XDrawLine(s->dpy, s->buf, s->gc, x1, y1, x2, y2); } /* Draw text and return pixel width */ @@ -210,7 +211,8 @@ static int xft_text(Ins *s, XftDraw *xd, XftFont *f, unsigned long rgb, XftColor col; xftcol(s, rgb, &col); XGlyphInfo ext; XftTextExtentsUtf8(s->dpy, f, (const FcChar8 *)str, strlen(str), &ext); - XftDrawStringUtf8(xd, &col, f, x, y + ext.height - ext.y, + /* y is the TOP of the text row; compute baseline from font metrics */ + XftDrawStringUtf8(xd, &col, f, x, y + f->ascent, (const FcChar8 *)str, strlen(str)); XftColorFree(s->dpy, s->vis, s->cmap, &col); return ext.width; @@ -264,7 +266,7 @@ static void draw_textfield(Ins *s, XftDraw *xd, int x, int y, int w, fill_rect(s, x, y, w, 32, C_INPUT_BG); /* border */ XSetForeground(s->dpy, s->gc, mkcolor(s, bord)); - XDrawRectangle(s->dpy, s->win, s->gc, x, y, w - 1, 31); + XDrawRectangle(s->dpy, s->buf, s->gc, x, y, w - 1, 31); /* content */ if (tf->len == 0 && !focused && placeholder) { @@ -321,10 +323,10 @@ static void draw_radio(Ins *s, XftDraw *xd, int x, int y, int w, /* radio circle */ int cx = x + 20, cy = y + 22; XSetForeground(s->dpy, s->gc, mkcolor(s, C_SEP)); - XDrawArc(s->dpy, s->win, s->gc, cx-8, cy-8, 16, 16, 0, 360*64); + XDrawArc(s->dpy, s->buf, s->gc, cx-8, cy-8, 16, 16, 0, 360*64); if (selected) { XSetForeground(s->dpy, s->gc, mkcolor(s, C_BTN_PRI)); - XFillArc(s->dpy, s->win, s->gc, cx-5, cy-5, 10, 10, 0, 360*64); + XFillArc(s->dpy, s->buf, s->gc, cx-5, cy-5, 10, 10, 0, 360*64); } xft_text(s, xd, s->f_body, C_TXT, x+38, y+8, label); @@ -335,7 +337,7 @@ static void draw_radio(Ins *s, XftDraw *xd, int x, int y, int w, static void draw_progress(Ins *s, int x, int y, int w, int h, int pct) { fill_rect(s, x, y, w, h, C_BAR_BG); XSetForeground(s->dpy, s->gc, mkcolor(s, C_BORDER)); - XDrawRectangle(s->dpy, s->win, s->gc, x, y, w-1, h-1); + XDrawRectangle(s->dpy, s->buf, s->gc, x, y, w-1, h-1); if (pct > 0) { int fw = (w - 2) * pct / 100; @@ -439,7 +441,7 @@ static void draw_footer(Ins *s, XftDraw *xd, int dy = fy + FOOT_H/2; unsigned long dc = (i == dot_step) ? C_BTN_PRI : C_SEP; XSetForeground(s->dpy, s->gc, mkcolor(s, dc)); - XFillArc(s->dpy, s->win, s->gc, dx-4, dy-4, 8, 8, 0, 360*64); + XFillArc(s->dpy, s->buf, s->gc, dx-4, dy-4, 8, 8, 0, 360*64); } int bw = 120, bh = 36, by = fy + (FOOT_H - bh) / 2; @@ -592,21 +594,21 @@ static void draw_locale(Ins *s, XftDraw *xd) { unsigned long fbd = factive ? C_INPUT_ACT : C_INPUT_BD; fill_rect(s, lx, fy, LC_PANE_W, 26, C_INPUT_BG); XSetForeground(s->dpy, s->gc, mkcolor(s, fbd)); - XDrawRectangle(s->dpy, s->win, s->gc, lx, fy, LC_PANE_W-1, 25); + XDrawRectangle(s->dpy, s->buf, s->gc, lx, fy, LC_PANE_W-1, 25); const char *fdisp = s->tz_filter_len ? s->tz_filter : ""; xft_text(s, xd, s->f_body, s->tz_filter_len ? C_TXT_INP : C_TXT_DIM, lx + 6, fy + 17, s->tz_filter_len ? fdisp : "Filter…"); if (factive) { int cx = lx + 6 + text_w(s, s->f_body, fdisp); XSetForeground(s->dpy, s->gc, mkcolor(s, C_TXT_INP)); - XDrawLine(s->dpy, s->win, s->gc, cx, fy + 4, cx, fy + 21); + XDrawLine(s->dpy, s->buf, s->gc, cx, fy + 4, cx, fy + 21); } /* timezone list */ int ly = fy + 32; fill_rect(s, lx, ly, LC_PANE_W, LC_LIST_H, C_PANEL); XSetForeground(s->dpy, s->gc, mkcolor(s, C_SEP)); - XDrawRectangle(s->dpy, s->win, s->gc, lx, ly, LC_PANE_W-1, LC_LIST_H-1); + XDrawRectangle(s->dpy, s->buf, s->gc, lx, ly, LC_PANE_W-1, LC_LIST_H-1); int vis = 0, row = 0; for (int i = 0; i < NTZ && vis < LC_ROWS_VIS + s->tz_scroll; i++) { @@ -631,7 +633,7 @@ static void draw_locale(Ins *s, XftDraw *xd) { int kly = ty + 22 + 32; /* align with timezone list (below filter) */ fill_rect(s, rx, kly, LC_PANE_W, LC_LIST_H + 26, C_PANEL); XSetForeground(s->dpy, s->gc, mkcolor(s, C_SEP)); - XDrawRectangle(s->dpy, s->win, s->gc, rx, kly, LC_PANE_W-1, LC_LIST_H+25); + XDrawRectangle(s->dpy, s->buf, s->gc, rx, kly, LC_PANE_W-1, LC_LIST_H+25); int kvis = NKB < LC_ROWS_VIS + 1 ? NKB : LC_ROWS_VIS + 1; for (int i = s->kb_scroll; i < NKB && (i - s->kb_scroll) < kvis; i++) { @@ -908,7 +910,7 @@ static void draw_done(Ins *s, XftDraw *xd) { /* ══════════════════════════════════════════════════════════════════ */ static void redraw(Ins *s) { - XftDraw *xd = XftDrawCreate(s->dpy, s->win, s->vis, s->cmap); + XftDraw *xd = XftDrawCreate(s->dpy, s->buf, s->vis, s->cmap); fill_rect(s, 0, 0, WIN_W, WIN_H, C_BG); switch (s->step) { @@ -923,9 +925,12 @@ static void redraw(Ins *s) { /* outer border */ XSetForeground(s->dpy, s->gc, mkcolor(s, C_BORDER)); - XDrawRectangle(s->dpy, s->win, s->gc, 0, 0, WIN_W-1, WIN_H-1); + XDrawRectangle(s->dpy, s->buf, s->gc, 0, 0, WIN_W-1, WIN_H-1); XftDrawDestroy(xd); + + /* blit double-buffer → window in one shot (eliminates ghosting) */ + XCopyArea(s->dpy, s->buf, s->win, s->gc, 0, 0, WIN_W, WIN_H, 0, 0); XFlush(s->dpy); } @@ -1258,7 +1263,8 @@ static void init(Ins *s) { (sw - WIN_W)/2, (sh - WIN_H)/2, WIN_W, WIN_H, 0, s->depth, InputOutput, s->vis, CWBackPixel | CWEventMask, &swa); - s->gc = XCreateGC(s->dpy, s->win, 0, NULL); + s->gc = XCreateGC(s->dpy, s->win, 0, NULL); + s->buf = XCreatePixmap(s->dpy, s->win, WIN_W, WIN_H, s->depth); /* window title + WM hints */ XStoreName(s->dpy, s->win, "OrionOS Installer");