Krolyxon
Commit bb67215

Branches

Refs →

nsxivbb67215

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
Author
Bert Münnich
Date
2014-07-28 20:36 +0200
Parent
5e48191
Commit
bb6721549b30c33b0080975aa19a0b02a916c7e5

+54 −75

6 files changed

  1. M Makefile +1 −1
  2. M image.c +1 −1
  3. M main.c +5 −7
  4. M thumbs.c +10 −10
  5. M window.c +31 −52
  6. M window.h +6 −4
M Makefile View
@@ -1,4 +1,4 @@
1−VERSION = git-20140725
1+VERSION = git-20140728
22
33 PREFIX = /usr/local
44 MANPREFIX = $(PREFIX)/share/man
M image.c View
@@ -497,7 +497,7 @@ void img_render(img_t *img)
497497
498498 imlib_context_set_image(img->im);
499499 imlib_context_set_anti_alias(img->aa);
500− imlib_context_set_drawable(win->pm);
500+ imlib_context_set_drawable(win->buf.pm);
501501
502502 if (imlib_image_has_alpha()) {
503503 if ((bg = imlib_create_image(dw, dh)) == NULL)
M main.c View
@@ -301,7 +301,7 @@ void read_info(void)
301301 end:
302302 info.i -= info.lastsep;
303303 win.bar.l[info.i] = '\0';
304− win_update_bar(&win);
304+ win_draw(&win);
305305 close(info.fd);
306306 info.fd = -1;
307307 while (waitpid(-1, NULL, WNOHANG) > 0);
@@ -487,7 +487,7 @@ void run_key_handler(const char *key, unsigned int mask)
487487 if (restore_bar)
488488 memcpy(oldbar, win.bar.l, sizeof(win.bar.l));
489489 strncpy(win.bar.l, "Running key handler...", sizeof(win.bar.l));
490− win_update_bar(&win);
490+ win_draw(&win);
491491 win_set_cursor(&win, CURSOR_WATCH);
492492 stat(files[n].path, &oldst);
493493
@@ -512,7 +512,7 @@ void run_key_handler(const char *key, unsigned int mask)
512512 }
513513 restore_bar = false;
514514 strncpy(win.bar.l, "Reloading image...", sizeof(win.bar.l));
515− win_update_bar(&win);
515+ win_draw(&win);
516516
517517 if (mode == MODE_IMAGE) {
518518 img_close(&img, true);
@@ -529,7 +529,7 @@ void run_key_handler(const char *key, unsigned int mask)
529529 end:
530530 if (restore_bar)
531531 memcpy(win.bar.l, oldbar, sizeof(win.bar.l));
532− set_timeout(reset_cursor, TO_CURSOR_HIDE, true);
532+ reset_cursor();
533533 redraw();
534534 }
535535
@@ -732,9 +732,6 @@ void run(void)
732732 }
733733 }
734734 break;
735− case Expose:
736− win_expose(&win, &ev.xexpose);
737− break;
738735 case KeyPress:
739736 on_keypress(&ev.xkey);
740737 break;
@@ -870,6 +867,7 @@ int main(int argc, char **argv)
870867 }
871868
872869 win_open(&win);
870+ win_set_cursor(&win, CURSOR_WATCH);
873871
874872 run();
875873 cleanup();
M thumbs.c View
@@ -370,7 +370,7 @@ void tns_render(tns_t *tns)
370370
371371 win = tns->win;
372372 win_clear(win);
373− imlib_context_set_drawable(win->pm);
373+ imlib_context_set_drawable(win->buf.pm);
374374
375375 tns->cols = MAX(1, win->w / thumb_dim);
376376 tns->rows = MAX(1, win->h / thumb_dim);
@@ -429,14 +429,14 @@ void tns_mark(tns_t *tns, int n, bool mark)
429429 else
430430 col = win->bgcol;
431431
432− win_draw_rect(win, win->pm, x - 4, y - 4, 8, 2, true, 0, col);
433− win_draw_rect(win, win->pm, x - 4, y - 4, 2, 8, true, 0, col);
434− win_draw_rect(win, win->pm, x + w - 4, y - 4, 8, 2, true, 0, col);
435− win_draw_rect(win, win->pm, x + w + 2, y - 4, 2, 8, true, 0, col);
436− win_draw_rect(win, win->pm, x - 4, y + h + 2, 8, 2, true, 0, col);
437− win_draw_rect(win, win->pm, x - 4, y + h - 4, 2, 8, true, 0, col);
438− win_draw_rect(win, win->pm, x + w - 4, y + h + 2, 8, 2, true, 0, col);
439− win_draw_rect(win, win->pm, x + w + 2, y + h - 4, 2, 8, true, 0, col);
432+ win_draw_rect(win, win->buf.pm, x - 4, y - 4, 8, 2, true, 0, col);
433+ win_draw_rect(win, win->buf.pm, x - 4, y - 4, 2, 8, true, 0, col);
434+ win_draw_rect(win, win->buf.pm, x + w - 4, y - 4, 8, 2, true, 0, col);
435+ win_draw_rect(win, win->buf.pm, x + w + 2, y - 4, 2, 8, true, 0, col);
436+ win_draw_rect(win, win->buf.pm, x - 4, y + h + 2, 8, 2, true, 0, col);
437+ win_draw_rect(win, win->buf.pm, x - 4, y + h - 4, 2, 8, true, 0, col);
438+ win_draw_rect(win, win->buf.pm, x + w - 4, y + h + 2, 8, 2, true, 0, col);
439+ win_draw_rect(win, win->buf.pm, x + w + 2, y + h - 4, 2, 8, true, 0, col);
440440 }
441441 }
442442
@@ -457,7 +457,7 @@ void tns_highlight(tns_t *tns, int n, bool hl)
457457 else
458458 col = win->bgcol;
459459
460− win_draw_rect(win, win->pm, t->x - 3, t->y - 3, t->w + 6, t->h + 6,
460+ win_draw_rect(win, win->buf.pm, t->x - 3, t->y - 3, t->w + 6, t->h + 6,
461461 false, 2, col);
462462
463463 if (!hl && t->file->marked)
M window.c View
@@ -186,14 +186,13 @@ void win_open(win_t *win)
186186 int c, i, j, n;
187187 win_env_t *e;
188188 XClassHint classhint;
189− XSetWindowAttributes attr;
190− unsigned long attr_mask;
191189 unsigned long *icon_data;
192190 XColor col;
193191 char none_data[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
194192 Pixmap none;
195193 int gmask;
196194 XSizeHints sizehints;
195+ Bool fullscreen = options->fullscreen && fs_support;
197196
198197 if (win == NULL)
199198 return;
@@ -237,18 +236,15 @@ void win_open(win_t *win)
237236 win->y = 0;
238237 }
239238
240− attr.background_pixel = win->bgcol;
241− attr_mask = CWBackPixel;
242−
243239 win->xwin = XCreateWindow(e->dpy, RootWindow(e->dpy, e->scr),
244240 win->x, win->y, win->w, win->h, 0,
245− e->depth, InputOutput, e->vis, attr_mask, &attr);
241+ e->depth, InputOutput, e->vis, 0, NULL);
246242 if (win->xwin == None)
247243 die("could not create window");
248244
249245 XSelectInput(e->dpy, win->xwin,
250− ExposureMask | ButtonReleaseMask | ButtonPressMask |
251− KeyPressMask | PointerMotionMask | StructureNotifyMask);
246+ ButtonReleaseMask | ButtonPressMask | KeyPressMask |
247+ PointerMotionMask | StructureNotifyMask);
252248
253249 carrow = XCreateFontCursor(e->dpy, XC_left_ptr);
254250 chand = XCreateFontCursor(e->dpy, XC_fleur);
@@ -299,10 +295,18 @@ void win_open(win_t *win)
299295
300296 win->h -= win->bar.h;
301297
298+ win->buf.w = e->scrw;
299+ win->buf.h = e->scrh;
300+ win->buf.pm = XCreatePixmap(e->dpy, win->xwin,
301+ win->buf.w, win->buf.h, e->depth);
302+ XSetForeground(e->dpy, gc, fullscreen ? win->fscol : win->bgcol);
303+ XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h);
304+ XSetWindowBackgroundPixmap(e->dpy, win->xwin, win->buf.pm);
305+
302306 XMapWindow(e->dpy, win->xwin);
303307 XFlush(e->dpy);
304308
305− if (options->fullscreen)
309+ if (fullscreen)
306310 win_toggle_fullscreen(win);
307311 }
308312
@@ -329,12 +333,7 @@ bool win_configure(win_t *win, XConfigureEvent *c)
329333 if (win == NULL || c == NULL)
330334 return false;
331335
332− if ((changed = win->w != c->width || win->h + win->bar.h != c->height)) {
333− if (win->pm != None) {
334− XFreePixmap(win->env.dpy, win->pm);
335− win->pm = None;
336− }
337− }
336+ changed = win->w != c->width || win->h + win->bar.h != c->height;
338337
339338 win->x = c->x;
340339 win->y = c->y;
@@ -345,15 +344,6 @@ bool win_configure(win_t *win, XConfigureEvent *c)
345344 return changed;
346345 }
347346
348−void win_expose(win_t *win, XExposeEvent *e)
349−{
350− if (win == NULL || win->xwin == None || win->pm == None || e == NULL)
351− return;
352−
353− XCopyArea(win->env.dpy, win->pm, win->xwin, gc,
354− e->x, e->y, e->width, e->height, e->x, e->y);
355−}
356−
357347 void win_toggle_fullscreen(win_t *win)
358348 {
359349 XEvent ev;
@@ -402,20 +392,22 @@ void win_toggle_bar(win_t *win)
402392
403393 void win_clear(win_t *win)
404394 {
405− int h;
406395 win_env_t *e;
407396
408397 if (win == NULL || win->xwin == None)
409398 return;
410399
411− h = win->h + win->bar.h;
412400 e = &win->env;
413401
414− if (win->pm == None)
415− win->pm = XCreatePixmap(e->dpy, win->xwin, win->w, h, e->depth);
416−
402+ if (win->w > win->buf.w || win->h + win->bar.h > win->buf.h) {
403+ XFreePixmap(e->dpy, win->buf.pm);
404+ win->buf.w = MAX(win->buf.w, win->w);
405+ win->buf.h = MAX(win->buf.h, win->h + win->bar.h);
406+ win->buf.pm = XCreatePixmap(e->dpy, win->xwin,
407+ win->buf.w, win->buf.h, e->depth);
408+ }
417409 XSetForeground(e->dpy, gc, win->fullscreen ? win->fscol : win->bgcol);
418− XFillRectangle(e->dpy, win->pm, gc, 0, 0, win->w, h);
410+ XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h);
419411 }
420412
421413 void win_draw_bar(win_t *win)
@@ -425,7 +417,7 @@ void win_draw_bar(win_t *win)
425417 const char *dots = "...";
426418 win_env_t *e;
427419
428− if (win == NULL || win->xwin == None || win->pm == None)
420+ if (win == NULL || win->xwin == None)
429421 return;
430422
431423 e = &win->env;
@@ -433,7 +425,7 @@ void win_draw_bar(win_t *win)
433425 w = win->w;
434426
435427 XSetForeground(e->dpy, gc, win->bar.bgcol);
436− XFillRectangle(e->dpy, win->pm, gc, 0, win->h, win->w, win->bar.h);
428+ XFillRectangle(e->dpy, win->buf.pm, gc, 0, win->h, win->w, win->bar.h);
437429
438430 XSetForeground(e->dpy, gc, win->bar.fgcol);
439431 XSetBackground(e->dpy, gc, win->bar.bgcol);
@@ -444,9 +436,9 @@ void win_draw_bar(win_t *win)
444436 x = win->w - tw + H_TEXT_PAD;
445437 w -= tw;
446438 if (font.set)
447− XmbDrawString(e->dpy, win->pm, font.set, gc, x, y, win->bar.r, len);
439+ XmbDrawString(e->dpy, win->buf.pm, font.set, gc, x, y, win->bar.r, len);
448440 else
449− XDrawString(e->dpy, win->pm, gc, x, y, win->bar.r, len);
441+ XDrawString(e->dpy, win->buf.pm, gc, x, y, win->bar.r, len);
450442 }
451443 if ((len = strlen(win->bar.l)) > 0) {
452444 olen = len;
@@ -462,9 +454,9 @@ void win_draw_bar(win_t *win)
462454 }
463455 x = H_TEXT_PAD;
464456 if (font.set)
465− XmbDrawString(e->dpy, win->pm, font.set, gc, x, y, win->bar.l, len);
457+ XmbDrawString(e->dpy, win->buf.pm, font.set, gc, x, y, win->bar.l, len);
466458 else
467− XDrawString(e->dpy, win->pm, gc, x, y, win->bar.l, len);
459+ XDrawString(e->dpy, win->buf.pm, gc, x, y, win->bar.l, len);
468460 if (len != olen)
469461 memcpy(win->bar.l + len - w, rest, w);
470462 }
@@ -473,14 +465,14 @@ void win_draw_bar(win_t *win)
473465
474466 void win_draw(win_t *win)
475467 {
476− if (win == NULL || win->xwin == None || win->pm == None)
468+ if (win == NULL || win->xwin == None)
477469 return;
478470
479471 if (win->bar.h > 0)
480472 win_draw_bar(win);
481473
482− XCopyArea(win->env.dpy, win->pm, win->xwin, gc,
483− 0, 0, win->w, win->h + win->bar.h, 0, 0);
474+ XSetWindowBackgroundPixmap(win->env.dpy, win->xwin, win->buf.pm);
475+ XClearWindow(win->env.dpy, win->xwin);
484476 XFlush(win->env.dpy);
485477 }
486478
@@ -502,19 +494,6 @@ void win_draw_rect(win_t *win, Pixmap pm, int x, int y, int w, int h,
502494 XDrawRectangle(win->env.dpy, pm, gc, x, y, w, h);
503495 }
504496
505−void win_update_bar(win_t *win)
506−{
507− if (win == NULL || win->xwin == None || win->pm == None)
508− return;
509−
510− if (win->bar.h > 0) {
511− win_draw_bar(win);
512− XCopyArea(win->env.dpy, win->pm, win->xwin, gc,
513− 0, win->h, win->w, win->bar.h, 0, win->h);
514− XFlush(win->env.dpy);
515− }
516−}
517−
518497 int win_textwidth(const char *text, unsigned int len, bool with_padding)
519498 {
520499 XRectangle r;
M window.h View
@@ -56,7 +56,6 @@ typedef struct {
5656 unsigned long bgcol;
5757 unsigned long fscol;
5858 unsigned long selcol;
59− Pixmap pm;
6059
6160 int x;
6261 int y;
@@ -66,6 +65,12 @@ typedef struct {
6665
6766 bool fullscreen;
6867
68+ struct {
69+ int w;
70+ int h;
71+ Pixmap pm;
72+ } buf;
73+
6974 struct {
7075 unsigned int h;
7176 char l[BAR_L_LEN];
@@ -82,7 +87,6 @@ void win_open(win_t*);
8287 void win_close(win_t*);
8388
8489 bool win_configure(win_t*, XConfigureEvent*);
85−void win_expose(win_t*, XExposeEvent*);
8690
8791 void win_toggle_fullscreen(win_t*);
8892 void win_toggle_bar(win_t*);
@@ -92,8 +96,6 @@ void win_draw(win_t*);
9296 void win_draw_rect(win_t*, Pixmap, int, int, int, int, bool, int,
9397 unsigned long);
9498
95−void win_update_bar(win_t*);
96−
9799 int win_textwidth(const char*, unsigned int, bool);
98100
99101 void win_set_title(win_t*, const char*);