]> git.mdlowis.com Git - projs/tide.git/commitdiff
refactored window redrawing code
authorMichael D. Lowis <mike.lowis@gentex.com>
Thu, 9 May 2019 01:20:08 +0000 (21:20 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Thu, 9 May 2019 01:20:08 +0000 (21:20 -0400)
inc/win.h
inc/x11.h
src/lib/x11.c
src/lib/x11_gc.c
src/tframe.c
src/tide.c

index 28a718431c04ec00aa0cee9b1e7700a0c0aa24b7..e8b74f35452d1d19eb426a078fa29326e34c0f85 100644 (file)
--- 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,
index effc431e50e95dee8d8faedfec02f52f9f5dc612..90901e3df86324ee27e0efcc31ad946e6ba4a098 100644 (file)
--- 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);
index daebeed289406ad973947603e3cff8bf90124745..e56b48094cc235c1ef854aa8c26e943544a5f4dc 100644 (file)
@@ -1,4 +1,5 @@
 #include <x11.h>
+#include <utf.h>
 #include <locale.h>
 #include <signal.h>
 #include <sys/types.h>
@@ -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);
 }
-
-
index b08ef0979d678a17a2e7d21dc8ae91417ebc74f1..90e56102c20452d4cad8fabf4b16233ecc6ed52a 100644 (file)
@@ -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);
     }
 }
 
index 20b6df007e858688173b876ca2027563a12eab5c..67419ae8eb5dfd7cbff5fccdc0d6264d163f284e 100644 (file)
@@ -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) {
index 0676171623d854f4f5c63738e1851c324468accd..2a0f2fba9dc090cc2b3f52937d7101a900a5b1e6 100644 (file)
@@ -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) {