Skip to content

Commit 185577e

Browse files
committed
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)
1 parent dcdd42a commit 185577e

2 files changed

Lines changed: 51 additions & 10 deletions

File tree

src/gui_w32.c

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2985,6 +2985,42 @@ gui_mch_flash(int msec)
29852985
InvertRect(s_hdc, &rc);
29862986
}
29872987

2988+
/*
2989+
* Check if the specified point is on-screen. (multi-monitor aware)
2990+
*/
2991+
static BOOL
2992+
is_point_onscreen(int x, int y)
2993+
{
2994+
POINT pt = {x, y};
2995+
2996+
return MonitorFromPoint(pt, MONITOR_DEFAULTTONULL) != NULL;
2997+
}
2998+
2999+
/*
3000+
* Check if the whole area of the specified window is on-screen.
3001+
*
3002+
* Note about DirectX: Windows 10 1809 or above no longer maintains image of
3003+
* the window portion that is off-screen. Scrolling by DWriteContext_Scroll()
3004+
* only works when the whole window is on-screen.
3005+
*/
3006+
static BOOL
3007+
is_window_onscreen(HWND hwnd)
3008+
{
3009+
RECT rc;
3010+
3011+
GetWindowRect(hwnd, &rc);
3012+
3013+
if (!is_point_onscreen(rc.left, rc.top))
3014+
return FALSE;
3015+
if (!is_point_onscreen(rc.left, rc.bottom))
3016+
return FALSE;
3017+
if (!is_point_onscreen(rc.right, rc.top))
3018+
return FALSE;
3019+
if (!is_point_onscreen(rc.right, rc.bottom))
3020+
return FALSE;
3021+
return TRUE;
3022+
}
3023+
29883024
/*
29893025
* Return flags used for scrolling.
29903026
* The SW_INVALIDATE is required when part of the window is covered or
@@ -2996,15 +3032,12 @@ get_scroll_flags(void)
29963032
HWND hwnd;
29973033
RECT rcVim, rcOther, rcDest;
29983034

2999-
GetWindowRect(s_hwnd, &rcVim);
3000-
3001-
// Check if the window is partly above or below the screen. We don't care
3002-
// about partly left or right of the screen, it is not relevant when
3003-
// scrolling up or down.
3004-
if (rcVim.top < 0 || rcVim.bottom > GetSystemMetrics(SM_CYFULLSCREEN))
3035+
// Check if the window is (partly) off-screen.
3036+
if (!is_window_onscreen(s_hwnd))
30053037
return SW_INVALIDATE;
30063038

30073039
// Check if there is an window (partly) on top of us.
3040+
GetWindowRect(s_hwnd, &rcVim);
30083041
for (hwnd = s_hwnd; (hwnd = GetWindow(hwnd, GW_HWNDPREV)) != (HWND)0; )
30093042
if (IsWindowVisible(hwnd))
30103043
{
@@ -3046,14 +3079,17 @@ gui_mch_delete_lines(
30463079
rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
30473080

30483081
#if defined(FEAT_DIRECTX)
3049-
if (IS_ENABLE_DIRECTX())
3082+
if (IS_ENABLE_DIRECTX() && is_window_onscreen(s_hwnd))
30503083
{
30513084
DWriteContext_Scroll(s_dwc, 0, -num_lines * gui.char_height, &rc);
3052-
DWriteContext_Flush(s_dwc);
30533085
}
30543086
else
30553087
#endif
30563088
{
3089+
#if defined(FEAT_DIRECTX)
3090+
if (IS_ENABLE_DIRECTX())
3091+
DWriteContext_Flush(s_dwc);
3092+
#endif
30573093
intel_gpu_workaround();
30583094
ScrollWindowEx(s_textArea, 0, -num_lines * gui.char_height,
30593095
&rc, &rc, NULL, NULL, get_scroll_flags());
@@ -3088,14 +3124,17 @@ gui_mch_insert_lines(
30883124
rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
30893125

30903126
#if defined(FEAT_DIRECTX)
3091-
if (IS_ENABLE_DIRECTX())
3127+
if (IS_ENABLE_DIRECTX() && is_window_onscreen(s_hwnd))
30923128
{
30933129
DWriteContext_Scroll(s_dwc, 0, num_lines * gui.char_height, &rc);
3094-
DWriteContext_Flush(s_dwc);
30953130
}
30963131
else
30973132
#endif
30983133
{
3134+
#if defined(FEAT_DIRECTX)
3135+
if (IS_ENABLE_DIRECTX())
3136+
DWriteContext_Flush(s_dwc);
3137+
#endif
30993138
intel_gpu_workaround();
31003139
// The SW_INVALIDATE is required when part of the window is covered or
31013140
// off-screen. How do we avoid it when it's not needed?

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,8 @@ static char *(features[]) =
750750

751751
static int included_patches[] =
752752
{ /* Add new patch number below this line */
753+
/**/
754+
1922,
753755
/**/
754756
1921,
755757
/**/

0 commit comments

Comments
 (0)