From befac6668eab41849b0e638b20c2636e82328fb4 Mon Sep 17 00:00:00 2001 From: Nathan Reiner Date: Sun, 30 Apr 2023 09:35:29 +0200 Subject: add mouse support --- drw.c | 10 ++-- swt.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ wayland.h | 13 ++--- 3 files changed, 172 insertions(+), 26 deletions(-) diff --git a/drw.c b/drw.c index 3800de5..a131623 100644 --- a/drw.c +++ b/drw.c @@ -413,7 +413,7 @@ load_bitmap(Font *font, uint_least32_t charcode) } FT_Get_Glyph(slot, &glyph); - FT_Glyph_StrokeBorder(&glyph, font->stroke, 0, 1); + error = FT_Glyph_StrokeBorder(&glyph, font->stroke, 0, 1); if (error) { fprintf(stderr, "warning: could not apply stroke\n"); return cglyph; @@ -441,17 +441,19 @@ draw_char(Canvas *canvas, FontCache *fontcache, uint_least32_t charcode, unsigne { Font *font; CacheGlyph cg; + unsigned stroke_size; font = get_font_with_charcode(fontcache, charcode); FT_Set_Pixel_Sizes(font->face, 0, fontcache->fontsize); if (boldstokemode && fontcache->fonttype == FONT_BOLD) { - FT_Stroker_Set(font->stroke, fontcache->fontsize * 2, FT_STROKER_LINECAP_BUTT, FT_STROKER_LINEJOIN_ROUND, fontcache->fontsize * 2); - y -= fontcache->fontsize * 2 / 64 + 1; + stroke_size = fontcache->fontsize * 2; } else { - FT_Stroker_Set(font->stroke, 0, FT_STROKER_LINECAP_BUTT, FT_STROKER_LINEJOIN_ROUND, 0); + stroke_size = 0; } + FT_Stroker_Set(font->stroke, stroke_size, FT_STROKER_LINECAP_BUTT, FT_STROKER_LINEJOIN_ROUND, 0); + cg = load_bitmap(font, charcode); if (cg.bg == 0) diff --git a/swt.c b/swt.c index a48509f..2307096 100644 --- a/swt.c +++ b/swt.c @@ -418,6 +418,26 @@ wsetcursor(int cursor) { return 1; } +const char* modes[] = { + "visible", + "focused", + "appkeypad", + "mousebtn", + "mousemotion", + "reverse", + "kbdlock", + "hide", + "appcursor", + "mousesgr", + "8bit", + "blink", + "fblink", + "focus", + "mousex10", + "mousemany", + "brcktpaste", + "numlock", +}; void wsetmode(int set, unsigned int flags) { int mode = win.mode; @@ -662,7 +682,7 @@ keyboard_repeat_info(void *data, struct wl_keyboard *keyboard, int32_t rate, int int matchmod(uint32_t mask, uint32_t mod) { - return mask == KEY_MOD_ANY || mask & mod; + return mask == KEY_MOD_ANY || mask == mod; } @@ -697,6 +717,15 @@ kmap() if (!matchmod(kp->mask, client.kb.event.mod)) continue; + if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) + continue; + if (IS_SET(MODE_NUMLOCK) && kp->appkey == 2) + continue; + if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) + continue; + + fprintf(stderr, "found kmap: %#04x, %#04x\n", XKB_KEY_F1, client.kb.event.sym); + return kp->s; } @@ -712,6 +741,9 @@ handle_keyboard_event() int len; char c; + if (IS_SET(MODE_KBDLOCK)) + return; + if (client.kb.event.state == WL_KEYBOARD_KEY_STATE_PRESSED) { if (execshortcut()) return; @@ -727,6 +759,19 @@ handle_keyboard_event() buf[0] -= 'a' - 1; } + if (len == 1 && client.kb.event.state && client.kb.event.mod & KEY_MOD_ALT) { + if (IS_SET(MODE_8BIT)) { + if (*buf < 0177) { + c = *buf | 0x80; + len = utf8encode(c, buf); + } + } else { + buf[1] = buf[0]; + buf[0] = '\033'; + len = 2; + } + } + ttywrite(buf, strlen(buf), 1); } } @@ -753,16 +798,92 @@ pointer_leave(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl } +void +reportpointer(int motion) +{ + int len, btn, code; + int x = client.pointer.position.x, y = client.pointer.position.y; + int state = client.pointer.buttons.state; + char buf[40]; + static int ox, oy; + + if (motion) { + if (x == ox && y == oy) + return; + if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) + return; + /* MODE_MOUSEMOTION: no reporting if no button is pressed */ + if (IS_SET(MODE_MOUSEMOTION) && !state) + return; + /* Set btn to lowest-numbered pressed button, or 12 if no + * buttons are pressed. */ + btn = client.pointer.buttons.button - BTN_MOUSE + 1; + code = 32; + } else { + btn = client.pointer.buttons.button - BTN_MOUSE + 1; + /* Only buttons 1 through 11 can be encoded */ + if (btn < 1 || btn > 11) + return; + if (!state) { + /* MODE_MOUSEX10: no button release reporting */ + if (IS_SET(MODE_MOUSEX10)) + return; + /* Don't send release events for the scroll wheel */ + if (btn == 4 || btn == 5) + return; + } + code = 0; + } + + ox = x; + oy = y; + + /* Encode btn into code. If no button is pressed for a motion event in + * MODE_MOUSEMANY, then encode it as a release. */ + if ((!IS_SET(MODE_MOUSESGR) && state) || btn == 12) + code += 3; + else if (btn >= 8) + code += 128 + btn - 8; + else if (btn >= 4) + code += 64 + btn - 4; + else + code += btn - 1; + + if (!IS_SET(MODE_MOUSEX10)) { + code += ((client.kb.event.mod & KEY_MOD_SHIFT) ? 4 : 0) + + ((client.kb.event.mod & KEY_MOD_ALT) ? 8 : 0) /* meta key: alt */ + + ((client.kb.event.mod & KEY_MOD_CTRL) ? 16 : 0); + } + + if (IS_SET(MODE_MOUSESGR)) { + len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", + code, x+1, y+1, + state ? 'M' : 'm'); + } else if (x < 223 && y < 223) { + len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", + 32+code, 32+x+1, 32+y+1); + } else { + return; + } + + fprintf(stderr, "mouse: %s\n", buf + 1); + + ttywrite(buf, len, 0); +} + + void pointer_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t x, wl_fixed_t y) { - client.pointer.position.x = wl_fixed_to_int(x); - client.pointer.position.y = wl_fixed_to_int(y); + client.pointer.position.x = MIN(wintotty(wl_fixed_to_int(x), width), win.tty.width - 1); + client.pointer.position.y = MIN(wintotty(wl_fixed_to_int(y), height), win.tty.height - 1); - if (client.pointer.buttons.button & BTN_LEFT) { + if (IS_SET(MODE_MOUSE) | IS_SET(MODE_MOUSEMOTION) | IS_SET(MODE_MOUSEMANY)) { + reportpointer(1); + } else if (client.pointer.buttons.button & BTN_LEFT) { selextend( - MIN(wintotty(client.pointer.position.x, width), win.tty.width - 1), - MIN(wintotty(client.pointer.position.y, height), win.tty.height - 1), + client.pointer.position.x, + client.pointer.position.y, SEL_REGULAR, 0 ); @@ -776,9 +897,17 @@ pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t { int snap; - if (button == BTN_LEFT && state) { - client.pointer.buttons.button |= BTN_LEFT; + client.pointer.buttons.state = state; + + client.pointer.buttons.button = button; + + if (IS_SET(MODE_MOUSE) | IS_SET(MODE_MOUSEMANY) | IS_SET(MODE_MOUSEBTN) | IS_SET(MODE_MOUSESGR)) { + client.pointer.buttons.button = button; + reportpointer(0); + return; + } + if (button == BTN_LEFT && state) { if (client.pointer.buttons.click_combo == 1 && time - client.pointer.buttons.tclick <= doubleclicktimeout) { snap = SNAP_WORD; } else if (client.pointer.buttons.click_combo >= 2 && time - client.pointer.buttons.tclick <= tripleclicktimeout) { @@ -791,12 +920,12 @@ pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t client.pointer.buttons.tclick = time; ++client.pointer.buttons.click_combo; - if (IS_SET(MODE_MOUSE) | IS_SET(MODE_MOUSEMANY) | IS_SET(MODE_MOUSEBTN)) { - ttywrite("\031", 1, 1); + if (IS_SET(MODE_MOUSE) | IS_SET(MODE_MOUSEMANY) | IS_SET(MODE_MOUSEBTN) | IS_SET(MODE_MOUSESGR)) { + reportpointer(0); } else { selstart( - MIN(wintotty(client.pointer.position.x, width), win.tty.width - 1), - MIN(wintotty(client.pointer.position.y, height), win.tty.height - 1), + client.pointer.position.x, + client.pointer.position.y, snap ); } @@ -804,20 +933,34 @@ pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t } else if (button == BTN_LEFT && !state) { client.pointer.buttons.button &= ~BTN_LEFT; selextend( - MIN(wintotty(client.pointer.position.x, width), win.tty.width - 1), - MIN(wintotty(client.pointer.position.y, height), win.tty.height - 1), + client.pointer.position.x, + client.pointer.position.y, SEL_REGULAR, 1 ); } + + if (!state) + client.pointer.buttons.button = 0; } void pointer_axis(void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { - int v = wl_fixed_to_int(value); - fprintf(stderr, "scroll: a: %i, v: %i\n", axis, v); + int v; + if (IS_SET(MODE_MOUSE) | IS_SET(MODE_MOUSEMANY) | IS_SET(MODE_MOUSEBTN) | IS_SET(MODE_MOUSESGR) | IS_SET(MODE_MOUSEX10)) { + v = wl_fixed_to_int(value); + client.pointer.buttons.state = 1; + if (v > 0) + client.pointer.buttons.button = BTN_MOUSE + 4; + else + client.pointer.buttons.button = BTN_MOUSE + 3; + reportpointer(0); + + client.pointer.buttons.button = 0; + client.pointer.buttons.state = 0; + } } diff --git a/wayland.h b/wayland.h index 97c608a..0c89e03 100644 --- a/wayland.h +++ b/wayland.h @@ -9,12 +9,12 @@ #include "xdg-shell-client-protocol.h" typedef enum { - KEY_MOD_NONE = 1 << 0, - KEY_MOD_CTRL = 1 << 1, - KEY_MOD_ALT = 1 << 2, - KEY_MOD_SHIFT = 1 << 3, - KEY_MOD_LOGO = 1 << 4, - KEY_MOD_ANY = 1 << 5 + KEY_MOD_NONE = 0 << 0, + KEY_MOD_CTRL = 1 << 0, + KEY_MOD_ALT = 1 << 1, + KEY_MOD_SHIFT = 1 << 2, + KEY_MOD_LOGO = 1 << 3, + KEY_MOD_ANY = 1 << 4 } ModMask; @@ -73,6 +73,7 @@ typedef struct { uint32_t button; uint8_t click_combo; uint32_t tclick; + uint32_t state; } buttons; } pointer; struct { -- cgit v1.2.3-70-g09d2