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
This commit is contained in:
parent
5e481912ec
commit
bb6721549b
2
Makefile
2
Makefile
@ -1,4 +1,4 @@
|
||||
VERSION = git-20140725
|
||||
VERSION = git-20140728
|
||||
|
||||
PREFIX = /usr/local
|
||||
MANPREFIX = $(PREFIX)/share/man
|
||||
|
2
image.c
2
image.c
@ -497,7 +497,7 @@ void img_render(img_t *img)
|
||||
|
||||
imlib_context_set_image(img->im);
|
||||
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 ((bg = imlib_create_image(dw, dh)) == NULL)
|
||||
|
12
main.c
12
main.c
@ -301,7 +301,7 @@ void read_info(void)
|
||||
end:
|
||||
info.i -= info.lastsep;
|
||||
win.bar.l[info.i] = '\0';
|
||||
win_update_bar(&win);
|
||||
win_draw(&win);
|
||||
close(info.fd);
|
||||
info.fd = -1;
|
||||
while (waitpid(-1, NULL, WNOHANG) > 0);
|
||||
@ -487,7 +487,7 @@ void run_key_handler(const char *key, unsigned int mask)
|
||||
if (restore_bar)
|
||||
memcpy(oldbar, win.bar.l, 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);
|
||||
stat(files[n].path, &oldst);
|
||||
|
||||
@ -512,7 +512,7 @@ void run_key_handler(const char *key, unsigned int mask)
|
||||
}
|
||||
restore_bar = false;
|
||||
strncpy(win.bar.l, "Reloading image...", sizeof(win.bar.l));
|
||||
win_update_bar(&win);
|
||||
win_draw(&win);
|
||||
|
||||
if (mode == MODE_IMAGE) {
|
||||
img_close(&img, true);
|
||||
@ -529,7 +529,7 @@ void run_key_handler(const char *key, unsigned int mask)
|
||||
end:
|
||||
if (restore_bar)
|
||||
memcpy(win.bar.l, oldbar, sizeof(win.bar.l));
|
||||
set_timeout(reset_cursor, TO_CURSOR_HIDE, true);
|
||||
reset_cursor();
|
||||
redraw();
|
||||
}
|
||||
|
||||
@ -732,9 +732,6 @@ void run(void)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Expose:
|
||||
win_expose(&win, &ev.xexpose);
|
||||
break;
|
||||
case KeyPress:
|
||||
on_keypress(&ev.xkey);
|
||||
break;
|
||||
@ -870,6 +867,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
win_open(&win);
|
||||
win_set_cursor(&win, CURSOR_WATCH);
|
||||
|
||||
run();
|
||||
cleanup();
|
||||
|
20
thumbs.c
20
thumbs.c
@ -370,7 +370,7 @@ void tns_render(tns_t *tns)
|
||||
|
||||
win = tns->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->rows = MAX(1, win->h / thumb_dim);
|
||||
@ -429,14 +429,14 @@ void tns_mark(tns_t *tns, int n, bool mark)
|
||||
else
|
||||
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
|
||||
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);
|
||||
|
||||
if (!hl && t->file->marked)
|
||||
|
83
window.c
83
window.c
@ -186,14 +186,13 @@ void win_open(win_t *win)
|
||||
int c, i, j, n;
|
||||
win_env_t *e;
|
||||
XClassHint classhint;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long attr_mask;
|
||||
unsigned long *icon_data;
|
||||
XColor col;
|
||||
char none_data[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
Pixmap none;
|
||||
int gmask;
|
||||
XSizeHints sizehints;
|
||||
Bool fullscreen = options->fullscreen && fs_support;
|
||||
|
||||
if (win == NULL)
|
||||
return;
|
||||
@ -237,18 +236,15 @@ void win_open(win_t *win)
|
||||
win->y = 0;
|
||||
}
|
||||
|
||||
attr.background_pixel = win->bgcol;
|
||||
attr_mask = CWBackPixel;
|
||||
|
||||
win->xwin = XCreateWindow(e->dpy, RootWindow(e->dpy, e->scr),
|
||||
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)
|
||||
die("could not create window");
|
||||
|
||||
XSelectInput(e->dpy, win->xwin,
|
||||
ExposureMask | ButtonReleaseMask | ButtonPressMask |
|
||||
KeyPressMask | PointerMotionMask | StructureNotifyMask);
|
||||
ButtonReleaseMask | ButtonPressMask | KeyPressMask |
|
||||
PointerMotionMask | StructureNotifyMask);
|
||||
|
||||
carrow = XCreateFontCursor(e->dpy, XC_left_ptr);
|
||||
chand = XCreateFontCursor(e->dpy, XC_fleur);
|
||||
@ -299,10 +295,18 @@ void win_open(win_t *win)
|
||||
|
||||
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);
|
||||
XFlush(e->dpy);
|
||||
|
||||
if (options->fullscreen)
|
||||
if (fullscreen)
|
||||
win_toggle_fullscreen(win);
|
||||
}
|
||||
|
||||
@ -329,12 +333,7 @@ bool win_configure(win_t *win, XConfigureEvent *c)
|
||||
if (win == NULL || c == NULL)
|
||||
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->y = c->y;
|
||||
@ -345,15 +344,6 @@ bool win_configure(win_t *win, XConfigureEvent *c)
|
||||
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)
|
||||
{
|
||||
XEvent ev;
|
||||
@ -402,20 +392,22 @@ void win_toggle_bar(win_t *win)
|
||||
|
||||
void win_clear(win_t *win)
|
||||
{
|
||||
int h;
|
||||
win_env_t *e;
|
||||
|
||||
if (win == NULL || win->xwin == None)
|
||||
return;
|
||||
|
||||
h = win->h + win->bar.h;
|
||||
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);
|
||||
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)
|
||||
@ -425,7 +417,7 @@ void win_draw_bar(win_t *win)
|
||||
const char *dots = "...";
|
||||
win_env_t *e;
|
||||
|
||||
if (win == NULL || win->xwin == None || win->pm == None)
|
||||
if (win == NULL || win->xwin == None)
|
||||
return;
|
||||
|
||||
e = &win->env;
|
||||
@ -433,7 +425,7 @@ void win_draw_bar(win_t *win)
|
||||
w = win->w;
|
||||
|
||||
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);
|
||||
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;
|
||||
w -= tw;
|
||||
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
|
||||
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) {
|
||||
olen = len;
|
||||
@ -462,9 +454,9 @@ void win_draw_bar(win_t *win)
|
||||
}
|
||||
x = H_TEXT_PAD;
|
||||
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
|
||||
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)
|
||||
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)
|
||||
{
|
||||
if (win == NULL || win->xwin == None || win->pm == None)
|
||||
if (win == NULL || win->xwin == None)
|
||||
return;
|
||||
|
||||
if (win->bar.h > 0)
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
XRectangle r;
|
||||
|
10
window.h
10
window.h
@ -56,7 +56,6 @@ typedef struct {
|
||||
unsigned long bgcol;
|
||||
unsigned long fscol;
|
||||
unsigned long selcol;
|
||||
Pixmap pm;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
@ -66,6 +65,12 @@ typedef struct {
|
||||
|
||||
bool fullscreen;
|
||||
|
||||
struct {
|
||||
int w;
|
||||
int h;
|
||||
Pixmap pm;
|
||||
} buf;
|
||||
|
||||
struct {
|
||||
unsigned int h;
|
||||
char l[BAR_L_LEN];
|
||||
@ -82,7 +87,6 @@ void win_open(win_t*);
|
||||
void win_close(win_t*);
|
||||
|
||||
bool win_configure(win_t*, XConfigureEvent*);
|
||||
void win_expose(win_t*, XExposeEvent*);
|
||||
|
||||
void win_toggle_fullscreen(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,
|
||||
unsigned long);
|
||||
|
||||
void win_update_bar(win_t*);
|
||||
|
||||
int win_textwidth(const char*, unsigned int, bool);
|
||||
|
||||
void win_set_title(win_t*, const char*);
|
||||
|
Loading…
Reference in New Issue
Block a user