moving a window isn't smooth (Issue #23160)

101 views
Skip to first unread message

charrir

unread,
Jan 19, 2023, 10:49:27 AM1/19/23
to wx-...@googlegroups.com, Subscribed

Description

When I move the window around the screen, the window follows very slowly the mouse and even keeps moving after I stopped dragging the window around. Is that simply due to the amount of widgets or is there another reason? Scrolling etc. works totally fine.
What I noticed is, that a lot of time is spent in USER32.dll but I couldn't really figure out what happens there.
I tried to install some filter to intercept the WM_MOVE event but this didnt help.

Here is a image of the call stack:

image

See some simple example below (not my actual program but I also have some child wxPanels, each with a few widgets):

#include <wx/wx.h>

namespace Examples {
    class Frame : public wxFrame {
        public:
            Frame() : wxFrame(nullptr, wxID_ANY, "StaticBoxSizerVertical example") {
                scroll->SetScrollRate(5, 5);
                scroll->SetSizer(boxScroll);
                for (int i = 0; i < 1000; i++)
                {
                    sizer.emplace_back(new wxBoxSizer(wxVERTICAL));
                    panels.emplace_back(new wxPanel(scroll, wxID_ANY));
                    labels.emplace_back(new wxStaticText(panels.at(i), wxID_ANY, "Label: " + std::to_string(i)));

                    sizer.at(i)->Add(labels.at(i));
                    panels.at(i)->SetSizer(sizer.at(i));
                    boxScroll->Add(panels.at(i));
                }


                SetSizerAndFit(boxSizerVertical);
                SetSize(300, 300);
                scroll->SetSize(300,300);
            }

        private:
            wxBoxSizer* boxSizerVertical = new wxBoxSizer(wxVERTICAL);
            wxScrolledWindow* scroll = new wxScrolledWindow(this);
            wxBoxSizer* boxScroll = new wxBoxSizer(wxVERTICAL);
            std::vector<wxPanel*> panels;
            std::vector<wxStaticText*> labels;
            std::vector<wxSizer*> sizer;
    };

    class Application : public wxApp {
            bool OnInit() override {
                (new Frame())->Show();
                return true;
            }
    };
}

wxIMPLEMENT_APP(Examples::Application);

Platform and version information

  • wxWidgets version you use: 3.2.1
  • wxWidgets port you use: wxMSW
  • OS and its version: Windows 10


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23160@github.com>

PB

unread,
Jan 19, 2023, 12:21:59 PM1/19/23
to wx-...@googlegroups.com, Subscribed

FWIW, I can reproduce the odd behaviour (also in the master).

The oddity (i.e., the window gaining inertia instead of being "glued" to the mouse cursor) starts appearing around i = 250, particularly when the window motion is circular. The larger the circle and the number of controls, the larger the inertia. It can still be reproduced even when scroll is not used and the panels are created as direct children of the frame. The issue manifests even when static texts are not created too.

The sizer and window count are rather high for a single frame but aside that, I cannot see anything really wrong with the code (unused boxSizerVertical aside). @charrir what is the approx. count of the windows in the frame in your actual application: Is it really in higher hundreds or more?

In fact, I can reproduce it with just this (may require doing large and fast circles when moving the window)

diff --git a/samples/minimal/minimal.cpp b/samples/minimal/minimal.cpp
index 501caf9096..ba1f1cd943 100644
--- a/samples/minimal/minimal.cpp
+++ b/samples/minimal/minimal.cpp
@@ -170,6 +170,10 @@ MyFrame::MyFrame(const wxString& title)
     SetSizer(sizer);
 #endif // wxUSE_MENUBAR/!wxUSE_MENUBAR
 
+    SetSizer(new wxBoxSizer(wxVERTICAL));
+    for ( size_t i = 0; i < 1000; ++i )
+        GetSizer()->Add(new wxPanel(this));
+
 #if wxUSE_STATUSBAR
     // create a status bar just for fun (by default with 1 pane only)
     CreateStatusBar(2);


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23160/1397339150@github.com>

PB

unread,
Jan 19, 2023, 12:46:41 PM1/19/23
to wx-...@googlegroups.com, Subscribed

Actually, I think I can reproduce it with pure Win32 application running this basic code:

#include <windows.h>

void FatalError(LPCWSTR errorMessage)
{
    MessageBox(nullptr, errorMessage, L"Fatal error", MB_OK | MB_ICONERROR);
    exit(-1);
}

LRESULT CALLBACK MainFrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    if ( message == WM_DESTROY )
    {
        PostQuitMessage(0);
        return 0;
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}


HWND CreateMainFrame(HINSTANCE hInstance)
{
    LPCWSTR className = L"TestFrame";

    WNDCLASSEX wcex = {0};

    wcex.cbSize         = sizeof(WNDCLASSEX);
    wcex.lpfnWndProc    = MainFrameWndProc;
    wcex.hInstance      = hInstance;
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszClassName  = className;

    if ( !RegisterClassEx(&wcex) )
        FatalError(L"Could not register the class for the application window.");

    HWND hFrame = CreateWindow(className, L"Test Many Children", WS_OVERLAPPEDWINDOW,
                    CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, nullptr, nullptr, hInstance, nullptr);
    if ( !hFrame )
      FatalError(L"Could not create the application window.");

    for ( size_t i = 0; i < 1000; ++i )
    {
        HWND hChild = CreateWindow(L"STATIC",  L"", WS_CHILD | WS_VISIBLE | SS_GRAYRECT,
                            10, 10, 20, 30, hFrame, nullptr, hInstance, nullptr);

        if ( !hChild )
             FatalError(L"Could not create a child.");
    }

    return hFrame;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow)
{
    HWND hMainFrame = CreateMainFrame(hInstance);

    ShowWindow(hMainFrame, nCmdShow);
    UpdateWindow(hMainFrame);
    MSG msg;

    while ( GetMessage(&msg, nullptr, 0, 0) )
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}

So it may be a Windows (I am on the latest Windows 10) bug or even a (broken?) feature...


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23160/1397374445@github.com>

VZ

unread,
Jan 19, 2023, 3:35:40 PM1/19/23
to wx-...@googlegroups.com, Subscribed

We discussed something similar in the past, although the only thing I could find quickly is #15766 which is not quite the same.

Anyhow, I'm afraid I still don't know what to do about it, other than the obvious advice to not create that many controls...


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23160/1397569259@github.com>

VZ

unread,
Jan 19, 2023, 3:44:57 PM1/19/23
to wx-...@googlegroups.com, Subscribed

Closed #23160 as completed.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issue/23160/issue_event/8316026569@github.com>

VZ

unread,
Jan 19, 2023, 3:44:58 PM1/19/23
to wx-...@googlegroups.com, Subscribed

Sorry, on further thought, it does look like exactly the same issue because it's just dwm.exe lagging, so I'm closing this one as duplicate. The other issue contains some workarounds...


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23160/1397579459@github.com>

PB

unread,
Jan 19, 2023, 4:11:40 PM1/19/23
to wx-...@googlegroups.com, Subscribed

I may be missing something, but this issue is not about scrolling at all, just moving a window around quickly? Scrolling in the code posted in the OP actually works flawlessly (but the scrollable area is not very large there)....

Of course, the root cause still can be DWM lag: As shown with the pure Win32 code, the issue is not in wxWidgets.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23160/1397615675@github.com>

VZ

unread,
Jan 19, 2023, 5:02:57 PM1/19/23
to wx-...@googlegroups.com, Subscribed

I thought it was scrolling too initially, but, finally, I think it's just creating many controls inside a scrolled window which triggers it. Apparently DWM recalculates something for all windows, even not currently visible ones, for each window move...


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23160/1397668041@github.com>

charrir

unread,
Jan 20, 2023, 3:27:38 AM1/20/23
to wx-...@googlegroups.com, Subscribed

@PBfordev I've got approximately 2000 Widgets in my main apllication and I thought that this shouldn't be a problem if not all of them are visible at the same time. I also tried freezing them but it didn't help.
I thought that only I had the problem because I didn't find anything at all on that topic except that issue about the scrolled window which wasn't really the same problem and that made me curious.
Thanks for your replies!


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23160/1398060353@github.com>

Andy Robinson

unread,
Jan 20, 2023, 4:41:01 AM1/20/23
to wx-...@googlegroups.com
On 19/01/2023 15:49, charrir wrote:
> When I move the window around the screen, the window follows very slowly
> the mouse and even keeps moving after I stopped dragging the window
> around. Is that simply due to the amount of widgets or is there another
> reason? Scrolling etc. works totally fine.
Obvious question - what happens when you drag the windows of other
non-wx applications? Do they move smoothly?

Regards,
Andy Robinson, Seventh String Software, www.seventhstring.com

Eric Jensen

unread,
Jan 20, 2023, 6:09:01 AM1/20/23
to wx-...@googlegroups.com, Subscribed

Actually, I think I can reproduce it with pure Win32 application running this basic code:

I can't reproduce the behavior with your code.
Windows 10, today's updates, relatively old machine: i5-4670, GTX-970, 16GB RAM

I only see a slowdown when i move the window partly off-screen and then back, so that all 1000 windows get repainted, but this seems normal to me.

So, there must still be other factors involved.

BTW: I found this comment on MSDN:

Because DWM maintains a complete copy of your window offscreen, if you do a full invalidate, it's going to send a WM_PAINT to every control, whether they are visible or not. If you only invalidate the visible region, it should only send WM_PAINT to the controls that need repainting.
https://social.msdn.microsoft.com/Forums/azure/en-US/fab161e9-ca99-4af2-873e-ea4aa5de2c22/desktop-window-manager-dwmexe-grinding-pc-to-a-halt-in-windows-10?forum=windowsgeneraldevelopmentissues


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23160/1398233542@github.com>

PB

unread,
Jan 20, 2023, 6:36:27 AM1/20/23
to wx-...@googlegroups.com, Subscribed

Funnily enough, I tried all three code examples from above on a different PC (CPU Intel Core i5 7600 - base clock 3.5 GHz, the other one was AMD Ryzen R5 2600 - base clock 3.4 GHz; the AMD one has MUCH faster GPU but it does not seem to matter here):

  1. The code from the OP: Can reproduce. Can also still reproduce when wxScrolled is not used and panels are created as direct children of the frame. However, on the AMD PC the issue starts to manifest when around i = 250, on the Intel one I needed to go to 500+.
  2. Patch to the Minimal sample: Could not reproduce.
  3. Pure Win32: Could not reproduce.

In all three cases on the Intel PC dwm.exe CPU usage reported in the Task Manager goes over 25% and the CPU clock from under 2 GHz to over 3.5 GHz; however, the lag is observable only with #3 (where the clock nears 4 GHz and probably still not fast enough for the task).

I am not aware of any application using hundreds, let alone thousands, children HWNDs at once, I tried a few random applications (MSVS, Total Commander, MS Word, File Explorer) but it did not make dwm.exe spike at all.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23160/1398258892@github.com>

charrir

unread,
Jan 20, 2023, 7:19:29 AM1/20/23
to wx-...@googlegroups.com, Subscribed

With the pure win32 I also experience lag.
Guess the only two options I have is either to live with the lag or to reduce the widgets somehow.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23160/1398305822@github.com>

VZ

unread,
Jan 20, 2023, 8:22:38 AM1/20/23
to wx-...@googlegroups.com, Subscribed

Have you tried the workaround from the other issue? It's not really a solution as you can't ask all your users to do it, but I'd be curious if this does solve this problem too.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23160/1398375908@github.com>

PB

unread,
Jan 20, 2023, 1:51:08 PM1/20/23
to wx-...@googlegroups.com, Subscribed

Have you tried the workaround from the other issue?

I tried, on the computer where the issue manifests much more, with the code in the OP. I did not see any change.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23160/1398800794@github.com>

VZ

unread,
Jan 25, 2023, 8:46:40 AM1/25/23
to wx-...@googlegroups.com, Subscribed

Thanks for testing this, it's unfortunate that even this doesn't fix it, but I really don't know what else can we do. The problem is clearly in dwm and I don't think it has any APIs to tell it to ignore some of the windows...


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23160/1403648464@github.com>

Reply all
Reply to author
Forward
0 new messages