From 9768492b19c125eaac4b936d45dda9df711c8fca Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Thu, 9 May 2019 23:15:59 -0400 Subject: [PATCH] rework mouse handling --- Makefile | 1 + inc/edit.h | 16 +++++ src/lib/mouse.c | 63 ++++++++++++++++++++ src/tide.c | 152 ++++++++++++++++++++---------------------------- 4 files changed, 143 insertions(+), 89 deletions(-) create mode 100644 src/lib/mouse.c diff --git a/Makefile b/Makefile index 60f0f8f..71764a0 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ LIBEDIT_OBJS = \ src/lib/view.o \ src/lib/draw.o \ src/lib/shortcuts.o \ + src/lib/mouse.o \ src/lib/x11.o \ src/lib/x11_gc.o \ src/lib/x11_sel.o diff --git a/inc/edit.h b/inc/edit.h index 8e9fe61..434cb32 100644 --- a/inc/edit.h +++ b/inc/edit.h @@ -209,3 +209,19 @@ void undo(char* arg); void redo(char* arg); void newline(char* arg); void highlight(char* arg); + +enum { + MouseActNone, + MouseActSel, + MouseActSelCtx, + MouseActSelWord, + MouseActCut, + MouseActPaste, + MouseActExec, + MouseActExecArg, + MouseActFetch, + MouseActScrollUp, + MouseActScrollDn, +}; + +int process_mouse(int btn, bool pressed); diff --git a/src/lib/mouse.c b/src/lib/mouse.c new file mode 100644 index 0000000..3382573 --- /dev/null +++ b/src/lib/mouse.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include "config.h" + +#define PRESSED(mods, btn) \ + ((mods & (1 << (btn + 7))) == (1 << (btn + 7))) + +static int ExecRequest = 0; + +static int mouse_left(bool pressed) { + static int count = 0; + static Time before = 0; + if (!pressed) return MouseActNone; + count = ((X.now - before) <= (uint64_t)ClickTime ? count+1 : 1); + before = X.now; + if (PRESSED(X.mods, MouseRight)) { + return MouseActNone; + } else if (PRESSED(X.mods, MouseMiddle)) { + ExecRequest = 0; + return MouseActExecArg; + } else if (count == 1) { + return MouseActSel; + } else if (count == 2) { + return MouseActSelCtx; + } else if (count == 3) { + return MouseActSelWord; + } else { + return MouseActNone; + } +} + +static int mouse_middle(bool pressed) { + if (pressed) { ExecRequest = 1; return MouseActNone; } + if (PRESSED(X.mods, MouseLeft)) { + return MouseActCut; + } else if (ExecRequest) { + return MouseActExec; + } else { + return MouseActNone; + } +} + +static int mouse_right(bool pressed) { + if (pressed) return MouseActNone; + if (PRESSED(X.mods, MouseLeft)) { + return MouseActPaste; + } else { + return MouseActFetch; + } +} + +int process_mouse(int btn, bool pressed) { + switch(btn) { + case MouseLeft: return mouse_left(pressed); + case MouseMiddle: return mouse_middle(pressed); + case MouseRight: return mouse_right(pressed); + case MouseWheelUp: return (pressed ? MouseActScrollUp : MouseActNone); + case MouseWheelDn: return (pressed ? MouseActScrollDn : MouseActNone); + } + return MouseActNone; +} diff --git a/src/tide.c b/src/tide.c index e1e3373..854f3c5 100644 --- a/src/tide.c +++ b/src/tide.c @@ -42,7 +42,6 @@ static int FontSel; static bool SyncMouse = false; static int SearchDir = DOWN; static char* SearchTerm = NULL; -static int ExecRequest = 0; #define PRESSED(mods, btn) \ ((mods & (1 << (btn + 7))) == (1 << (btn + 7))) @@ -83,80 +82,6 @@ static void tide_send(char* type) { } } -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 = ((X.now - before) <= (uint64_t)ClickTime ? count+1 : 1); - before = X.now; - if (PRESSED(X.mods, MouseRight)) { - puts("fetch tag"); - } else if (PRESSED(X.mods, MouseMiddle)) { - /* if we didnt get an arg, find one in the selection */ - char* arg = NULL; - if (!arg || !*arg) arg = view_getstr(win_view(EDIT)); - if (!arg || !*arg) arg = view_getstr(win_view(TAGS)); - char* str = view_fetch(win_view(id), row, col, riscmd); - if (str) exec(str, arg); - free(str); - free(arg); - ExecRequest = 0; - } else { - if (count == 1) - view_setcursor(win_view(id), row, col, win_keymodsset(ModShift)); - else if (count == 2) - view_select(win_view(id), row, col); - else if (count == 3) - view_selword(win_view(id), row, col); - } -} - -static void mouse_middle(WinRegion id, bool pressed, size_t row, size_t col) { - if (pressed) { ExecRequest = 1; return; } - if (PRESSED(X.mods, MouseLeft)) { - cut(NULL); - } else if (ExecRequest) { - char* str = view_fetch(win_view(id), row, col, riscmd); - if (str) exec(str, NULL); - free(str); - } -} - -static void mouse_right(WinRegion id, bool pressed, size_t row, size_t col) { - if (pressed) return; - if (PRESSED(X.mods, MouseLeft)) { - paste(NULL); - } else { - FetchCmd[2] = view_fetch(win_view(id), row, col, risfile); - if (job_run(FetchCmd) != 0) { - SearchDir *= (win_keymodsset(ModShift) ? -1 : +1); - free(SearchTerm); - SearchTerm = view_fetch(win_view(id), row, col, risfile); - view_findstr(win_view(EDIT), SearchDir, SearchTerm); - SyncMouse = true; - } - free(FetchCmd[2]); - } -} - -static void mouse_scroll(WinRegion id, bool pressed, int amount) { - if (!pressed) - view_scroll(win_view(id), amount); -} - -static void mouse_click(int btn, bool pressed, int x, int y) { - size_t row, col; - Focused = (y <= Divider ? TAGS : EDIT); - get_position(Focused, x, y, &row, &col); - switch(btn) { - case MouseLeft: mouse_left(Focused, pressed, row, col); break; - case MouseMiddle: mouse_middle(Focused, pressed, row, col); break; - case MouseRight: mouse_right(Focused, pressed, row, col); break; - case MouseWheelUp: mouse_scroll(Focused, pressed, -ScrollBy); break; - case MouseWheelDn: mouse_scroll(Focused, pressed, +ScrollBy); break; - } -} - size_t glyph_width(View* view, int c) { FcChar32 rune = (FcChar32)c; XGlyphInfo extents; @@ -175,14 +100,65 @@ static void xkeypress(XConf* x, XEvent* e) { view_insert(win_view(FOCUSED), key); } -static void xbtnpress(XConf* x, XEvent* e) { - (void)x; - mouse_click(e->xbutton.button, true, e->xbutton.x, e->xbutton.y); -} - -static void xbtnrelease(XConf* x, XEvent* e) { +static void xmousebtn(XConf* x, XEvent* e) { (void)x; - mouse_click(e->xbutton.button, false, e->xbutton.x, e->xbutton.y); + size_t row, col; + Focused = (e->xbutton.y <= Divider ? TAGS : EDIT); + get_position(Focused, e->xbutton.x, e->xbutton.y, &row, &col); + switch (process_mouse(e->xbutton.button, (e->type == ButtonPress))) { + case MouseActNone: + break; + case MouseActSel: + view_setcursor(win_view(Focused), row, col, win_keymodsset(ModShift)); + break; + case MouseActSelCtx: + view_select(win_view(Focused), row, col); + break; + case MouseActSelWord: + view_selword(win_view(Focused), row, col); + break; + case MouseActCut: + cut(NULL); + break; + case MouseActPaste: + paste(NULL); + break; + case MouseActExec: { + char* str = view_fetch(win_view(Focused), row, col, riscmd); + if (str) exec(str, NULL); + free(str); + break; + } + case MouseActExecArg: { + /* if we didnt get an arg, find one in the selection */ + char* arg = NULL; + if (!arg || !*arg) arg = view_getstr(win_view(EDIT)); + if (!arg || !*arg) arg = view_getstr(win_view(TAGS)); + char* str = view_fetch(win_view(Focused), row, col, riscmd); + if (str) exec(str, arg); + free(str); + free(arg); + break; + } + case MouseActFetch: { + FetchCmd[2] = view_fetch(win_view(Focused), row, col, risfile); + if (job_run(FetchCmd) != 0) { + SearchDir *= (win_keymodsset(ModShift) ? -1 : +1); + free(SearchTerm); + SearchTerm = view_fetch(win_view(Focused), row, col, risfile); + view_findstr(win_view(EDIT), SearchDir, SearchTerm); + SyncMouse = true; + } + free(FetchCmd[2]); + break; + } + case MouseActScrollUp: + view_scroll(win_view(Focused), -ScrollBy); + break; + case MouseActScrollDn: + view_scroll(win_view(Focused), +ScrollBy); + break; + } } static void xbtnmotion(XConf* x, XEvent* e) { @@ -223,8 +199,9 @@ static void xredraw(XConf* x) { } static void xupdate(Job* job) { - /* redraw if we have changes */ - if (!x11_process_events(&X, xredraw) && job) return; + /* redraw if we have changes or if we have input from a job */ + if (!x11_process_events(&X, xredraw) && !job) + xredraw(&X); } void win_init(void) { @@ -258,8 +235,8 @@ void win_init(void) { #endif /* register event handlers */ X.eventfns[KeyPress] = xkeypress; - X.eventfns[ButtonPress] = xbtnpress; - X.eventfns[ButtonRelease] = xbtnrelease; + X.eventfns[ButtonPress] = xmousebtn; + X.eventfns[ButtonRelease] = xmousebtn; X.eventfns[MotionNotify] = xbtnmotion; X.eventfns[ClientMessage] = xclientmsg; } @@ -396,9 +373,6 @@ static void exec(char* cmd, char* arg) { } } -/* Keyboard Editing Handlers - ******************************************************************************/ - /* Keyboard and Tag Handlers ******************************************************************************/ static void change_focus(char* arg) { -- 2.51.0