From 8a856b7707cb7353df403b8d22175f7f39466954 Mon Sep 17 00:00:00 2001 From: Joachim Henze Date: Tue, 1 Dec 2020 16:43:09 +0100 Subject: [PATCH] [0.4.10][WIN32SS] Fix scrollbar bug CORE-15557 & CORE-13986 Fixes CORE-13986 "Wise Installer draws scrollbars enabled while they should be drawn disabled" by porting back 0.4.11-dev-586-g 929a2c6 (the mentioned CORE-ID in that commit was wrong due to typo) which requires to pick also 0.4.14-dev-1167-g 8bb9434 to prevent the first fix introducing regression CORE-16721 "Scrolling by pressing the scrollbar arrows does not draw the arrows as pressed" and finally port back 0.4.14-dev-243-g 19fbdda to fix CORE-15557 "disabled scrollbars being clickable" In sum this brings the scrollbar code to the state of 0.4.13-release-0-g 4ee3778 --- win32ss/user/ntuser/scrollbar.c | 25 +++++++++- win32ss/user/user32/controls/scrollbar.c | 63 +++++++++++++++++++----- 2 files changed, 75 insertions(+), 13 deletions(-) diff --git a/win32ss/user/ntuser/scrollbar.c b/win32ss/user/ntuser/scrollbar.c index 3b2023f9326..565987bb4b8 100644 --- a/win32ss/user/ntuser/scrollbar.c +++ b/win32ss/user/ntuser/scrollbar.c @@ -58,6 +58,10 @@ DBG_DEFAULT_CHANNEL(UserScrollbar); /* FUNCTIONS *****************************************************************/ +BOOL APIENTRY +IntEnableScrollBar(BOOL Horz, PSCROLLBARINFO Info, UINT wArrows); + + /* Ported from WINE20020904 */ /* Compute the scroll bar rectangle, in drawing coordinates (i.e. client coords for SB_CTL, window coords for SB_VERT and * SB_HORZ). 'arrowSize' returns the width or height of an arrow (depending on * the orientation of the scrollbar), @@ -203,6 +207,14 @@ IntCalculateThumb(PWND Wnd, LONG idObject, PSCROLLBARINFO psbi, PSBDATA pSBData) psbi->xyThumbBottom = 0; ThumbPos = Thumb; } + else if (psbi->rgstate[SBRG_TOPRIGHTBTN] == STATE_SYSTEM_UNAVAILABLE && + psbi->rgstate[SBRG_BOTTOMLEFTBTN] == STATE_SYSTEM_UNAVAILABLE && + pSBData->posMin >= (int)(pSBData->posMax - max(pSBData->page - 1, 0))) + { + /* Nothing to scroll */ + psbi->xyThumbTop = 0; + psbi->xyThumbBottom = 0; + } else { ThumbBox = pSBData->page ? MINTRACKTHUMB : UserGetSystemMetrics(SM_CXHTHUMB); @@ -525,7 +537,6 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) OldPos = Info->nPos; Info->nPos = lpsi->nPos; pSBData->pos = lpsi->nPos; - bChangeParams = TRUE; } } @@ -599,11 +610,15 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) else /* Show and enable scroll-bar only if no page only changed. */ if (lpsi->fMask != SIF_PAGE) { - new_flags = ESB_ENABLE_BOTH; if ((nBar != SB_CTL) && bChangeParams) { + new_flags = ESB_ENABLE_BOTH; action |= SA_SSI_SHOW; } + else if (nBar == SB_CTL) + { + new_flags = ESB_ENABLE_BOTH; + } } if (Window->pSBInfo->WSBflags != new_flags) /* Check arrow flags */ @@ -642,6 +657,12 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME); } */ } + + if (bChangeParams && (nBar == SB_HORZ || nBar == SB_VERT) && (lpsi->fMask & SIF_DISABLENOSCROLL)) + { + IntEnableScrollBar(nBar == SB_HORZ, psbi, Window->pSBInfo->WSBflags); + } + /* Return current position */ return lpsi->fMask & SIF_PREVIOUSPOS ? OldPos : pSBData->pos; } diff --git a/win32ss/user/user32/controls/scrollbar.c b/win32ss/user/user32/controls/scrollbar.c index 3eb02429610..8e5983e5d7b 100644 --- a/win32ss/user/user32/controls/scrollbar.c +++ b/win32ss/user/user32/controls/scrollbar.c @@ -318,6 +318,26 @@ IntGetScrollBarInfo(HWND Wnd, INT Bar, PSCROLLBARINFO ScrollBarInfo) return NtUserGetScrollBarInfo(Wnd, IntScrollGetObjectId(Bar), ScrollBarInfo); } +static VOID FASTCALL +IntUpdateScrollArrows(HWND Wnd, HDC hDC, PSCROLLBARINFO ScrollBarInfo, + SETSCROLLBARINFO *info, INT SBType, INT Arrow, + BOOL Vertical, BOOL Pressed) +{ + if (Pressed) + { + ScrollBarInfo->rgstate[Arrow] |= STATE_SYSTEM_PRESSED; + } + else + { + ScrollBarInfo->rgstate[Arrow] &= ~STATE_SYSTEM_PRESSED; + } + /* Update arrow state */ + info->rgstate[Arrow] = ScrollBarInfo->rgstate[Arrow]; + NtUserSetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), info); + + IntDrawScrollArrows(hDC, ScrollBarInfo, Vertical); +} + void IntDrawScrollBar(HWND Wnd, HDC DC, INT Bar) { @@ -831,9 +851,11 @@ IntScrollHandleScrollEvent(HWND Wnd, INT SBType, UINT Msg, POINT Pt) PrevPt = Pt; if (SBType == SB_CTL && (GetWindowLongPtrW(Wnd, GWL_STYLE) & WS_TABSTOP)) SetFocus(Wnd); SetCapture(Wnd); - ScrollBarInfo.rgstate[ScrollTrackHitTest] |= STATE_SYSTEM_PRESSED; - NewInfo.rgstate[ScrollTrackHitTest] = ScrollBarInfo.rgstate[ScrollTrackHitTest]; - NtUserSetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), &NewInfo); + /* Don't update scrollbar if disabled. */ + if (ScrollBarInfo.rgstate[ScrollTrackHitTest] != STATE_SYSTEM_UNAVAILABLE) + { + IntUpdateScrollArrows (Wnd, Dc, &ScrollBarInfo, &NewInfo, SBType, ScrollTrackHitTest, Vertical, TRUE); + } break; case WM_MOUSEMOVE: @@ -846,13 +868,12 @@ IntScrollHandleScrollEvent(HWND Wnd, INT SBType, UINT Msg, POINT Pt) ReleaseCapture(); /* if scrollbar has focus, show back caret */ if (Wnd == GetFocus()) ShowCaret(Wnd); - ScrollBarInfo.rgstate[ScrollTrackHitTest] &= ~STATE_SYSTEM_PRESSED; - NewInfo.rgstate[ScrollTrackHitTest] = ScrollBarInfo.rgstate[ScrollTrackHitTest]; - NtUserSetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), &NewInfo); - - IntDrawScrollInterior(Wnd,Dc,SBType,Vertical,&ScrollBarInfo); - IntDrawScrollArrows(Dc, &ScrollBarInfo, Vertical); - + /* Don't update scrollbar if disabled. */ + if (ScrollBarInfo.rgstate[ScrollTrackHitTest] != STATE_SYSTEM_UNAVAILABLE) + { + IntUpdateScrollArrows (Wnd, Dc, &ScrollBarInfo, &NewInfo, SBType, ScrollTrackHitTest, Vertical, FALSE); + IntDrawScrollInterior(Wnd,Dc,SBType,Vertical,&ScrollBarInfo); + } break; case WM_SYSTIMER: @@ -883,9 +904,17 @@ IntScrollHandleScrollEvent(HWND Wnd, INT SBType, UINT Msg, POINT Pt) SetSystemTimer(Wnd, SCROLL_TIMER, (WM_LBUTTONDOWN == Msg) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, (TIMERPROC) NULL); + if (ScrollBarInfo.rgstate[ScrollTrackHitTest] != STATE_SYSTEM_UNAVAILABLE) + { + if (!(ScrollBarInfo.rgstate[ScrollTrackHitTest] &= STATE_SYSTEM_PRESSED)) + { + IntUpdateScrollArrows (Wnd, Dc, &ScrollBarInfo, &NewInfo, SBType, ScrollTrackHitTest, Vertical, TRUE); + } + } } else { + IntUpdateScrollArrows (Wnd, Dc, &ScrollBarInfo, &NewInfo, SBType, ScrollTrackHitTest, Vertical, FALSE); KillSystemTimer(Wnd, SCROLL_TIMER); } break; @@ -985,8 +1014,20 @@ IntScrollHandleScrollEvent(HWND Wnd, INT SBType, UINT Msg, POINT Pt) SetSystemTimer(Wnd, SCROLL_TIMER, (WM_LBUTTONDOWN == Msg) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, (TIMERPROC) NULL); + if (ScrollBarInfo.rgstate[ScrollTrackHitTest] != STATE_SYSTEM_UNAVAILABLE) + { + if (!(ScrollBarInfo.rgstate[ScrollTrackHitTest] &= STATE_SYSTEM_PRESSED)) + { + TRACE("Set Arrow\n"); + IntUpdateScrollArrows (Wnd, Dc, &ScrollBarInfo, &NewInfo, SBType, ScrollTrackHitTest, Vertical, TRUE); + } + } } - else KillSystemTimer(Wnd, SCROLL_TIMER); + else + { + IntUpdateScrollArrows (Wnd, Dc, &ScrollBarInfo, &NewInfo, SBType, ScrollTrackHitTest, Vertical, FALSE); + KillSystemTimer(Wnd, SCROLL_TIMER); + } break; }