From d9354df713e3dc72da81ed8d4fae6f2994c32349 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Mon, 1 May 2017 20:14:51 -0400 Subject: [PATCH] Heavily reworked event loop. Hopefully the thrashing stops here... --- inc/win.h | 2 +- inc/x11.h | 25 ++++++++++++------ lib/win.c | 23 +++++++++++++--- lib/x11.c | 79 +++++++++++++++++++++++++++++++------------------------ xedit.c | 6 ++--- 5 files changed, 85 insertions(+), 50 deletions(-) diff --git a/inc/win.h b/inc/win.h index 1b0ce3d..586d781 100644 --- a/inc/win.h +++ b/inc/win.h @@ -45,7 +45,7 @@ Buf* win_buf(WinRegion id); Sel* win_sel(WinRegion id); bool win_btnpressed(MouseBtn btn); WinRegion win_getregion(void); -void win_setregion(WinRegion id); +bool win_setregion(WinRegion id); void win_setscroll(double offset, double visible); /* These functions must be implemented by any appliation that wishes diff --git a/inc/x11.h b/inc/x11.h index 124e8d5..9d04255 100644 --- a/inc/x11.h +++ b/inc/x11.h @@ -134,20 +134,29 @@ bool x11_keymodsset(int mask); void x11_window(char* name, int width, int height); void x11_dialog(char* name, int height, int width); void x11_show(void); -void x11_loop(void); -void x11_handle_events(void); +bool x11_running(void); +void x11_flip(void); +void x11_flush(void); +void x11_finish(void); + +bool x11_events_await(unsigned int ms); +void x11_events_take(void); + +void x11_mouse_get(int* x, int* y); +void x11_mouse_set(int x, int y); + XFont x11_font_load(char* name); size_t x11_font_height(XFont fnt); size_t x11_font_width(XFont fnt); size_t x11_font_descent(XFont fnt); -void x11_draw_rect(int color, int x, int y, int width, int height); -void x11_getsize(int* width, int* height); -void x11_warp_mouse(int x, int y); -void x11_draw_utf8(XFont font, int fg, int bg, int x, int y, char* str); void x11_font_getglyph(XFont font, XGlyphSpec* spec, uint32_t rune); size_t x11_font_getglyphs(XGlyphSpec* specs, const XGlyph* glyphs, int len, XFont font, int x, int y); + +void x11_draw_rect(int color, int x, int y, int width, int height); +void x11_draw_utf8(XFont font, int fg, int bg, int x, int y, char* str); void x11_draw_glyphs(int fg, int bg, XGlyphSpec* glyphs, size_t nglyphs); void x11_draw_utf8(XFont font, int fg, int bg, int x, int y, char* str); -bool x11_getsel(int selid, void(*cbfn)(char*)); -bool x11_setsel(int selid, char* str); + +bool x11_sel_get(int selid, void(*cbfn)(char*)); +bool x11_sel_set(int selid, char* str); diff --git a/lib/win.c b/lib/win.c index db1d76b..ca7d241 100644 --- a/lib/win.c +++ b/lib/win.c @@ -64,8 +64,20 @@ void win_dialog(char* name) { } void win_loop(void) { + int ptr_x, ptr_y; x11_show(); - x11_loop(); + while (x11_running()) { + bool pending = x11_events_await(200 /* ms */); + x11_flush(); + x11_mouse_get(&ptr_x, &ptr_y); + win_setregion(getregion(ptr_x, ptr_y)); + if (win_setregion(getregion(ptr_x, ptr_y)) || pending) { + x11_events_take(); + x11_flip(); + } + x11_flush(); + } + x11_finish(); } void win_settext(WinRegion id, char* text) { @@ -94,8 +106,11 @@ WinRegion win_getregion(void) { return Focused; } -void win_setregion(WinRegion id) { - Focused = id; +bool win_setregion(WinRegion id) { + bool changed = true; + if (id == TAGS || id == EDIT) + changed = true, Focused = id; + return changed; } void win_warpptr(WinRegion id) { @@ -211,7 +226,7 @@ static void onredraw(int width, int height) { Regions[Focused].warp_ptr = false; size_t x = Regions[Focused].x + (Regions[Focused].csrx * fwidth) - (fwidth/2); size_t y = Regions[Focused].y + (Regions[Focused].csry * fheight) + (fheight/2); - x11_warp_mouse(x,y); + x11_mouse_set(x, y); } } diff --git a/lib/x11.c b/lib/x11.c index c4c4759..90c8f44 100644 --- a/lib/x11.c +++ b/lib/x11.c @@ -9,7 +9,7 @@ #include #include -static struct XSel* selfetch(Atom atom); +static struct XSel* selfetch(Atom atom); static void selclear(XEvent* evnt); static void selnotify(XEvent* evnt); static void selrequest(XEvent* evnt); @@ -135,8 +135,8 @@ void x11_window(char* name, int width, int height) { | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask - | PointerMotionMask - | PointerMotionHintMask +// | PointerMotionMask +// | PointerMotionHintMask | KeyPressMask ); @@ -172,6 +172,28 @@ void x11_show(void) { XMapWindow(X.display, X.window); } +bool x11_running(void) { + return Running; +} + +void x11_flip(void) { + Config->redraw(X.width, X.height); + XCopyArea(X.display, X.pixmap, X.window, X.gc, 0, 0, X.width, X.height, 0, 0); +} + +void x11_flush(void) { + XFlush(X.display); +} + +void x11_finish(void) { + XCloseDisplay(X.display); + /* we're exiting now. If we own the clipboard, make sure it persists */ + if (Selections[CLIPBOARD].text) + cmdwrite((char*[]){ "xcpd", NULL }, Selections[CLIPBOARD].text, NULL); +} + +/******************************************************************************/ + static uint32_t special_keys(uint32_t key) { switch (key) { case XK_F1: return KEY_F1; @@ -310,7 +332,17 @@ void x11_handle_event(XEvent* e) { } } -void x11_handle_events(void) { +bool x11_events_await(unsigned int ms) { + fd_set fds; + int xfd = ConnectionNumber(X.display), redraw = 1; + /* configure for 100ms timeout */ + struct timeval tv = { .tv_usec = ms * 1000 }; + FD_ZERO(&fds); + FD_SET(xfd, &fds); + return (select(xfd+1, &fds, NULL, NULL, &tv) > 0); +} + +void x11_events_take(void) { XEvent e; while (XPending(X.display)) { XNextEvent(X.display, &e); @@ -319,30 +351,13 @@ void x11_handle_events(void) { } } -void x11_loop(void) { - fd_set fds; - int xfd = ConnectionNumber(X.display); - for (XEvent e; Running;) { - /* configure for 100ms timeout */ - struct timeval tv = { .tv_usec = 100000 }; - FD_ZERO(&fds); - FD_SET(xfd, &fds); - - /* wait for events with a timeout, then handle them if we got any */ - int ready = select(xfd+1, &fds, NULL, NULL, &tv); - if (ready > 0) { - x11_handle_events(); - Config->redraw(X.width, X.height); - XCopyArea(X.display, X.pixmap, X.window, X.gc, 0, 0, X.width, X.height, 0, 0); - } else { - Window xw; int x; unsigned int ux; - XQueryPointer(X.display, X.window, &xw, &xw, &x, &x, &x, &x, &ux); - } - } - XCloseDisplay(X.display); - /* we're exiting now. If we own the clipboard, make sure it persists */ - if (Selections[CLIPBOARD].text) - cmdwrite((char*[]){ "xcpd", NULL }, Selections[CLIPBOARD].text, NULL); +void x11_mouse_set(int x, int y) { + XWarpPointer(X.display, X.window, X.window, 0, 0, X.width, X.height, x, y); +} + +void x11_mouse_get(int* ptrx, int* ptry) { + Window xw; int x; unsigned int ux; + XQueryPointer(X.display, X.window, &xw, &xw, &x, &x, ptrx, ptry, &ux); } XFont x11_font_load(char* name) { @@ -497,10 +512,6 @@ void x11_draw_utf8(XFont fnt, int fg, int bg, int x, int y, char* str) { x11_draw_glyphs(fg, bg, (XGlyphSpec*)specs, nspecs); } -void x11_warp_mouse(int x, int y) { - XWarpPointer(X.display, X.window, X.window, 0, 0, X.width, X.height, x, y); -} - /* Selection Handling *****************************************************************************/ @@ -585,7 +596,7 @@ static void selrequest(XEvent* evnt) { XSendEvent(X.display, s.xselection.requestor, True, 0, &s); } -bool x11_getsel(int selid, void(*cbfn)(char*)) { +bool x11_sel_get(int selid, void(*cbfn)(char*)) { struct XSel* sel = &(Selections[selid]); if (sel->callback) return false; Window owner = XGetSelectionOwner(X.display, sel->atom); @@ -598,7 +609,7 @@ bool x11_getsel(int selid, void(*cbfn)(char*)) { return true; } -bool x11_setsel(int selid, char* str) { +bool x11_sel_set(int selid, char* str) { struct XSel* sel = &(Selections[selid]); if (!sel || !str || !*str) { free(str); diff --git a/xedit.c b/xedit.c index dea5613..aeed285 100644 --- a/xedit.c +++ b/xedit.c @@ -116,17 +116,17 @@ static void onpaste(char* text) { static void cut(void) { char* str = view_getstr(win_view(FOCUSED), NULL); - x11_setsel(CLIPBOARD, str); + x11_sel_set(CLIPBOARD, str); if (str && *str) delete(); } static void paste(void) { - assert(x11_getsel(CLIPBOARD, onpaste)); + assert(x11_sel_get(CLIPBOARD, onpaste)); } static void copy(void) { char* str = view_getstr(win_view(FOCUSED), NULL); - x11_setsel(CLIPBOARD, str); + x11_sel_set(CLIPBOARD, str); } static void quit(void) { -- 2.52.0