Bläddra i källkod

Overhauled window drawing, yet again; fixes issue #155

- Buffer for window content is bigger than the window, minimizes artifacts
  when window is resized
- Back to using XSetWindowBackgroundPixmap() instead of XCopyArea(),
  no need to handle exposure events; X server can show gray background directly
  after resize event before sxiv redraws the window contents
master
Bert Münnich 10 år sedan
förälder
incheckning
bb6721549b
6 ändrade filer med 54 tillägg och 75 borttagningar
  1. +1
    -1
      Makefile
  2. +1
    -1
      image.c
  3. +5
    -7
      main.c
  4. +10
    -10
      thumbs.c
  5. +31
    -52
      window.c
  6. +6
    -4
      window.h

+ 1
- 1
Makefile Visa fil

@@ -1,4 +1,4 @@
VERSION = git-20140725
VERSION = git-20140728


PREFIX = /usr/local PREFIX = /usr/local
MANPREFIX = $(PREFIX)/share/man MANPREFIX = $(PREFIX)/share/man


+ 1
- 1
image.c Visa fil

@@ -497,7 +497,7 @@ void img_render(img_t *img)


imlib_context_set_image(img->im); imlib_context_set_image(img->im);
imlib_context_set_anti_alias(img->aa); imlib_context_set_anti_alias(img->aa);
imlib_context_set_drawable(win->pm);
imlib_context_set_drawable(win->buf.pm);


if (imlib_image_has_alpha()) { if (imlib_image_has_alpha()) {
if ((bg = imlib_create_image(dw, dh)) == NULL) if ((bg = imlib_create_image(dw, dh)) == NULL)


+ 5
- 7
main.c Visa fil

@@ -301,7 +301,7 @@ void read_info(void)
end: end:
info.i -= info.lastsep; info.i -= info.lastsep;
win.bar.l[info.i] = '\0'; win.bar.l[info.i] = '\0';
win_update_bar(&win);
win_draw(&win);
close(info.fd); close(info.fd);
info.fd = -1; info.fd = -1;
while (waitpid(-1, NULL, WNOHANG) > 0); while (waitpid(-1, NULL, WNOHANG) > 0);
@@ -487,7 +487,7 @@ void run_key_handler(const char *key, unsigned int mask)
if (restore_bar) if (restore_bar)
memcpy(oldbar, win.bar.l, sizeof(win.bar.l)); memcpy(oldbar, win.bar.l, sizeof(win.bar.l));
strncpy(win.bar.l, "Running key handler...", sizeof(win.bar.l)); strncpy(win.bar.l, "Running key handler...", sizeof(win.bar.l));
win_update_bar(&win);
win_draw(&win);
win_set_cursor(&win, CURSOR_WATCH); win_set_cursor(&win, CURSOR_WATCH);
stat(files[n].path, &oldst); stat(files[n].path, &oldst);


@@ -512,7 +512,7 @@ void run_key_handler(const char *key, unsigned int mask)
} }
restore_bar = false; restore_bar = false;
strncpy(win.bar.l, "Reloading image...", sizeof(win.bar.l)); strncpy(win.bar.l, "Reloading image...", sizeof(win.bar.l));
win_update_bar(&win);
win_draw(&win);


if (mode == MODE_IMAGE) { if (mode == MODE_IMAGE) {
img_close(&img, true); img_close(&img, true);
@@ -529,7 +529,7 @@ void run_key_handler(const char *key, unsigned int mask)
end: end:
if (restore_bar) if (restore_bar)
memcpy(win.bar.l, oldbar, sizeof(win.bar.l)); memcpy(win.bar.l, oldbar, sizeof(win.bar.l));
set_timeout(reset_cursor, TO_CURSOR_HIDE, true);
reset_cursor();
redraw(); redraw();
} }


@@ -732,9 +732,6 @@ void run(void)
} }
} }
break; break;
case Expose:
win_expose(&win, &ev.xexpose);
break;
case KeyPress: case KeyPress:
on_keypress(&ev.xkey); on_keypress(&ev.xkey);
break; break;
@@ -870,6 +867,7 @@ int main(int argc, char **argv)
} }


win_open(&win); win_open(&win);
win_set_cursor(&win, CURSOR_WATCH);


run(); run();
cleanup(); cleanup();


+ 10
- 10
thumbs.c Visa fil

@@ -370,7 +370,7 @@ void tns_render(tns_t *tns)


win = tns->win; win = tns->win;
win_clear(win); win_clear(win);
imlib_context_set_drawable(win->pm);
imlib_context_set_drawable(win->buf.pm);


tns->cols = MAX(1, win->w / thumb_dim); tns->cols = MAX(1, win->w / thumb_dim);
tns->rows = MAX(1, win->h / thumb_dim); tns->rows = MAX(1, win->h / thumb_dim);
@@ -429,14 +429,14 @@ void tns_mark(tns_t *tns, int n, bool mark)
else else
col = win->bgcol; col = win->bgcol;


win_draw_rect(win, win->pm, x - 4, y - 4, 8, 2, true, 0, col);
win_draw_rect(win, win->pm, x - 4, y - 4, 2, 8, true, 0, col);
win_draw_rect(win, win->pm, x + w - 4, y - 4, 8, 2, true, 0, col);
win_draw_rect(win, win->pm, x + w + 2, y - 4, 2, 8, true, 0, col);
win_draw_rect(win, win->pm, x - 4, y + h + 2, 8, 2, true, 0, col);
win_draw_rect(win, win->pm, x - 4, y + h - 4, 2, 8, true, 0, col);
win_draw_rect(win, win->pm, x + w - 4, y + h + 2, 8, 2, true, 0, col);
win_draw_rect(win, win->pm, x + w + 2, y + h - 4, 2, 8, true, 0, col);
win_draw_rect(win, win->buf.pm, x - 4, y - 4, 8, 2, true, 0, col);
win_draw_rect(win, win->buf.pm, x - 4, y - 4, 2, 8, true, 0, col);
win_draw_rect(win, win->buf.pm, x + w - 4, y - 4, 8, 2, true, 0, col);
win_draw_rect(win, win->buf.pm, x + w + 2, y - 4, 2, 8, true, 0, col);
win_draw_rect(win, win->buf.pm, x - 4, y + h + 2, 8, 2, true, 0, col);
win_draw_rect(win, win->buf.pm, x - 4, y + h - 4, 2, 8, true, 0, col);
win_draw_rect(win, win->buf.pm, x + w - 4, y + h + 2, 8, 2, true, 0, col);
win_draw_rect(win, win->buf.pm, x + w + 2, y + h - 4, 2, 8, true, 0, col);
} }
} }


@@ -457,7 +457,7 @@ void tns_highlight(tns_t *tns, int n, bool hl)
else else
col = win->bgcol; col = win->bgcol;


win_draw_rect(win, win->pm, t->x - 3, t->y - 3, t->w + 6, t->h + 6,
win_draw_rect(win, win->buf.pm, t->x - 3, t->y - 3, t->w + 6, t->h + 6,
false, 2, col); false, 2, col);


if (!hl && t->file->marked) if (!hl && t->file->marked)


+ 31
- 52
window.c Visa fil

@@ -186,14 +186,13 @@ void win_open(win_t *win)
int c, i, j, n; int c, i, j, n;
win_env_t *e; win_env_t *e;
XClassHint classhint; XClassHint classhint;
XSetWindowAttributes attr;
unsigned long attr_mask;
unsigned long *icon_data; unsigned long *icon_data;
XColor col; XColor col;
char none_data[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; char none_data[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
Pixmap none; Pixmap none;
int gmask; int gmask;
XSizeHints sizehints; XSizeHints sizehints;
Bool fullscreen = options->fullscreen && fs_support;


if (win == NULL) if (win == NULL)
return; return;
@@ -237,18 +236,15 @@ void win_open(win_t *win)
win->y = 0; win->y = 0;
} }


attr.background_pixel = win->bgcol;
attr_mask = CWBackPixel;

win->xwin = XCreateWindow(e->dpy, RootWindow(e->dpy, e->scr), win->xwin = XCreateWindow(e->dpy, RootWindow(e->dpy, e->scr),
win->x, win->y, win->w, win->h, 0, win->x, win->y, win->w, win->h, 0,
e->depth, InputOutput, e->vis, attr_mask, &attr);
e->depth, InputOutput, e->vis, 0, NULL);
if (win->xwin == None) if (win->xwin == None)
die("could not create window"); die("could not create window");
XSelectInput(e->dpy, win->xwin, XSelectInput(e->dpy, win->xwin,
ExposureMask | ButtonReleaseMask | ButtonPressMask |
KeyPressMask | PointerMotionMask | StructureNotifyMask);
ButtonReleaseMask | ButtonPressMask | KeyPressMask |
PointerMotionMask | StructureNotifyMask);


carrow = XCreateFontCursor(e->dpy, XC_left_ptr); carrow = XCreateFontCursor(e->dpy, XC_left_ptr);
chand = XCreateFontCursor(e->dpy, XC_fleur); chand = XCreateFontCursor(e->dpy, XC_fleur);
@@ -299,10 +295,18 @@ void win_open(win_t *win)


win->h -= win->bar.h; win->h -= win->bar.h;


win->buf.w = e->scrw;
win->buf.h = e->scrh;
win->buf.pm = XCreatePixmap(e->dpy, win->xwin,
win->buf.w, win->buf.h, e->depth);
XSetForeground(e->dpy, gc, fullscreen ? win->fscol : win->bgcol);
XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h);
XSetWindowBackgroundPixmap(e->dpy, win->xwin, win->buf.pm);

XMapWindow(e->dpy, win->xwin); XMapWindow(e->dpy, win->xwin);
XFlush(e->dpy); XFlush(e->dpy);


if (options->fullscreen)
if (fullscreen)
win_toggle_fullscreen(win); win_toggle_fullscreen(win);
} }


@@ -329,12 +333,7 @@ bool win_configure(win_t *win, XConfigureEvent *c)
if (win == NULL || c == NULL) if (win == NULL || c == NULL)
return false; return false;


if ((changed = win->w != c->width || win->h + win->bar.h != c->height)) {
if (win->pm != None) {
XFreePixmap(win->env.dpy, win->pm);
win->pm = None;
}
}
changed = win->w != c->width || win->h + win->bar.h != c->height;


win->x = c->x; win->x = c->x;
win->y = c->y; win->y = c->y;
@@ -345,15 +344,6 @@ bool win_configure(win_t *win, XConfigureEvent *c)
return changed; return changed;
} }


void win_expose(win_t *win, XExposeEvent *e)
{
if (win == NULL || win->xwin == None || win->pm == None || e == NULL)
return;

XCopyArea(win->env.dpy, win->pm, win->xwin, gc,
e->x, e->y, e->width, e->height, e->x, e->y);
}

void win_toggle_fullscreen(win_t *win) void win_toggle_fullscreen(win_t *win)
{ {
XEvent ev; XEvent ev;
@@ -402,20 +392,22 @@ void win_toggle_bar(win_t *win)


void win_clear(win_t *win) void win_clear(win_t *win)
{ {
int h;
win_env_t *e; win_env_t *e;


if (win == NULL || win->xwin == None) if (win == NULL || win->xwin == None)
return; return;


h = win->h + win->bar.h;
e = &win->env; e = &win->env;


if (win->pm == None)
win->pm = XCreatePixmap(e->dpy, win->xwin, win->w, h, e->depth);

if (win->w > win->buf.w || win->h + win->bar.h > win->buf.h) {
XFreePixmap(e->dpy, win->buf.pm);
win->buf.w = MAX(win->buf.w, win->w);
win->buf.h = MAX(win->buf.h, win->h + win->bar.h);
win->buf.pm = XCreatePixmap(e->dpy, win->xwin,
win->buf.w, win->buf.h, e->depth);
}
XSetForeground(e->dpy, gc, win->fullscreen ? win->fscol : win->bgcol); XSetForeground(e->dpy, gc, win->fullscreen ? win->fscol : win->bgcol);
XFillRectangle(e->dpy, win->pm, gc, 0, 0, win->w, h);
XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h);
} }


void win_draw_bar(win_t *win) void win_draw_bar(win_t *win)
@@ -425,7 +417,7 @@ void win_draw_bar(win_t *win)
const char *dots = "..."; const char *dots = "...";
win_env_t *e; win_env_t *e;


if (win == NULL || win->xwin == None || win->pm == None)
if (win == NULL || win->xwin == None)
return; return;


e = &win->env; e = &win->env;
@@ -433,7 +425,7 @@ void win_draw_bar(win_t *win)
w = win->w; w = win->w;


XSetForeground(e->dpy, gc, win->bar.bgcol); XSetForeground(e->dpy, gc, win->bar.bgcol);
XFillRectangle(e->dpy, win->pm, gc, 0, win->h, win->w, win->bar.h);
XFillRectangle(e->dpy, win->buf.pm, gc, 0, win->h, win->w, win->bar.h);


XSetForeground(e->dpy, gc, win->bar.fgcol); XSetForeground(e->dpy, gc, win->bar.fgcol);
XSetBackground(e->dpy, gc, win->bar.bgcol); XSetBackground(e->dpy, gc, win->bar.bgcol);
@@ -444,9 +436,9 @@ void win_draw_bar(win_t *win)
x = win->w - tw + H_TEXT_PAD; x = win->w - tw + H_TEXT_PAD;
w -= tw; w -= tw;
if (font.set) if (font.set)
XmbDrawString(e->dpy, win->pm, font.set, gc, x, y, win->bar.r, len);
XmbDrawString(e->dpy, win->buf.pm, font.set, gc, x, y, win->bar.r, len);
else else
XDrawString(e->dpy, win->pm, gc, x, y, win->bar.r, len);
XDrawString(e->dpy, win->buf.pm, gc, x, y, win->bar.r, len);
} }
if ((len = strlen(win->bar.l)) > 0) { if ((len = strlen(win->bar.l)) > 0) {
olen = len; olen = len;
@@ -462,9 +454,9 @@ void win_draw_bar(win_t *win)
} }
x = H_TEXT_PAD; x = H_TEXT_PAD;
if (font.set) if (font.set)
XmbDrawString(e->dpy, win->pm, font.set, gc, x, y, win->bar.l, len);
XmbDrawString(e->dpy, win->buf.pm, font.set, gc, x, y, win->bar.l, len);
else else
XDrawString(e->dpy, win->pm, gc, x, y, win->bar.l, len);
XDrawString(e->dpy, win->buf.pm, gc, x, y, win->bar.l, len);
if (len != olen) if (len != olen)
memcpy(win->bar.l + len - w, rest, w); memcpy(win->bar.l + len - w, rest, w);
} }
@@ -473,14 +465,14 @@ void win_draw_bar(win_t *win)


void win_draw(win_t *win) void win_draw(win_t *win)
{ {
if (win == NULL || win->xwin == None || win->pm == None)
if (win == NULL || win->xwin == None)
return; return;


if (win->bar.h > 0) if (win->bar.h > 0)
win_draw_bar(win); win_draw_bar(win);


XCopyArea(win->env.dpy, win->pm, win->xwin, gc,
0, 0, win->w, win->h + win->bar.h, 0, 0);
XSetWindowBackgroundPixmap(win->env.dpy, win->xwin, win->buf.pm);
XClearWindow(win->env.dpy, win->xwin);
XFlush(win->env.dpy); XFlush(win->env.dpy);
} }


@@ -502,19 +494,6 @@ void win_draw_rect(win_t *win, Pixmap pm, int x, int y, int w, int h,
XDrawRectangle(win->env.dpy, pm, gc, x, y, w, h); XDrawRectangle(win->env.dpy, pm, gc, x, y, w, h);
} }


void win_update_bar(win_t *win)
{
if (win == NULL || win->xwin == None || win->pm == None)
return;

if (win->bar.h > 0) {
win_draw_bar(win);
XCopyArea(win->env.dpy, win->pm, win->xwin, gc,
0, win->h, win->w, win->bar.h, 0, win->h);
XFlush(win->env.dpy);
}
}

int win_textwidth(const char *text, unsigned int len, bool with_padding) int win_textwidth(const char *text, unsigned int len, bool with_padding)
{ {
XRectangle r; XRectangle r;


+ 6
- 4
window.h Visa fil

@@ -56,7 +56,6 @@ typedef struct {
unsigned long bgcol; unsigned long bgcol;
unsigned long fscol; unsigned long fscol;
unsigned long selcol; unsigned long selcol;
Pixmap pm;


int x; int x;
int y; int y;
@@ -66,6 +65,12 @@ typedef struct {


bool fullscreen; bool fullscreen;


struct {
int w;
int h;
Pixmap pm;
} buf;

struct { struct {
unsigned int h; unsigned int h;
char l[BAR_L_LEN]; char l[BAR_L_LEN];
@@ -82,7 +87,6 @@ void win_open(win_t*);
void win_close(win_t*); void win_close(win_t*);


bool win_configure(win_t*, XConfigureEvent*); bool win_configure(win_t*, XConfigureEvent*);
void win_expose(win_t*, XExposeEvent*);


void win_toggle_fullscreen(win_t*); void win_toggle_fullscreen(win_t*);
void win_toggle_bar(win_t*); void win_toggle_bar(win_t*);
@@ -92,8 +96,6 @@ void win_draw(win_t*);
void win_draw_rect(win_t*, Pixmap, int, int, int, int, bool, int, void win_draw_rect(win_t*, Pixmap, int, int, int, int, bool, int,
unsigned long); unsigned long);


void win_update_bar(win_t*);

int win_textwidth(const char*, unsigned int, bool); int win_textwidth(const char*, unsigned int, bool);


void win_set_title(win_t*, const char*); void win_set_title(win_t*, const char*);


Laddar…
Avbryt
Spara