From 0a5e4bee05a77fb9cc3e35608c4a0ea510e531c1 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Wed, 8 May 2019 21:20:08 -0400 Subject: [PATCH] refactored window redrawing code --- inc/win.h | 72 ------------------------------------------ inc/x11.h | 76 +++++++++++++++++++++++++++++++++++++++++++- src/lib/x11.c | 54 +++++++++++++++++++++++++++---- src/lib/x11_gc.c | 3 +- src/tframe.c | 80 +++++++++++++++++++++++++++------------------- src/tide.c | 82 +++++++++++++----------------------------------- 6 files changed, 193 insertions(+), 174 deletions(-) diff --git a/inc/win.h b/inc/win.h index 28a7184..e8b74f3 100644 --- a/inc/win.h +++ b/inc/win.h @@ -12,78 +12,6 @@ typedef struct { short y; } XGlyphSpec; -/* key definitions */ -enum Keys { - /* Define some runes in the private use area of unicode to represent - * special keys */ - KEY_F1 = (0xE000+0), - KEY_F2 = (0xE000+1), - KEY_F3 = (0xE000+2), - KEY_F4 = (0xE000+3), - KEY_F5 = (0xE000+4), - KEY_F6 = (0xE000+5), - KEY_F7 = (0xE000+6), - KEY_F8 = (0xE000+7), - KEY_F9 = (0xE000+8), - KEY_F10 = (0xE000+9), - KEY_F11 = (0xE000+10), - KEY_F12 = (0xE000+11), - KEY_INSERT = (0xE000+12), - KEY_DELETE = (0xE000+13), - KEY_HOME = (0xE000+14), - KEY_END = (0xE000+15), - KEY_PGUP = (0xE000+16), - KEY_PGDN = (0xE000+17), - KEY_UP = (0xE000+18), - KEY_DOWN = (0xE000+19), - KEY_RIGHT = (0xE000+20), - KEY_LEFT = (0xE000+21), - - /* ASCII Control Characters */ - KEY_CTRL_TILDE = 0x00, - KEY_CTRL_2 = 0x00, - KEY_CTRL_A = 0x01, - KEY_CTRL_B = 0x02, - KEY_CTRL_C = 0x03, - KEY_CTRL_D = 0x04, - KEY_CTRL_E = 0x05, - KEY_CTRL_F = 0x06, - KEY_CTRL_G = 0x07, - KEY_BACKSPACE = 0x08, - KEY_CTRL_H = 0x08, - KEY_TAB = 0x09, - KEY_CTRL_I = 0x09, - KEY_CTRL_J = 0x0A, - KEY_CTRL_K = 0x0B, - KEY_CTRL_L = 0x0C, - KEY_ENTER = 0x0D, - KEY_CTRL_M = 0x0D, - KEY_CTRL_N = 0x0E, - KEY_CTRL_O = 0x0F, - KEY_CTRL_P = 0x10, - KEY_CTRL_Q = 0x11, - KEY_CTRL_R = 0x12, - KEY_CTRL_S = 0x13, - KEY_CTRL_T = 0x14, - KEY_CTRL_U = 0x15, - KEY_CTRL_V = 0x16, - KEY_CTRL_W = 0x17, - KEY_CTRL_X = 0x18, - KEY_CTRL_Y = 0x19, - KEY_CTRL_Z = 0x1A, - KEY_ESCAPE = 0x1B, - KEY_CTRL_LSQ_BRACKET = 0x1B, - KEY_CTRL_3 = 0x1B, - KEY_CTRL_4 = 0x1C, - KEY_CTRL_BACKSLASH = 0x1C, - KEY_CTRL_5 = 0x1D, - KEY_CTRL_RSQ_BRACKET = 0x1D, - KEY_CTRL_6 = 0x1E, - KEY_CTRL_7 = 0x1F, - KEY_CTRL_SLASH = 0x1F, - KEY_CTRL_UNDERSCORE = 0x1F, -}; - /* Key modifier masks */ enum { ModNone = 0, diff --git a/inc/x11.h b/inc/x11.h index effc431..90901e3 100644 --- a/inc/x11.h +++ b/inc/x11.h @@ -31,15 +31,89 @@ enum { CLIPBOARD = 1 }; +/* key definitions */ +enum Keys { + /* Define some runes in the private use area of unicode to represent + * special keys */ + KEY_F1 = (0xE000+0), + KEY_F2 = (0xE000+1), + KEY_F3 = (0xE000+2), + KEY_F4 = (0xE000+3), + KEY_F5 = (0xE000+4), + KEY_F6 = (0xE000+5), + KEY_F7 = (0xE000+6), + KEY_F8 = (0xE000+7), + KEY_F9 = (0xE000+8), + KEY_F10 = (0xE000+9), + KEY_F11 = (0xE000+10), + KEY_F12 = (0xE000+11), + KEY_INSERT = (0xE000+12), + KEY_DELETE = (0xE000+13), + KEY_HOME = (0xE000+14), + KEY_END = (0xE000+15), + KEY_PGUP = (0xE000+16), + KEY_PGDN = (0xE000+17), + KEY_UP = (0xE000+18), + KEY_DOWN = (0xE000+19), + KEY_RIGHT = (0xE000+20), + KEY_LEFT = (0xE000+21), + + /* ASCII Control Characters */ + KEY_CTRL_TILDE = 0x00, + KEY_CTRL_2 = 0x00, + KEY_CTRL_A = 0x01, + KEY_CTRL_B = 0x02, + KEY_CTRL_C = 0x03, + KEY_CTRL_D = 0x04, + KEY_CTRL_E = 0x05, + KEY_CTRL_F = 0x06, + KEY_CTRL_G = 0x07, + KEY_BACKSPACE = 0x08, + KEY_CTRL_H = 0x08, + KEY_TAB = 0x09, + KEY_CTRL_I = 0x09, + KEY_CTRL_J = 0x0A, + KEY_CTRL_K = 0x0B, + KEY_CTRL_L = 0x0C, + KEY_ENTER = 0x0D, + KEY_CTRL_M = 0x0D, + KEY_CTRL_N = 0x0E, + KEY_CTRL_O = 0x0F, + KEY_CTRL_P = 0x10, + KEY_CTRL_Q = 0x11, + KEY_CTRL_R = 0x12, + KEY_CTRL_S = 0x13, + KEY_CTRL_T = 0x14, + KEY_CTRL_U = 0x15, + KEY_CTRL_V = 0x16, + KEY_CTRL_W = 0x17, + KEY_CTRL_X = 0x18, + KEY_CTRL_Y = 0x19, + KEY_CTRL_Z = 0x1A, + KEY_ESCAPE = 0x1B, + KEY_CTRL_LSQ_BRACKET = 0x1B, + KEY_CTRL_3 = 0x1B, + KEY_CTRL_4 = 0x1C, + KEY_CTRL_BACKSLASH = 0x1C, + KEY_CTRL_5 = 0x1D, + KEY_CTRL_RSQ_BRACKET = 0x1D, + KEY_CTRL_6 = 0x1E, + KEY_CTRL_7 = 0x1F, + KEY_CTRL_SLASH = 0x1F, + KEY_CTRL_UNDERSCORE = 0x1F, +}; + + int x11_init(XConf* x); void x11_error_clear(void); XErrorEvent* x11_error_get(void); void x11_mkwin(XConf* x, int width, int height, int evmask); void x11_mkdialog(XConf* x, int width, int height, int evmask); +int x11_process_events(XConf* x); void x11_event_loop(XConf* x, void (*redraw)(XConf* x)); int x11_getptr(XConf* x, int* ptrx, int* ptry); -KeySym x11_getkey(XConf* x, XEvent* e); +uint32_t x11_getkey(XConf* x, XEvent* e); void x11_centerwin(XConf* x); void x11_init_gc(XConf* x); diff --git a/src/lib/x11.c b/src/lib/x11.c index daebeed..e56b480 100644 --- a/src/lib/x11.c +++ b/src/lib/x11.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -53,9 +54,9 @@ void x11_mkwin(XConf* x, int width, int height, int evmask) { /* setup window attributes and events */ XSetWindowAttributes swa; swa.bit_gravity = NorthWestGravity; - swa.do_not_propagate_mask = 0; // do not hide any events from child window + swa.do_not_propagate_mask = 0; /* do not hide any events from child windows */ XChangeWindowAttributes(x->display, x->self, - CWBackingStore|CWBitGravity|CWEventMask|NoEventMask|CWBackPixel, + CWBackPixel|CWBorderPixel|CWBitGravity|CWEventMask|CWColormap, &swa); XSelectInput(x->display, x->self, evmask); } @@ -67,6 +68,25 @@ void x11_mkdialog(XConf* x, int width, int height, int evmask) { XChangeProperty(x->display, x->self, WindowType, XA_ATOM, 32, PropModeReplace, (unsigned char*)&DialogType, 1); } +int x11_process_events(XConf* x) { + int nqueued, nevents, dirty = false; + /* reap zombie background processes */ + for (int status; waitpid(-1, &status, WNOHANG) > 0;); + /* process the entire event queue */ + do { + nqueued = XEventsQueued(x->display, QueuedAfterFlush); + XGetMotionEvents(x->display, x->self, CurrentTime, CurrentTime, &nevents); + for (XEvent e; XPending(x->display);) { + XNextEvent(x->display, &e); + if (e.type == Expose) dirty = 1; + if (!XFilterEvent(&e, None) && x->eventfns[e.type]) + (x->eventfns[e.type])(x, &e); + } + dirty = dirty || nqueued; + } while ((nqueued = XEventsQueued(x->display, QueuedAfterFlush)) > 0); + return dirty; +} + void x11_event_loop(XConf* x, void (*redraw)(XConf* x)) { if (redraw) redraw(x); for (XEvent e; x->running;) { @@ -84,7 +104,27 @@ int x11_getptr(XConf* x, int* ptrx, int* ptry) { return XQueryPointer(x->display, x->self, &root, &child, ptrx, ptry, &winx, &winy, (unsigned int*)&mask); } -KeySym x11_getkey(XConf* x, XEvent* e) { +static uint32_t special_keys(uint32_t key) { + static uint32_t keymap[256] = { + /* Function keys */ + [0xBE] = KEY_F1, [0xBF] = KEY_F2, [0xC0] = KEY_F3, [0xC1] = KEY_F4, + [0xC2] = KEY_F5, [0xC3] = KEY_F6, [0xC4] = KEY_F7, [0xC5] = KEY_F8, + [0xC6] = KEY_F9, [0xC7] = KEY_F10, [0xC8] = KEY_F11, [0xC9] = KEY_F12, + /* Navigation keys */ + [0x50] = KEY_HOME, [0x51] = KEY_LEFT, [0x52] = KEY_UP, + [0x53] = KEY_RIGHT, [0x54] = KEY_DOWN, [0x55] = KEY_PGUP, + [0x56] = KEY_PGDN, [0x57] = KEY_END, + /* Control keys */ + [0x08] = '\b', [0x09] = '\t', [0x0d] = '\n', [0x0a] = '\n', + /* Miscellaneous */ + [0x63] = KEY_INSERT, [0x1B] = KEY_ESCAPE, [0xFF] = KEY_DELETE, + }; + /* lookup the key by keysym */ + key = ((key & 0xFF00) == 0xFF00 ? keymap[key & 0xFF] : key); + return (!key ? RUNE_ERR : key); +} + +uint32_t x11_getkey(XConf* x, XEvent* e) { char buf[8]; KeySym key; Status status; @@ -93,7 +133,9 @@ KeySym x11_getkey(XConf* x, XEvent* e) { Xutf8LookupString(x->xic, &(e->xkey), buf, sizeof(buf), &key, &status); else XLookupString(&(e->xkey), buf, sizeof(buf), &key, 0); - return key; + /* if it's ascii, just return it */ + if (key >= 0x20 && key <= 0x7F) + return (uint32_t)key; + /* translate special key codes into unicode codepoints */ + return special_keys(key); } - - diff --git a/src/lib/x11_gc.c b/src/lib/x11_gc.c index b08ef09..90e5610 100644 --- a/src/lib/x11_gc.c +++ b/src/lib/x11_gc.c @@ -10,8 +10,9 @@ static void xresize(XConf* x, XEvent* e) { if (e->xconfigure.width != x->width || e->xconfigure.height != x->height) { x->width = e->xconfigure.width; x->height = e->xconfigure.height; + XFreePixmap(x->display, x->pixmap); x->pixmap = XCreatePixmap(x->display, x->self, x->width, x->height, x->depth); - x->xft = XftDrawCreate(x->display, x->pixmap, x->visual, x->colormap); + XftDrawChange(x->xft, x->pixmap); } } diff --git a/src/tframe.c b/src/tframe.c index 20b6df0..67419ae 100644 --- a/src/tframe.c +++ b/src/tframe.c @@ -17,7 +17,7 @@ static int FontSel; Window Child = 0; int retile = 0; -/* X11 Window Code +/* X11 Font Code ******************************************************************************/ static void font_load(char* name) { XftFont* font = x11_font_load(&X, name); @@ -35,6 +35,8 @@ size_t glyph_width(View* view, int c) { return extents.xOff; } +/* X11 Event Code + ******************************************************************************/ static void xmaprequest(XConf* x, XEvent* e) { (void)x; XMapWindow(e->xmaprequest.display, e->xmaprequest.window); @@ -63,37 +65,49 @@ static void xexpose(XConf* x, XEvent* e) { retile = 1; } +static void xkeypress(XConf* x, XEvent* e) { + uint32_t key = x11_getkey(x, e); + if (key == RUNE_ERR) return; +// int mods = e->xkey.state & (ModCtrl|ModShift|ModAlt); +// int32_t mkey = tolower(key); +// for (KeyBinding* bind = Keys; bind && bind->key; bind++) { +// bool match = (mkey == bind->key); +// bool exact = (bind->mods == mods); +// bool any = (bind->mods == ModAny); +// bool oneplus = ((bind->mods == ModOneOrMore) && (mods & ModOneOrMore)); +// if (match && (exact || oneplus || any)) { +// bind->fn(bind->arg); +// return; +// } +// } + /* fallback to just inserting the rune if it doesn't fall in the private use area. + * the private use area is used to encode special keys */ + if (key < 0xE000 || key > 0xF8FF) + view_insert(&Tags, key); +} + +/* X11 Drawing Code + ******************************************************************************/ static void xupdate(Job* job) { - int nqueued, nevents; - do { - nqueued = XEventsQueued(X.display, QueuedAfterFlush); - XGetMotionEvents(X.display, X.self, CurrentTime, CurrentTime, &nevents); - for (XEvent e; XPending(X.display);) { - XNextEvent(X.display, &e); - if (!XFilterEvent(&e, None) && X.eventfns[e.type]) - (X.eventfns[e.type])(&X, &e); - for (int status; waitpid(-1, &status, WNOHANG) > 0;); - } - if (nqueued || !job) { - /* determine the size of the regions */ - size_t maxtagrows = ((X.height/4) / X.font->height); - size_t tagrows = view_limitrows(&Tags, maxtagrows); - /* draw the regions to the window */ - drawcsr csr = { .w = X.width, .h = X.height }; - csr.x += ScrollWidth + 1; - draw_statbox(&X, NORMAL); - draw_view(&X, &Tags, X.font, tagrows, &csr, TagsBg, TagsFg, TagsSel, false); - int prev_div = Divider; - Divider = draw_hrule(&X, &csr); - draw_rect(&X, EditBg, 0, Divider+2, csr.w, csr.h); - XCopyArea(X.display, X.pixmap, X.self, X.gc, 0, 0, X.width, X.height, 0, 0); - if ((retile || prev_div != Divider) && Child) { - XMoveResizeWindow(X.display, Child, -1, Divider, X.width, X.height - Divider); - retile = 0; - } - XFlush(X.display); - } - } while ((nqueued = XEventsQueued(X.display, QueuedAfterFlush)) > 0); + /* redraw if we have changes */ + if (!x11_process_events(&X) && job) return; + /* determine the size of the regions */ + size_t maxtagrows = ((X.height/4) / X.font->height); + size_t tagrows = view_limitrows(&Tags, maxtagrows); + /* draw the regions to the window */ + drawcsr csr = { .w = X.width, .h = X.height }; + csr.x += ScrollWidth + 1; + draw_statbox(&X, NORMAL); + draw_view(&X, &Tags, X.font, tagrows, &csr, TagsBg, TagsFg, TagsSel, false); + int prev_div = Divider; + Divider = draw_hrule(&X, &csr); + draw_rect(&X, EditBg, 0, Divider+2, csr.w, csr.h); + XCopyArea(X.display, X.pixmap, X.self, X.gc, 0, 0, X.width, X.height, 0, 0); + if ((retile || prev_div != Divider) && Child) { + XMoveResizeWindow(X.display, Child, -1, Divider, X.width, X.height - Divider); + retile = 0; + } + XFlush(X.display); } void win_init(KeyBinding* bindings) { @@ -111,7 +125,7 @@ void win_init(KeyBinding* bindings) { } x11_mkwin(&X, 640, 480, 0 // | FocusChangeMask -// | KeyPressMask + | KeyPressMask // | ButtonPressMask // | ButtonReleaseMask // | ButtonMotionMask @@ -128,7 +142,6 @@ void win_init(KeyBinding* bindings) { x11_show(&X); /* register event handlers */ -// X.eventfns[KeyPress] = xkeypress; // X.eventfns[ButtonPress] = xbtnpress; // X.eventfns[ButtonRelease] = xbtnrelease; // X.eventfns[MotionNotify] = xbtnmotion; @@ -136,6 +149,7 @@ void win_init(KeyBinding* bindings) { X.eventfns[ConfigureNotify] = xconfigure; X.eventfns[ClientMessage] = xclientmsg; X.eventfns[Expose] = xexpose; + X.eventfns[KeyPress] = xkeypress; } void win_loop(void) { diff --git a/src/tide.c b/src/tide.c index 0676171..2a0f2fb 100644 --- a/src/tide.c +++ b/src/tide.c @@ -86,35 +86,6 @@ static void tide_send(char* type) { } } -static uint32_t special_keys(uint32_t key) { - static uint32_t keymap[256] = { - /* Function keys */ - [0xBE] = KEY_F1, [0xBF] = KEY_F2, [0xC0] = KEY_F3, [0xC1] = KEY_F4, - [0xC2] = KEY_F5, [0xC3] = KEY_F6, [0xC4] = KEY_F7, [0xC5] = KEY_F8, - [0xC6] = KEY_F9, [0xC7] = KEY_F10, [0xC8] = KEY_F11, [0xC9] = KEY_F12, - /* Navigation keys */ - [0x50] = KEY_HOME, [0x51] = KEY_LEFT, [0x52] = KEY_UP, - [0x53] = KEY_RIGHT, [0x54] = KEY_DOWN, [0x55] = KEY_PGUP, - [0x56] = KEY_PGDN, [0x57] = KEY_END, - /* Control keys */ - [0x08] = '\b', [0x09] = '\t', [0x0d] = '\n', [0x0a] = '\n', - /* Miscellaneous */ - [0x63] = KEY_INSERT, [0x1B] = KEY_ESCAPE, [0xFF] = KEY_DELETE, - }; - /* lookup the key by keysym */ - key = ((key & 0xFF00) == 0xFF00 ? keymap[key & 0xFF] : key); - return (!key ? RUNE_ERR : key); -} - -static uint32_t getkey(XConf* x, XEvent* e) { - KeySym key = x11_getkey(x, e); - /* if it's ascii, just return it */ - if (key >= 0x20 && key <= 0x7F) - return (uint32_t)key; - /* translate special key codes into unicode codepoints */ - return special_keys(key); -} - static void mouse_left(WinRegion id, bool pressed, size_t row, size_t col) { static int count = 0; static Time before = 0; @@ -204,7 +175,7 @@ static void xkeypress(XConf* x, XEvent* e) { (void)x; Now = e->xkey.time; Focused = (e->xkey.y <= Divider ? TAGS : EDIT); - uint32_t key = getkey(x, e); + uint32_t key = x11_getkey(x, e); if (key == RUNE_ERR) return; KeyBtnState = e->xkey.state; int mods = KeyBtnState & (ModCtrl|ModShift|ModAlt); @@ -258,37 +229,26 @@ static void xclientmsg(XConf* x, XEvent* e) { } static void xupdate(Job* job) { - int nqueued, nevents; - do { - nqueued = XEventsQueued(X.display, QueuedAfterFlush); - XGetMotionEvents(X.display, X.self, CurrentTime, CurrentTime, &nevents); - for (XEvent e; XPending(X.display);) { - XNextEvent(X.display, &e); - if (!XFilterEvent(&e, None) && X.eventfns[e.type]) - (X.eventfns[e.type])(&X, &e); - for (int status; waitpid(-1, &status, WNOHANG) > 0;); - } - if (nqueued || !job) { - /* force update the title */ - win_title(NULL); - /* determine the size of the regions */ - size_t maxtagrows = ((X.height/4) / X.tagfont->height); - size_t tagrows = view_limitrows(win_view(TAGS), maxtagrows); - size_t tagregsz = (tagrows * X.tagfont->height) + 7; - size_t editrows = (X.height - tagregsz) / X.font->height ; - /* draw the regions to the window */ - drawcsr csr = { .w = X.width, .h = X.height }; - csr.x += ScrollWidth + 1; - draw_statbox(&X, win_view(EDIT)->buffer.status); - draw_view(&X, &Regions[TAGS], X.tagfont, tagrows, &csr, TagsBg, TagsFg, TagsSel, false); - Divider = draw_hrule(&X, &csr); - draw_view(&X, &Regions[EDIT], X.font, editrows, &csr, EditBg, EditFg, EditSel, SyncMouse); - draw_scroll(&X, &csr, win_view(EDIT), Divider); - XCopyArea(X.display, X.pixmap, X.self, X.gc, 0, 0, X.width, X.height, 0, 0); - SyncMouse = false; - XFlush(X.display); - } - } while ((nqueued = XEventsQueued(X.display, QueuedAfterFlush)) > 0); + /* redraw if we have changes */ + if (!x11_process_events(&X) && job) return; + /* force update the title */ + win_title(NULL); + /* determine the size of the regions */ + size_t maxtagrows = ((X.height/4) / X.tagfont->height); + size_t tagrows = view_limitrows(win_view(TAGS), maxtagrows); + size_t tagregsz = (tagrows * X.tagfont->height) + 7; + size_t editrows = (X.height - tagregsz) / X.font->height ; + /* draw the regions to the window */ + drawcsr csr = { .w = X.width, .h = X.height }; + csr.x += ScrollWidth + 1; + draw_statbox(&X, win_view(EDIT)->buffer.status); + draw_view(&X, &Regions[TAGS], X.tagfont, tagrows, &csr, TagsBg, TagsFg, TagsSel, false); + Divider = draw_hrule(&X, &csr); + draw_view(&X, &Regions[EDIT], X.font, editrows, &csr, EditBg, EditFg, EditSel, SyncMouse); + draw_scroll(&X, &csr, win_view(EDIT), Divider); + XCopyArea(X.display, X.pixmap, X.self, X.gc, 0, 0, X.width, X.height, 0, 0); + SyncMouse = false; + XFlush(X.display); } void win_init(KeyBinding* bindings) { -- 2.49.0