From 4a5d5d26aa8c66ef9c4e64cc355c63888b04d4e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bert=20M=C3=BCnnich?= Date: Mon, 29 Oct 2012 18:25:17 +0100 Subject: [PATCH 1/2] Overhauled window drawing - Draw onto pixmap as before, but use the same size for the pixmap as for the window, allocate new pixmap after configure requests - Use XCopyArea() instead of XSetWindowBackgroundPixmap(), which now requires handling of Expose events --- main.c | 24 ++++++++++++++++++------ window.c | 39 ++++++++++++++++++++++++++++----------- window.h | 1 + 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/main.c b/main.c index f6d09f5..848d1a4 100644 --- a/main.c +++ b/main.c @@ -420,7 +420,7 @@ void run(void) { fd_set fds; struct timeval timeout; XEvent ev, nextev; - unsigned int qlen; + bool discard; redraw(); @@ -453,10 +453,20 @@ void run(void) { do { XNextEvent(win.env.dpy, &ev); - qlen = XEventsQueued(win.env.dpy, QueuedAlready); - if (qlen > 0) + discard = false; + if (XEventsQueued(win.env.dpy, QueuedAlready) > 0) { XPeekEvent(win.env.dpy, &nextev); - } while (qlen > 0 && ev.type == nextev.type); + switch (ev.type) { + case ConfigureNotify: + discard = ev.type == nextev.type; + break; + case KeyPress: + discard = (nextev.type == KeyPress || nextev.type == KeyRelease) + && ev.xkey.keycode == nextev.xkey.keycode; + break; + } + } + } while (discard); switch (ev.type) { /* handle events */ @@ -482,9 +492,11 @@ void run(void) { } } break; + case Expose: + win_expose(&win, &ev.xexpose); + break; case KeyPress: - if (qlen == 0 || ev.xkey.keycode != nextev.xkey.keycode) - on_keypress(&ev.xkey); + on_keypress(&ev.xkey); break; case MotionNotify: if (mode == MODE_IMAGE) { diff --git a/window.c b/window.c index 0d86925..71a7915 100644 --- a/window.c +++ b/window.c @@ -188,8 +188,9 @@ void win_open(win_t *win) { if (win->xwin == None) die("could not create window"); - XSelectInput(e->dpy, win->xwin, StructureNotifyMask | KeyPressMask | - ButtonPressMask | ButtonReleaseMask | PointerMotionMask); + XSelectInput(e->dpy, win->xwin, + ExposureMask | ButtonReleaseMask | ButtonPressMask | + KeyPressMask | PointerMotionMask | StructureNotifyMask); carrow = XCreateFontCursor(e->dpy, XC_left_ptr); chand = XCreateFontCursor(e->dpy, XC_fleur); @@ -246,10 +247,15 @@ void win_close(win_t *win) { bool win_configure(win_t *win, XConfigureEvent *c) { bool changed; - if (win == NULL) + if (win == NULL || c == NULL) return false; - changed = win->w != c->width || win->h + win->barh != c->height; + if ((changed = win->w != c->width || win->h + win->barh != c->height)) { + if (win->pm != None) { + XFreePixmap(win->env.dpy, win->pm); + win->pm = None; + } + } win->x = c->x; win->y = c->y; @@ -260,6 +266,15 @@ bool win_configure(win_t *win, XConfigureEvent *c) { return changed; } +void win_expose(win_t *win, XExposeEvent *e) { + if (win == NULL || win->xwin == None || e == NULL) + return; + + if (win->pm != None) + XCopyArea(win->env.dpy, win->pm, win->xwin, gc, + e->x, e->y, e->width, e->height, e->x, e->y); +} + bool win_moveresize(win_t *win, int x, int y, unsigned int w, unsigned int h) { if (win == NULL || win->xwin == None) return false; @@ -323,19 +338,20 @@ 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->barh; e = &win->env; - if (win->pm != None) - XFreePixmap(e->dpy, win->pm); - win->pm = XCreatePixmap(e->dpy, win->xwin, e->scrw, e->scrh, e->depth); + if (win->pm == None) + win->pm = XCreatePixmap(e->dpy, win->xwin, win->w, h, e->depth); XSetForeground(e->dpy, gc, win->fullscreen ? win->fscol : win->bgcol); - XFillRectangle(e->dpy, win->pm, gc, 0, 0, e->scrw, e->scrh); + XFillRectangle(e->dpy, win->pm, gc, 0, 0, win->w, h); } void win_draw_bar(win_t *win) { @@ -397,12 +413,13 @@ void win_draw(win_t *win) { if (win->barh > 0) win_draw_bar(win); - XSetWindowBackgroundPixmap(win->env.dpy, win->xwin, win->pm); - XClearWindow(win->env.dpy, win->xwin); + XCopyArea(win->env.dpy, win->pm, win->xwin, gc, + 0, 0, win->w, win->h + win->barh, 0, 0); } void win_draw_rect(win_t *win, Pixmap pm, int x, int y, int w, int h, - bool fill, int lw, unsigned long col) { + bool fill, int lw, unsigned long col) +{ XGCValues gcval; if (win == NULL || pm == None) diff --git a/window.h b/window.h index c3948cd..5e033e3 100644 --- a/window.h +++ b/window.h @@ -66,6 +66,7 @@ void win_open(win_t*); void win_close(win_t*); bool win_configure(win_t*, XConfigureEvent*); +void win_expose(win_t*, XExposeEvent*); bool win_moveresize(win_t*, int, int, unsigned int, unsigned int); void win_toggle_fullscreen(win_t*); From 22a8b665716edab993ce09008d0fb541498d633b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bert=20M=C3=BCnnich?= Date: Mon, 29 Oct 2012 23:23:50 +0100 Subject: [PATCH 2/2] Fixed BadDrawable errors caused by invalid window pixmap --- window.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/window.c b/window.c index 71a7915..b9970a6 100644 --- a/window.c +++ b/window.c @@ -267,12 +267,11 @@ bool win_configure(win_t *win, XConfigureEvent *c) { } void win_expose(win_t *win, XExposeEvent *e) { - if (win == NULL || win->xwin == None || e == NULL) + if (win == NULL || win->xwin == None || win->pm == None || e == NULL) return; - if (win->pm != None) - XCopyArea(win->env.dpy, win->pm, win->xwin, gc, - e->x, e->y, e->width, e->height, e->x, e->y); + XCopyArea(win->env.dpy, win->pm, win->xwin, gc, + e->x, e->y, e->width, e->height, e->x, e->y); } bool win_moveresize(win_t *win, int x, int y, unsigned int w, unsigned int h) { @@ -359,7 +358,7 @@ void win_draw_bar(win_t *win) { int len, x, y, w, tw = 0, seplen; const char *rt; - if (win == NULL || win->xwin == None) + if (win == NULL || win->xwin == None || win->pm == None) return; e = &win->env; @@ -407,7 +406,7 @@ void win_draw_bar(win_t *win) { } void win_draw(win_t *win) { - if (win == NULL || win->xwin == None) + if (win == NULL || win->xwin == None || win->pm == None) return; if (win->barh > 0)