Fix horizontal wheel events not being reported to client programs when they grab the mouse
Fixes #2819
This commit is contained in:
parent
3a9c6088b2
commit
a89e1b5573
@ -45,6 +45,8 @@ Detailed list of changes
|
||||
|
||||
- Allow resizing windows created in session files (:pull:`5196`)
|
||||
|
||||
- Fix horizontal wheel events not being reported to client programs when they grab the mouse (:iss:`2819`)
|
||||
|
||||
|
||||
0.25.2 [2022-06-07]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -109,17 +109,17 @@ class TermManager:
|
||||
|
||||
|
||||
class MouseButton(IntFlag):
|
||||
NONE, LEFT, MIDDLE, RIGHT, FOURTH, FIFTH = 0, 1, 2, 4, 8, 16
|
||||
WHEEL_UP, WHEEL_DOWN = -1, -2
|
||||
NONE, LEFT, MIDDLE, RIGHT, FOURTH, FIFTH, SIXTH, SEVENTH = 0, 1, 2, 4, 8, 16, 32, 64
|
||||
WHEEL_UP, WHEEL_DOWN, WHEEL_LEFT, WHEEL_RIGHT = -1, -2, -4, -8
|
||||
|
||||
|
||||
bmap = {0: MouseButton.LEFT, 1: MouseButton.MIDDLE, 2: MouseButton.RIGHT}
|
||||
bmap = MouseButton.LEFT, MouseButton.MIDDLE, MouseButton.RIGHT
|
||||
ebmap = MouseButton.FOURTH, MouseButton.FIFTH, MouseButton.SIXTH, MouseButton.SEVENTH
|
||||
wbmap = MouseButton.WHEEL_UP, MouseButton.WHEEL_DOWN, MouseButton.WHEEL_LEFT, MouseButton.WHEEL_RIGHT
|
||||
SHIFT_INDICATOR = 1 << 2
|
||||
ALT_INDICATOR = 1 << 3
|
||||
CTRL_INDICATOR = 1 << 4
|
||||
MOTION_INDICATOR = 1 << 5
|
||||
SCROLL_BUTTON_INDICATOR = 1 << 6
|
||||
EXTRA_BUTTON_INDICATOR = 1 << 7
|
||||
|
||||
|
||||
class EventType(Enum):
|
||||
@ -150,12 +150,11 @@ def decode_sgr_mouse(text: str, screen_size: ScreenSize) -> MouseEvent:
|
||||
typ = EventType.RELEASE if m == 'm' else (EventType.MOVE if cb & MOTION_INDICATOR else EventType.PRESS)
|
||||
buttons: MouseButton = MouseButton.NONE
|
||||
cb3 = cb & 3
|
||||
if cb3 != 3:
|
||||
if cb & SCROLL_BUTTON_INDICATOR:
|
||||
buttons = MouseButton.WHEEL_DOWN if cb3 & 1 else MouseButton.WHEEL_UP
|
||||
elif cb & EXTRA_BUTTON_INDICATOR:
|
||||
buttons |= MouseButton.FIFTH if cb3 & 1 else MouseButton.FOURTH
|
||||
else:
|
||||
if cb >= 128:
|
||||
buttons |= ebmap[cb3]
|
||||
elif cb >= 64:
|
||||
buttons |= wbmap[cb3]
|
||||
elif cb3 < 3:
|
||||
buttons |= bmap[cb3]
|
||||
mods = 0
|
||||
if cb & SHIFT_INDICATOR:
|
||||
|
||||
@ -135,8 +135,8 @@ encode_mouse_button(Window *w, int button, MouseAction action, int mods) {
|
||||
}
|
||||
|
||||
static int
|
||||
encode_mouse_scroll(Window *w, bool upwards, int mods) {
|
||||
return encode_mouse_event(w, upwards ? 4 : 5, PRESS, mods);
|
||||
encode_mouse_scroll(Window *w, int button, int mods) {
|
||||
return encode_mouse_event(w, button, PRESS, mods);
|
||||
}
|
||||
|
||||
// }}}
|
||||
@ -815,6 +815,38 @@ mouse_event(const int button, int modifiers, int action) {
|
||||
if (mouse_cursor_shape != old_cursor) set_mouse_cursor(mouse_cursor_shape);
|
||||
}
|
||||
|
||||
static int
|
||||
scale_scroll(Screen *screen, double offset, bool is_high_resolution, double *pending_scroll_pixels, int cell_size) {
|
||||
// scale the scroll by the multiplier unless the mouse is grabbed. If the mouse is grabbed only change direction.
|
||||
#define SCALE_SCROLL(which) { double scale = OPT(which); if (screen->modes.mouse_tracking_mode) scale /= fabs(scale); offset *= scale; }
|
||||
int s = 0;
|
||||
if (is_high_resolution) {
|
||||
SCALE_SCROLL(touch_scroll_multiplier);
|
||||
double pixels = *pending_scroll_pixels + offset;
|
||||
if (fabs(pixels) < cell_size) {
|
||||
*pending_scroll_pixels = pixels;
|
||||
return 0;
|
||||
}
|
||||
s = (int)round(pixels) / cell_size;
|
||||
*pending_scroll_pixels = pixels - s * cell_size;
|
||||
} else {
|
||||
SCALE_SCROLL(wheel_scroll_multiplier);
|
||||
s = (int) round(offset);
|
||||
if (offset != 0) {
|
||||
const int min_lines = screen->modes.mouse_tracking_mode ? 1 : OPT(wheel_scroll_min_lines);
|
||||
if (min_lines > 0 && abs(s) < min_lines) s = offset > 0 ? min_lines : -min_lines;
|
||||
// Always add the minimum number of lines when it is negative
|
||||
else if (min_lines < 0) s = offset > 0 ? s - min_lines : s + min_lines;
|
||||
// apparently on cocoa some mice generate really small yoffset values
|
||||
// when scrolling slowly https://github.com/kovidgoyal/kitty/issues/1238
|
||||
if (s == 0) s = offset > 0 ? 1 : -1;
|
||||
}
|
||||
*pending_scroll_pixels = 0;
|
||||
}
|
||||
return s;
|
||||
#undef SCALE_SCROLL
|
||||
}
|
||||
|
||||
void
|
||||
scroll_event(double xoffset, double yoffset, int flags, int modifiers) {
|
||||
debug("\x1b[36mScroll\x1b[m xoffset: %f yoffset: %f flags: %x modifiers: %s\n", xoffset, yoffset, flags, format_mods(modifiers));
|
||||
@ -874,41 +906,15 @@ scroll_event(double xoffset, double yoffset, int flags, int modifiers) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (yoffset == 0.0) return;
|
||||
|
||||
int s;
|
||||
bool is_high_resolution = flags & 1;
|
||||
|
||||
// scale the scroll by the multiplier unless the mouse is grabbed. If the mouse is grabbed only change direction.
|
||||
#define SCALE_SCROLL(which) { double scale = OPT(which); if (screen->modes.mouse_tracking_mode) scale /= fabs(scale); yoffset *= scale; }
|
||||
if (is_high_resolution) {
|
||||
SCALE_SCROLL(touch_scroll_multiplier);
|
||||
double pixels = screen->pending_scroll_pixels + yoffset;
|
||||
if (fabs(pixels) < global_state.callback_os_window->fonts_data->cell_height) {
|
||||
screen->pending_scroll_pixels = pixels;
|
||||
return;
|
||||
}
|
||||
s = (int)round(pixels) / (int)global_state.callback_os_window->fonts_data->cell_height;
|
||||
screen->pending_scroll_pixels = pixels - s * (int) global_state.callback_os_window->fonts_data->cell_height;
|
||||
} else {
|
||||
SCALE_SCROLL(wheel_scroll_multiplier);
|
||||
s = (int) round(yoffset);
|
||||
if (yoffset != 0) {
|
||||
const int min_lines = screen->modes.mouse_tracking_mode ? 1 : OPT(wheel_scroll_min_lines);
|
||||
if (min_lines > 0 && abs(s) < min_lines) s = yoffset > 0 ? min_lines : -min_lines;
|
||||
// Always add the minimum number of lines when it is negative
|
||||
else if (min_lines < 0) s = yoffset > 0 ? s - min_lines : s + min_lines;
|
||||
// apparently on cocoa some mice generate really small yoffset values
|
||||
// when scrolling slowly https://github.com/kovidgoyal/kitty/issues/1238
|
||||
if (s == 0) s = yoffset > 0 ? 1 : -1;
|
||||
}
|
||||
screen->pending_scroll_pixels = 0;
|
||||
}
|
||||
#undef SCALE_SCROLL
|
||||
if (s == 0) return;
|
||||
if (yoffset != 0.0) {
|
||||
s = scale_scroll(screen, yoffset, is_high_resolution, &screen->pending_scroll_pixels_y, global_state.callback_os_window->fonts_data->cell_height);
|
||||
if (s) {
|
||||
bool upwards = s > 0;
|
||||
if (screen->modes.mouse_tracking_mode) {
|
||||
int sz = encode_mouse_scroll(w, upwards, modifiers);
|
||||
int sz = encode_mouse_scroll(w, upwards ? 4 : 5, modifiers);
|
||||
if (sz > 0) {
|
||||
mouse_event_buf[sz] = 0;
|
||||
for (s = abs(s); s > 0; s--) {
|
||||
@ -919,6 +925,23 @@ scroll_event(double xoffset, double yoffset, int flags, int modifiers) {
|
||||
if (screen->linebuf == screen->main_linebuf) screen_history_scroll(screen, abs(s), upwards);
|
||||
else fake_scroll(w, abs(s), upwards);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (xoffset != 0.0) {
|
||||
s = scale_scroll(screen, xoffset, is_high_resolution, &screen->pending_scroll_pixels_x, global_state.callback_os_window->fonts_data->cell_width);
|
||||
if (s) {
|
||||
if (screen->modes.mouse_tracking_mode) {
|
||||
int sz = encode_mouse_scroll(w, s > 0 ? 6 : 7, modifiers);
|
||||
if (sz > 0) {
|
||||
mouse_event_buf[sz] = 0;
|
||||
for (s = abs(s); s > 0; s--) {
|
||||
write_escape_code_to_child(screen, CSI, mouse_event_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
|
||||
@ -78,7 +78,7 @@ typedef struct {
|
||||
PyObject_HEAD
|
||||
|
||||
unsigned int columns, lines, margin_top, margin_bottom, charset, scrolled_by;
|
||||
double pending_scroll_pixels;
|
||||
double pending_scroll_pixels_x, pending_scroll_pixels_y;
|
||||
CellPixelSize cell_size;
|
||||
OverlayLine overlay_line;
|
||||
id_type window_id;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user