mirror of
https://github.com/vim/vim.git
synced 2025-10-04 05:25:06 -04:00
patch 8.2.1922: Win32: scrolling problems when part of window is off-screen
Problem: Win32: scrolling doesn't work properly when part of window is off-screen. Solution: Fall back to GDI scrolling if part of the window is off-screen. Handle multi-monitor setup better. (Ken Takata, closes #7219)
This commit is contained in:
@@ -2985,6 +2985,42 @@ gui_mch_flash(int msec)
|
|||||||
InvertRect(s_hdc, &rc);
|
InvertRect(s_hdc, &rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the specified point is on-screen. (multi-monitor aware)
|
||||||
|
*/
|
||||||
|
static BOOL
|
||||||
|
is_point_onscreen(int x, int y)
|
||||||
|
{
|
||||||
|
POINT pt = {x, y};
|
||||||
|
|
||||||
|
return MonitorFromPoint(pt, MONITOR_DEFAULTTONULL) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the whole area of the specified window is on-screen.
|
||||||
|
*
|
||||||
|
* Note about DirectX: Windows 10 1809 or above no longer maintains image of
|
||||||
|
* the window portion that is off-screen. Scrolling by DWriteContext_Scroll()
|
||||||
|
* only works when the whole window is on-screen.
|
||||||
|
*/
|
||||||
|
static BOOL
|
||||||
|
is_window_onscreen(HWND hwnd)
|
||||||
|
{
|
||||||
|
RECT rc;
|
||||||
|
|
||||||
|
GetWindowRect(hwnd, &rc);
|
||||||
|
|
||||||
|
if (!is_point_onscreen(rc.left, rc.top))
|
||||||
|
return FALSE;
|
||||||
|
if (!is_point_onscreen(rc.left, rc.bottom))
|
||||||
|
return FALSE;
|
||||||
|
if (!is_point_onscreen(rc.right, rc.top))
|
||||||
|
return FALSE;
|
||||||
|
if (!is_point_onscreen(rc.right, rc.bottom))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return flags used for scrolling.
|
* Return flags used for scrolling.
|
||||||
* The SW_INVALIDATE is required when part of the window is covered or
|
* The SW_INVALIDATE is required when part of the window is covered or
|
||||||
@@ -2996,15 +3032,12 @@ get_scroll_flags(void)
|
|||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
RECT rcVim, rcOther, rcDest;
|
RECT rcVim, rcOther, rcDest;
|
||||||
|
|
||||||
GetWindowRect(s_hwnd, &rcVim);
|
// Check if the window is (partly) off-screen.
|
||||||
|
if (!is_window_onscreen(s_hwnd))
|
||||||
// Check if the window is partly above or below the screen. We don't care
|
|
||||||
// about partly left or right of the screen, it is not relevant when
|
|
||||||
// scrolling up or down.
|
|
||||||
if (rcVim.top < 0 || rcVim.bottom > GetSystemMetrics(SM_CYFULLSCREEN))
|
|
||||||
return SW_INVALIDATE;
|
return SW_INVALIDATE;
|
||||||
|
|
||||||
// Check if there is an window (partly) on top of us.
|
// Check if there is an window (partly) on top of us.
|
||||||
|
GetWindowRect(s_hwnd, &rcVim);
|
||||||
for (hwnd = s_hwnd; (hwnd = GetWindow(hwnd, GW_HWNDPREV)) != (HWND)0; )
|
for (hwnd = s_hwnd; (hwnd = GetWindow(hwnd, GW_HWNDPREV)) != (HWND)0; )
|
||||||
if (IsWindowVisible(hwnd))
|
if (IsWindowVisible(hwnd))
|
||||||
{
|
{
|
||||||
@@ -3046,14 +3079,17 @@ gui_mch_delete_lines(
|
|||||||
rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
|
rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
|
||||||
|
|
||||||
#if defined(FEAT_DIRECTX)
|
#if defined(FEAT_DIRECTX)
|
||||||
if (IS_ENABLE_DIRECTX())
|
if (IS_ENABLE_DIRECTX() && is_window_onscreen(s_hwnd))
|
||||||
{
|
{
|
||||||
DWriteContext_Scroll(s_dwc, 0, -num_lines * gui.char_height, &rc);
|
DWriteContext_Scroll(s_dwc, 0, -num_lines * gui.char_height, &rc);
|
||||||
DWriteContext_Flush(s_dwc);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
#if defined(FEAT_DIRECTX)
|
||||||
|
if (IS_ENABLE_DIRECTX())
|
||||||
|
DWriteContext_Flush(s_dwc);
|
||||||
|
#endif
|
||||||
intel_gpu_workaround();
|
intel_gpu_workaround();
|
||||||
ScrollWindowEx(s_textArea, 0, -num_lines * gui.char_height,
|
ScrollWindowEx(s_textArea, 0, -num_lines * gui.char_height,
|
||||||
&rc, &rc, NULL, NULL, get_scroll_flags());
|
&rc, &rc, NULL, NULL, get_scroll_flags());
|
||||||
@@ -3088,14 +3124,17 @@ gui_mch_insert_lines(
|
|||||||
rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
|
rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
|
||||||
|
|
||||||
#if defined(FEAT_DIRECTX)
|
#if defined(FEAT_DIRECTX)
|
||||||
if (IS_ENABLE_DIRECTX())
|
if (IS_ENABLE_DIRECTX() && is_window_onscreen(s_hwnd))
|
||||||
{
|
{
|
||||||
DWriteContext_Scroll(s_dwc, 0, num_lines * gui.char_height, &rc);
|
DWriteContext_Scroll(s_dwc, 0, num_lines * gui.char_height, &rc);
|
||||||
DWriteContext_Flush(s_dwc);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
#if defined(FEAT_DIRECTX)
|
||||||
|
if (IS_ENABLE_DIRECTX())
|
||||||
|
DWriteContext_Flush(s_dwc);
|
||||||
|
#endif
|
||||||
intel_gpu_workaround();
|
intel_gpu_workaround();
|
||||||
// The SW_INVALIDATE is required when part of the window is covered or
|
// The SW_INVALIDATE is required when part of the window is covered or
|
||||||
// off-screen. How do we avoid it when it's not needed?
|
// off-screen. How do we avoid it when it's not needed?
|
||||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1922,
|
||||||
/**/
|
/**/
|
||||||
1921,
|
1921,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user