On Tue, 6 Jun 2023 16:07:53 GMT, Alexey Ivanov <[email protected]> wrote:
> **Problem description** > > If you grab the thumb of the scroll bar of `ScrollPane` and drag it slowly > and continuously up and down, you'll notice the UI stops rendering correctly: > the child component of the scroll pane will render on the left of the frame > itself, the inside of the scroll pane will be filled with the background > color of its child component. > > **Root cause** > > AWT calls the > [`::SetScrollInfo`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setscrollinfo) > function on EDT when AWT processes scroll bar tracking events. This Windows > API is not thread-safe, calling this function on an incorrect thread leads to > leaking GDI objects. > > When the process reaches the limit on the number of GDI objects, it cannot > create new GDI objects, which results in rendering issues. > > **Fix** > > To resolve the problem, I modified the code so that `::SetScrollInfo` and > [`::GetScrollInfo`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getscrollinfo) > are always called on the toolkit thread, all AWT components are created on > the toolkit thread. > > An automatic test is provided. The test scrolls the vertical scroll bar up > and down. Then the test takes a screenshot. When the bug is reproduced, the > robot cannot create new GDI objects to capture the screenshot and it throws > `OutOfMemoryError`. src/java.desktop/windows/native/libawt/windows/awt_ScrollPane.cpp line 704: > 702: gos->orient = orient; > 703: > 704: return > static_cast<jint>(reinterpret_cast<INT_PTR>(AwtToolkit::GetInstance().InvokeFunction( So this needs to block until the toolkit thread can process this and return, but since its directly called from Java (ie we are in a JNI method) I think this is likely fine. src/java.desktop/windows/native/libawt/windows/awt_ScrollPane.cpp line 745: > 743: ssps->y = y; > 744: > 745: > AwtToolkit::GetInstance().InvokeFunctionLater(AwtScrollPane::_SetScrollPos, > ssps); Whereas in the _GetOffset case above, you clearly need to wait until the result is returned - I guess you didn't see a need to block here ? Or the case below ? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14338#discussion_r1220105799 PR Review Comment: https://git.openjdk.org/jdk/pull/14338#discussion_r1220107433
