From: Michael D. Lowis Date: Thu, 9 May 2019 02:29:02 +0000 (-0400) Subject: further button press refactoring X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=21894fda5a9edbf64827f4e4024ce01e58d9b751;p=projs%2Ftide.git further button press refactoring --- diff --git a/inc/win.h b/inc/win.h index e8b74f3..e0ced7f 100644 --- a/inc/win.h +++ b/inc/win.h @@ -12,20 +12,6 @@ typedef struct { short y; } XGlyphSpec; -/* Key modifier masks */ -enum { - ModNone = 0, - ModShift = (1 << 0), - ModCapsLock = (1 << 1), - ModCtrl = (1 << 2), - ModAlt = (1 << 3), - ModNumLock = (1 << 4), - ModScrollLock = (1 << 5), - ModWindows = (1 << 6), - ModOneOrMore = (ModCtrl|ModAlt), - ModAny = -1 -}; - enum { MouseLeft = 1, MouseMiddle = 2, @@ -41,14 +27,7 @@ typedef enum { FOCUSED = 2 } WinRegion; -typedef struct { - int mods; - Rune key; - void (*fn)(char*); - char* arg; -} KeyBinding; - -void win_init(KeyBinding* bindings); +void win_init(void); void win_title(char* path); void win_font(char* font); void win_prop_set(char* xname, char* ename, char* value); diff --git a/inc/x11.h b/inc/x11.h index 90901e3..9331416 100644 --- a/inc/x11.h +++ b/inc/x11.h @@ -23,6 +23,7 @@ typedef struct XConf { XIM xim; GC gc; void (*eventfns[LASTEvent])(struct XConf*, XEvent*); + Time now; } XConf; /* Selection identifiers */ @@ -103,6 +104,26 @@ enum Keys { KEY_CTRL_UNDERSCORE = 0x1F, }; +/* Key modifier masks */ +enum { + ModNone = 0, + ModShift = (1 << 0), + ModCapsLock = (1 << 1), + ModCtrl = (1 << 2), + ModAlt = (1 << 3), + ModNumLock = (1 << 4), + ModScrollLock = (1 << 5), + ModWindows = (1 << 6), + ModOneOrMore = (ModCtrl|ModAlt), + ModAny = -1 +}; + +typedef struct { + int mods; + uint32_t key; + void (*fn)(char*); + char* arg; +} KeyBinding; int x11_init(XConf* x); void x11_error_clear(void); @@ -114,6 +135,7 @@ 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); uint32_t x11_getkey(XConf* x, XEvent* e); +uint32_t x11_process_key(XConf* x, XEvent* e, KeyBinding* keys); void x11_centerwin(XConf* x); void x11_init_gc(XConf* x); diff --git a/src/lib/x11.c b/src/lib/x11.c index e56b480..1f15a21 100644 --- a/src/lib/x11.c +++ b/src/lib/x11.c @@ -68,6 +68,15 @@ 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); } +static void update_time(XConf* x, XEvent* e) { + if ( + (e->type == KeyPress) || (e->type == ButtonPress) || + (e->type == ButtonRelease) || (e->type == MotionNotify) + ) { + x->now = e->xkey.time; + } +} + int x11_process_events(XConf* x) { int nqueued, nevents, dirty = false; /* reap zombie background processes */ @@ -78,6 +87,7 @@ int x11_process_events(XConf* x) { XGetMotionEvents(x->display, x->self, CurrentTime, CurrentTime, &nevents); for (XEvent e; XPending(x->display);) { XNextEvent(x->display, &e); + update_time(x, &e); if (e.type == Expose) dirty = 1; if (!XFilterEvent(&e, None) && x->eventfns[e.type]) (x->eventfns[e.type])(x, &e); @@ -139,3 +149,23 @@ uint32_t x11_getkey(XConf* x, XEvent* e) { /* translate special key codes into unicode codepoints */ return special_keys(key); } + +uint32_t x11_process_key(XConf* x, XEvent* e, KeyBinding* keys) { + uint32_t key = x11_getkey(x, e); + if (key == RUNE_ERR) return key; + int mods = e->xkey.state & (ModCtrl|ModShift|ModAlt); + int32_t mkey = tolower(key); + for (KeyBinding* bind = keys; bind && bind->key; bind++) { + bool match = (mkey == (int32_t)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 RUNE_ERR; + } + } + /* 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 */ + return (key < 0xE000 || key > 0xF8FF ? key : RUNE_ERR); +} diff --git a/src/tframe.c b/src/tframe.c index 67419ae..8c95559 100644 --- a/src/tframe.c +++ b/src/tframe.c @@ -66,23 +66,8 @@ static void xexpose(XConf* x, XEvent* e) { } 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) + uint32_t key = x11_process_key(x, e, NULL); + if (key != RUNE_ERR) view_insert(&Tags, key); } @@ -110,8 +95,7 @@ static void xupdate(Job* job) { XFlush(X.display); } -void win_init(KeyBinding* bindings) { - (void)bindings; +void win_init(void) { signal(SIGPIPE, SIG_IGN); // Ignore the SIGPIPE signal setlocale(LC_CTYPE, ""); XSetLocaleModifiers(""); @@ -175,7 +159,7 @@ void win_quit(void) { ******************************************************************************/ int main(void) { /* create the window */ - win_init(NULL); + win_init(); /* Initialize the views */ view_init(&Tags, NULL); diff --git a/src/tide.c b/src/tide.c index 2a0f2fb..60b9ffa 100644 --- a/src/tide.c +++ b/src/tide.c @@ -34,12 +34,11 @@ typedef struct { char* ARGV0; static Tag Builtins[18]; -static Time Now; +static KeyBinding Bindings[]; static struct XConf X; static int KeyBtnState; static WinRegion Focused = EDIT; static View Regions[NREGIONS]; -static KeyBinding* Keys = NULL; static int Divider; static int FontSel; static bool SyncMouse = false; @@ -90,8 +89,8 @@ static void mouse_left(WinRegion id, bool pressed, size_t row, size_t col) { static int count = 0; static Time before = 0; if (!pressed) return; - count = ((Now - before) <= (uint64_t)ClickTime ? count+1 : 1); - before = Now; + count = ((X.now - before) <= (uint64_t)ClickTime ? count+1 : 1); + before = X.now; if (PRESSED(MouseRight)) { puts("fetch tag"); } else if (PRESSED(MouseMiddle)) { @@ -172,47 +171,27 @@ size_t glyph_width(View* view, int c) { } static void xkeypress(XConf* x, XEvent* e) { - (void)x; - Now = e->xkey.time; + uint32_t key = x11_process_key(x, e, Bindings); Focused = (e->xkey.y <= Divider ? TAGS : EDIT); - uint32_t key = x11_getkey(x, e); - if (key == RUNE_ERR) return; KeyBtnState = e->xkey.state; - int mods = KeyBtnState & (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) + if (key != RUNE_ERR) view_insert(win_view(FOCUSED), key); } static void xbtnpress(XConf* x, XEvent* e) { (void)x; - Now = e->xbutton.time; KeyBtnState = (e->xbutton.state | (1 << (e->xbutton.button + 7))); mouse_click(e->xbutton.button, true, e->xbutton.x, e->xbutton.y); } static void xbtnrelease(XConf* x, XEvent* e) { (void)x; - Now = e->xbutton.time; KeyBtnState = (KeyBtnState & ~(1 << (e->xbutton.button + 7))); mouse_click(e->xbutton.button, false, e->xbutton.x, e->xbutton.y); } static void xbtnmotion(XConf* x, XEvent* e) { while (XCheckTypedEvent(x->display, MotionNotify, e)); - Now = e->xbutton.time; size_t row, col; KeyBtnState = e->xbutton.state; int xpos = e->xbutton.x, ypos = e->xbutton.y; @@ -251,8 +230,7 @@ static void xupdate(Job* job) { XFlush(X.display); } -void win_init(KeyBinding* bindings) { - Keys = bindings; +void win_init(void) { signal(SIGPIPE, SIG_IGN); // Ignore the SIGPIPE signal setlocale(LC_CTYPE, ""); XSetLocaleModifiers(""); @@ -327,7 +305,7 @@ void win_loop(void) { void win_quit(void) { static uint64_t before = 0; - if ((win_buf(EDIT)->status != MODIFIED) || (Now - before) <= (uint64_t)ClickTime) { + if ((win_buf(EDIT)->status != MODIFIED) || (X.now - before) <= (uint64_t)ClickTime) { tide_send("DEL"); X.eventfns[SelectionClear] = x11_sel_quit; XUnmapWindow(X.display, X.self); @@ -337,7 +315,7 @@ void win_quit(void) { if (fork()) exit(0); /* fork into background if we still have selection */ } } - before = Now; + before = X.now; } void win_togglefocus(void) { @@ -881,7 +859,7 @@ int main(int argc, char** argv) { if (!ShellCmd[0]) ShellCmd[0] = "/bin/sh"; /* create the window */ - win_init(Bindings); + win_init(); /* Initialize the views */ view_init(&Regions[TAGS], NULL);