aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2022-08-25 00:10:17 +0200
committerPřemysl Eric Janouch <p@janouch.name>2022-08-25 00:10:17 +0200
commit2d219f1a4bf3f2e8cb3916c63d4765d0781b41f0 (patch)
treea927a36c9416520566cb8e536f1a5919d3e86e74
parenta77d872e7fdd109ece11275cb3a1d48574199fb3 (diff)
downloadnncmpp-2d219f1a4bf3f2e8cb3916c63d4765d0781b41f0.tar.gz
nncmpp-2d219f1a4bf3f2e8cb3916c63d4765d0781b41f0.tar.xz
nncmpp-2d219f1a4bf3f2e8cb3916c63d4765d0781b41f0.zip
Rework mouse event processing
X11's triple-click bug is gone, and we may pass modifier state.
-rw-r--r--nncmpp.c85
1 files changed, 51 insertions, 34 deletions
diff --git a/nncmpp.c b/nncmpp.c
index 68568b2..2e7aeb2 100644
--- a/nncmpp.c
+++ b/nncmpp.c
@@ -2728,8 +2728,11 @@ app_editor_process_action (enum action action)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// Carefully chosen to limit the possibility of ever hitting termo keymods.
+enum { APP_KEYMOD_DOUBLE_CLICK = 1 << 15 };
+
static bool
-app_process_left_mouse_click (struct widget *w, int x, int y, bool double_click)
+app_process_left_mouse_click (struct widget *w, int x, int y, int modifiers)
{
switch (w->id)
{
@@ -2772,7 +2775,7 @@ app_process_left_mouse_click (struct widget *w, int x, int y, bool double_click)
tab->item_selected = row_index + tab->item_top;
app_invalidate ();
- if (double_click)
+ if (modifiers & APP_KEYMOD_DOUBLE_CLICK)
app_process_action (ACTION_CHOOSE);
break;
}
@@ -2793,7 +2796,7 @@ app_process_left_mouse_click (struct widget *w, int x, int y, bool double_click)
static bool
app_process_mouse (termo_mouse_event_t type, int x, int y, int button,
- bool double_click)
+ int modifiers)
{
// XXX: Terminals don't let us know which button has been released,
// so we can't press buttons at that point. We'd need a special "click"
@@ -2817,7 +2820,7 @@ app_process_mouse (termo_mouse_event_t type, int x, int y, int button,
x -= target->x;
y -= target->y;
- return app_process_left_mouse_click (target, x, y, double_click);
+ return app_process_left_mouse_click (target, x, y, modifiers);
}
if (g.editor.line)
@@ -2840,7 +2843,7 @@ app_process_mouse (termo_mouse_event_t type, int x, int y, int button,
{
case 1:
g.ui_dragging = target->id;
- return app_process_left_mouse_click (target, x, y, double_click);
+ return app_process_left_mouse_click (target, x, y, modifiers);
case 4:
if (target->id == WIDGET_LIST)
return app_process_action (ACTION_SCROLL_UP);
@@ -5243,23 +5246,25 @@ tui_on_tty_event (termo_key_t *event, int64_t event_ts)
static int64_t last_event_ts;
static int last_button;
- int y, x, button, y_last, x_last;
+ int y, x, button, y_last, x_last, modifiers = 0;
termo_mouse_event_t type, type_last;
if (termo_interpret_mouse (g.tk, event, &type, &button, &y, &x))
{
- bool double_click = termo_interpret_mouse
+ if (termo_interpret_mouse
(g.tk, &last_event, &type_last, NULL, &y_last, &x_last)
- && event_ts - last_event_ts < 500
- && type_last == TERMO_MOUSE_RELEASE && type == TERMO_MOUSE_PRESS
- && y_last == y && x_last == x && last_button == button;
- if (!app_process_mouse (type, x, y, button, double_click))
- beep ();
-
- // Prevent interpreting triple clicks as two double clicks
- if (double_click)
+ && event_ts - last_event_ts < 500
+ && type_last == TERMO_MOUSE_RELEASE && type == TERMO_MOUSE_PRESS
+ && y_last == y && x_last == x && last_button == button)
+ {
+ modifiers |= APP_KEYMOD_DOUBLE_CLICK;
+ // Prevent interpreting triple clicks as two double clicks.
last_button = 0;
+ }
else if (type == TERMO_MOUSE_PRESS)
last_button = button;
+
+ if (!app_process_mouse (type, x, y, button, modifiers))
+ beep ();
}
else if (!app_process_termo_event (event))
beep ();
@@ -6001,43 +6006,55 @@ x11_init_pixmap (void)
= XRenderCreatePicture (g.dpy, g.x11_pixmap, format, 0, NULL);
}
+static int
+x11_state_to_modifiers (unsigned int state)
+{
+ int modifiers = 0;
+ if (state & ShiftMask) modifiers |= TERMO_KEYMOD_SHIFT;
+ if (state & ControlMask) modifiers |= TERMO_KEYMOD_CTRL;
+ if (state & Mod1Mask) modifiers |= TERMO_KEYMOD_ALT;
+ return modifiers;
+}
+
static bool
on_x11_input_event (XEvent *ev)
{
- static XEvent last_button_event;
+ static XEvent last_press_event;
if (ev->type == KeyPress)
{
- last_button_event = (XEvent) {};
+ last_press_event = (XEvent) {};
return on_x11_keypress (ev);
}
if (ev->type == MotionNotify)
{
- // We only select for Button1MotionMask, so this works out.
- int x = ev->xmotion.x, y = ev->xmotion.y;
- return app_process_mouse (TERMO_MOUSE_DRAG, x, y, 1, false);
+ return app_process_mouse (TERMO_MOUSE_DRAG,
+ ev->xmotion.x, ev->xmotion.y, 1 /* Button1MotionMask */,
+ x11_state_to_modifiers (ev->xmotion.state));
}
- // See tui_on_tty_event(). Just here we know the button on button release.
+ // This is nearly the same as tui_on_tty_event().
int x = ev->xbutton.x, y = ev->xbutton.y;
unsigned int button = ev->xbutton.button;
- bool double_click = ev->xbutton.time - last_button_event.xbutton.time < 500
- && last_button_event.type == ButtonRelease && ev->type == ButtonPress
- && abs (last_button_event.xbutton.x - x) < 5
- && abs (last_button_event.xbutton.y - y) < 5
- && last_button_event.xbutton.button == button;
-
- // Prevent interpreting triple clicks as two double clicks.
- // FIXME: This doesn't work: we skip ButtonPress, but use ButtonRelease.
- last_button_event = (XEvent) {};
- if (!double_click)
- last_button_event = *ev;
+ int modifiers = x11_state_to_modifiers (ev->xbutton.state);
+ if (ev->type == ButtonPress
+ && ev->xbutton.time - last_press_event.xbutton.time < 500
+ && abs (last_press_event.xbutton.x - x) < 5
+ && abs (last_press_event.xbutton.y - y) < 5
+ && last_press_event.xbutton.button == button)
+ {
+ modifiers |= APP_KEYMOD_DOUBLE_CLICK;
+ // Prevent interpreting triple clicks as two double clicks.
+ last_press_event = (XEvent) {};
+ }
+ else if (ev->type == ButtonPress)
+ last_press_event = *ev;
if (ev->type == ButtonPress)
return app_process_mouse
- (TERMO_MOUSE_PRESS, x, y, button, double_click);
+ (TERMO_MOUSE_PRESS, x, y, button, modifiers);
if (ev->type == ButtonRelease)
return app_process_mouse
- (TERMO_MOUSE_RELEASE, x, y, button, double_click);
+ (TERMO_MOUSE_RELEASE, x, y, button, modifiers);
return false;
}