1
0
forked from aniani/vim

patch 9.0.0775: MS-Windows: mouse scrolling not supported in the console

Problem:    MS-Windows: mouse scrolling not supported in the console.
Solution:   Add event handling for mouse scroll events. (Christopher
            Plewright, closes #11374)
This commit is contained in:
Christopher Plewright
2022-10-16 19:47:45 +01:00
committed by Bram Moolenaar
parent 6a12d26f34
commit 2a46f81ec7
4 changed files with 158 additions and 31 deletions

View File

@@ -1231,6 +1231,100 @@ mch_bevalterm_changed(void)
}
# endif
/*
* Win32 console mouse scroll event handler.
* Loosely based on the _OnMouseWheel() function in gui_w32.c
*
* This encodes the mouse scroll direction and keyboard modifiers into
* g_nMouseClick, and the mouse position into g_xMouse and g_yMouse
*
* The direction of the scroll is decoded from two fields of the win32 console
* mouse event record;
* 1. The axis - vertical or horizontal flag - from dwEventFlags, and
* 2. The sign - positive or negative (aka delta flag) - from dwButtonState
*
* When scroll axis is HORIZONTAL
* - If the high word of the dwButtonState member contains a positive
* value, the wheel was rotated to the right.
* - Otherwise, the wheel was rotated to the left.
* When scroll axis is VERTICAL
* - If the high word of the dwButtonState member contains a positive value,
* the wheel was rotated forward, away from the user.
* - Otherwise, the wheel was rotated backward, toward the user.
*/
static void
decode_mouse_wheel(MOUSE_EVENT_RECORD *pmer)
{
win_T *wp;
int horizontal = (pmer->dwEventFlags == MOUSE_HWHEELED);
int zDelta = pmer->dwButtonState;
g_xMouse = pmer->dwMousePosition.X;
g_yMouse = pmer->dwMousePosition.Y;
#ifdef FEAT_PROP_POPUP
int lcol;
int lrow;
lcol = g_xMouse;
lrow = g_yMouse;
wp = mouse_find_win(&lrow, &lcol, FAIL_POPUP);
if (wp != NULL && popup_is_popup(wp))
{
g_nMouseClick = -1;
cmdarg_T cap;
oparg_T oa;
CLEAR_FIELD(cap);
clear_oparg(&oa);
cap.oap = &oa;
if (horizontal)
{
cap.arg = zDelta < 0 ? MSCR_LEFT : MSCR_RIGHT;
cap.cmdchar = zDelta < 0 ? K_MOUSELEFT : K_MOUSERIGHT;
}
else
{
cap.cmdchar = zDelta < 0 ? K_MOUSEUP : K_MOUSEDOWN;
cap.arg = zDelta < 0 ? MSCR_UP : MSCR_DOWN;
}
// Mouse hovers over popup window, scroll it if possible.
mouse_row = wp->w_winrow;
mouse_col = wp->w_wincol;
nv_mousescroll(&cap);
update_screen(0);
setcursor();
out_flush();
return;
}
#endif
mouse_col = g_xMouse;
mouse_row = g_yMouse;
char_u modifiers = 0;
char_u direction = 0;
// Decode the direction into an event that Vim can process
if (horizontal)
direction = zDelta >= 0 ? KE_MOUSELEFT : KE_MOUSERIGHT;
else
direction = zDelta >= 0 ? KE_MOUSEDOWN : KE_MOUSEUP;
// Decode the win32 console key modifers into Vim mouse modifers.
if (pmer->dwControlKeyState & SHIFT_PRESSED)
modifiers |= MOD_MASK_SHIFT; //MOUSE_SHIFT;
if (pmer->dwControlKeyState & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
modifiers |= MOD_MASK_CTRL; //MOUSE_CTRL;
if (pmer->dwControlKeyState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
modifiers |= MOD_MASK_ALT; // MOUSE_ALT;
// add (bitwise or) the scroll direction and the key modifier chars
// together.
g_nMouseClick = ((direction << 8) | modifiers);
return;
}
/*
* Decode a MOUSE_EVENT. If it's a valid event, return MOUSE_LEFT,
* MOUSE_MIDDLE, or MOUSE_RIGHT for a click; MOUSE_DRAG for a mouse
@@ -1304,6 +1398,13 @@ decode_mouse_event(
if (g_nMouseClick != -1)
return TRUE;
if (pmer->dwEventFlags == MOUSE_WHEELED
|| pmer->dwEventFlags == MOUSE_HWHEELED)
{
decode_mouse_wheel(pmer);
return TRUE; // we now should have a mouse scroll in g_nMouseClick
}
nButton = -1;
g_xMouse = pmer->dwMousePosition.X;
g_yMouse = pmer->dwMousePosition.Y;
@@ -1939,12 +2040,34 @@ mch_inchar(
fprintf(fdDump, "{%02x @ %d, %d}",
g_nMouseClick, g_xMouse, g_yMouse);
# endif
typeahead[typeaheadlen++] = ESC + 128;
typeahead[typeaheadlen++] = 'M';
typeahead[typeaheadlen++] = g_nMouseClick;
typeahead[typeaheadlen++] = g_xMouse + '!';
typeahead[typeaheadlen++] = g_yMouse + '!';
g_nMouseClick = -1;
char_u modifiers = ((char_u *)(&g_nMouseClick))[0];
char_u scroll_dir = ((char_u *)(&g_nMouseClick))[1];
if (scroll_dir == KE_MOUSEDOWN
|| scroll_dir == KE_MOUSEUP
|| scroll_dir == KE_MOUSELEFT
|| scroll_dir == KE_MOUSERIGHT)
{
if (modifiers > 0)
{
typeahead[typeaheadlen++] = CSI;
typeahead[typeaheadlen++] = KS_MODIFIER;
typeahead[typeaheadlen++] = modifiers;
}
typeahead[typeaheadlen++] = CSI;
typeahead[typeaheadlen++] = KS_EXTRA;
typeahead[typeaheadlen++] = scroll_dir;
g_nMouseClick = -1;
}
else
{
typeahead[typeaheadlen++] = ESC + 128;
typeahead[typeaheadlen++] = 'M';
typeahead[typeaheadlen++] = g_nMouseClick;
typeahead[typeaheadlen++] = g_xMouse + '!';
typeahead[typeaheadlen++] = g_yMouse + '!';
g_nMouseClick = -1;
}
}
else
{
@@ -8361,7 +8484,7 @@ stop_timeout(void)
{
if (timer_active)
{
BOOL ret = DeleteTimerQueueTimer(NULL, timer_handle, NULL);
BOOL ret = DeleteTimerQueueTimer(NULL, timer_handle, NULL);
timer_active = FALSE;
if (!ret && GetLastError() != ERROR_IO_PENDING)
{