Application window refreshing only on mouse movement. Topic is solved
Application window refreshing only on mouse movement.
Hello,
I've developed a multithreaded wxWidgets application on a Linux platform. The application uses a few detached threads for fetching new data from local devices or the network, and a single thread to queue events in the "main" loop, which then updates the display via event handlers. Data is shared between the threads using wxCriticalSectionLocker(s) where necessary. Each thread contains a different delay, to avoid locking/timing issues.
The application works well, however, I've run into a problem, where the main application window is not refreshed until the mouse is moved. I've searched through several forums, which mainly suggested explicitly using Update() and Refresh() in the main window event handler. Initially, this seemed to work, however, now the issue has returned. I'm still not sure what might be causing the problem, as it occurs irregularly.
New data is displayed in the application via wxStaticText(s) and wxStaticBitmap(s). These are also shown or hidden as needed. User control is made available via wxTextCtrl(s) and wxButton(s).
I would appreciate any help in fixing this issue.
Best regards,
Ksawery
I've developed a multithreaded wxWidgets application on a Linux platform. The application uses a few detached threads for fetching new data from local devices or the network, and a single thread to queue events in the "main" loop, which then updates the display via event handlers. Data is shared between the threads using wxCriticalSectionLocker(s) where necessary. Each thread contains a different delay, to avoid locking/timing issues.
The application works well, however, I've run into a problem, where the main application window is not refreshed until the mouse is moved. I've searched through several forums, which mainly suggested explicitly using Update() and Refresh() in the main window event handler. Initially, this seemed to work, however, now the issue has returned. I'm still not sure what might be causing the problem, as it occurs irregularly.
New data is displayed in the application via wxStaticText(s) and wxStaticBitmap(s). These are also shown or hidden as needed. User control is made available via wxTextCtrl(s) and wxButton(s).
I would appreciate any help in fixing this issue.
Best regards,
Ksawery
Re: Application window refreshing only on mouse movement.
As usual - could you provide minimal but reproducible sample? Does the behaviour exists only in multithreading apps? What exactly version of the library?
Re: Application window refreshing only on mouse movement.
Which exact Linux version/distro, window manager, wxWidgets version are you using?
Does wxWidgets use GTK2 or GTK3?
There are a few things you can do to further narrow down the error.
1) use logging inside the threads and the event handlers that change the gui to check if everything works as intended (is the code that updates the gui executed when it should, or only when the mouse moves)
2) does the mouse need to be over your application window in order to update the gui, or can it also be outside?
2a) if it needs to be over your application, what happens if you drag a window from another application across yours? Does it refresh the GUI?
Does wxWidgets use GTK2 or GTK3?
There are a few things you can do to further narrow down the error.
1) use logging inside the threads and the event handlers that change the gui to check if everything works as intended (is the code that updates the gui executed when it should, or only when the mouse moves)
2) does the mouse need to be over your application window in order to update the gui, or can it also be outside?
2a) if it needs to be over your application, what happens if you drag a window from another application across yours? Does it refresh the GUI?
This sounds suspicious. wxCriticalSections, wxMutex etc. should take care of that. Delays will be unreliable over time.Each thread contains a different delay, to avoid locking/timing issues.
Use the source, Luke!
Re: Application window refreshing only on mouse movement.
Hi,
In addition - what theme do you use?
Thank you.
In addition - what theme do you use?
Thank you.
Re: Application window refreshing only on mouse movement.
Thank you for your replies. As I'm not currently in the office, I can't answer all your questions, however, I can answer the following:
Here is the event handler that refreshes the display (partially in pseudo-code):
Here is the event table used in the main frame:
And here are the parameters of the frame constructor:
Many thanks,
Ksawery
I'm using wxWidgets version 3.1.4, with GTK3.Does wxWidgets use GTK2 or GTK3?
Latest version of Ubuntu Cinnamon Remix, with the Kimmo-Light theme.In addition - what theme do you use?
I will need to double-check this when I'm in the office.1) use logging inside the threads and the event handlers that change the gui to check if everything works as intended (is the code that updates the gui executed when it should, or only when the mouse moves)
I think that the window is updated regardless of the mouse position, however, I would also need to double-check this.2) does the mouse need to be over your application window in order to update the gui, or can it also be outside?
Do you believe that adding delays at the end of each thread might be the culprit? I wanted to avoid queuing events too frequently in the main thread, as the event handler might not be able to keep up. Currently, window refresh events are delayed by 200ms. Would you recommend replacing these with minimal delays?This sounds suspicious. wxCriticalSections, wxMutex etc. should take care of that. Delays will be unreliable over time.
So far I've only noticed the problem in the multithreaded application.Does the behaviour exists only in multithreading apps?
Here is the thread that queues events in the main loop (depending on application mode, it either sends events to an error window or the main window):As usual - could you provide minimal but reproducible sample?
Code: Select all
#include "cThreadRefreshDisplay.h"
DEFINE_EVENT_TYPE(wxEVT_DISPLAY_UPDATE)
cThreadRefreshDisplay::cThreadRefreshDisplay(cMain* pMain, cMainError* pMainError, bool bErrorMode) : wxThread(wxTHREAD_DETACHED)
{
this->pMain = pMain;
this->pMainError = pMainError;
this->bErrorMode = bErrorMode;
}
cThreadRefreshDisplay::~cThreadRefreshDisplay()
{
if (!bErrorMode) pMain->threadRefreshDisplay = NULL;
else pMainError->threadRefreshDisplay = NULL;
}
wxThread::ExitCode cThreadRefreshDisplay::Entry()
{
while (!TestDestroy())
{
if (bErrorMode)
{
if (pMainError != NULL)
{
//Send event to main window
wxCommandEvent* evt = new wxCommandEvent(wxEVT_DISPLAY_UPDATE, wxID_ANY);
((wxEvtHandler*) pMainError)->QueueEvent(evt);
}
}
else
{
if (pMain != NULL)
{
//Send event to main window
wxCommandEvent* evt = new wxCommandEvent(wxEVT_DISPLAY_UPDATE, wxID_ANY);
((wxEvtHandler*) pMain)->QueueEvent(evt);
}
}
wxThread::Sleep(DELAY_REFRESH_DISPLAY); // 211ms delay
}
return (wxThread::ExitCode) 0;
}
Code: Select all
void cMain::RefreshDisplay(void)
{
{
wxCriticalSectionLocker local_lock(mbMaster->local_guard);
// FETCH SHARED DATA
}
// CHECK IF APPLICATION MODE CHANGED
// IF CHANGED, DELETE AND RE-DRAW SEVERAL ELEMENTS, INCLUDING:
// PANELS, STATIC BITMAPS, STATIC TEXTS, TEXT INPUTS AND BUTTONS.
// IF UNCHANGED, UPDATE EXISTING ELEMENTS, INCLUDING
// STATIC BITMAPS, STATIC TEXTS AND TEXT INPUTS
// REFRESH AND UPDATE FRAME
this->Refresh();
this->Update();
}
Code: Select all
wxBEGIN_EVENT_TABLE(cMain, wxFrame)
EVT_MENU(wxID_INFO, cMain::OnMenuClickedInformation)
EVT_MENU(wxID_NETWORK, cMain::OnMenuClickedMode)
EVT_MENU(wxID_CLOSE, cMain::OnMenuClickedExit)
EVT_COMMAND(wxID_ANY, wxEVT_REMOTE_SET_CURRENT, cMain::OnRemoteSetCurrent)
EVT_COMMAND(wxID_ANY, wxEVT_DISPLAY_UPDATE, cMain::OnRefreshDisplay)
EVT_CLOSE(cMain::OnClose)
wxEND_EVENT_TABLE()
Code: Select all
cMain::cMain(cEntry* pEntry) : wxFrame(nullptr, wxID_ANY, " ", wxPoint(175, 9), wxSize(850, 1005), (wxDEFAULT_FRAME_STYLE & ~wxRESIZE_BORDER & ~wxMAXIMIZE_BOX & ~wxCLOSE_BOX))
Ksawery
Re: Application window refreshing only on mouse movement.
Did you leave out the part where the thread actually does something, or is this all it does? (which wouldn't make any sense).Here is the thread that queues events in the main loop...
Code: Select all
wxCriticalSectionLocker local_lock(mbMaster->local_guard);
Use the source, Luke!
Re: Application window refreshing only on mouse movement.
The thread only queues events in the main window. Other threads are tasked with fetching or sending new data, which is then shared between all threads in the application. Perhaps this multithreading model is faulty. Should I remove the display-refresh thread entirely, and replace it with a while loop in the main window?Did you leave out the part where the thread actually does something, or is this all it does? (which wouldn't make any sense).
Initially, I also suspected that this might be the case, however, why would it "unlock" only when the mouse is moved? There are several other threads that use the same lock, however, the lock is used for a very short period of time in each case (to fetch a few shared variables and buffers). The other threads are tasked with fetching/sending new data from/to the network and embedded devices.Who else locks this critical section? I wouldn't be surprised if this is the part where the application "hangs" and doesn't refresh its content. This should be easy to find with the logging i suggested in my previous post.
As suggested, I will need to test the application using logging when I'm in the office tomorrow.
Many thanks,
Ksawery
Re: Application window refreshing only on mouse movement.
Hi,
Because you algorythm is doing so.
Just get rid of the updating/refreshing thread and do this directly in the main GUI one.
Thank you.
Because you algorythm is doing so.
Just get rid of the updating/refreshing thread and do this directly in the main GUI one.
Thank you.
Re: Application window refreshing only on mouse movement.
Thanks for your reply, however, I don't understand how my algorithm is doing so? How does the process of queuing events from a separate thread cause the main window to only refresh when the mouse is moved? Of course, I now intend to make this change, however, I'd like to understand the actual difference that this change makes.Because you algorythm is doing so.
Just get rid of the updating/refreshing thread and do this directly in the main GUI one.
Many thanks,
Ksawery
Re: Application window refreshing only on mouse movement.
All UI operations should be done only in main thread. There are no guarantee that updating from other thread will correct.
Mouse moving is event so it unblocks internal event loop from waiting for event.
Re: Application window refreshing only on mouse movement.
If this thread just has the purpose to send unconditional refresh requests at a fixed rate, a simple timer would have done the same.The thread only queues events in the main window. Other threads are tasked with fetching or sending new data, which is then shared between all threads in the application. Perhaps this multithreading model is faulty. Should I remove the display-refresh thread entirely, and replace it with a while loop in the main window?
How many different elements are there to be updated? Or do you just unconditionally refresh everything?
If the threads are constantly working anyway, you could just have a timer in the main thread, e.g. at 2-20 Hz (which should be enough for gui updates) and update the content from there.
If you want to update specific parts of the GUI depending on which thread produced new data, i would use a wxMessageQueue that's shared among all threads. The worker threads would put a payload into the queue describing which gui parts needs update, the main thread would read from this queue in a timer event and perform the necessary updates.
https://docs.wxwidgets.org/trunk/classw ... _01_4.html
However, all these things will not solve the original issue, there must be another cause for this. Let's wait for the results from your inquiries tomorrow.
Use the source, Luke!
Re: Application window refreshing only on mouse movement.
I unconditionally refresh everything.How many different elements are there to be updated? Or do you just unconditionally refresh everything?
I will try using this instead of the worker thread.If the threads are constantly working anyway, you could just have a timer in the main thread, e.g. at 2-20 Hz (which should be enough for gui updates) and update the content from there.
After testing the application today, I noticed that the mouse does need to hover over the window, in order for it to update. The problem also seems to be intermittent. Initially I had the same issue, however after running the project from Eclipse in debug mode, the issue disappeared. Now the issue isn't there, even when I launch the program outside of Eclipse. It's very weird, as I'm finding it hard to reproduce the problem.2) does the mouse need to be over your application window in order to update the gui, or can it also be outside?
Re: Application window refreshing only on mouse movement.
Ok, this is very strange. But it would indicate that the issue is not inside wxWidgets or your application. Moving the mouse outside any of your application windows should not trigger any events and therefore should not have any effect. (Maybe you could confirm that by overriding wxApp::FilterEvent(...) and checking if there are any incoming events in that case).After testing the application today, I noticed that the mouse does need to hover over the window, in order for it to update.
That sounds more like a Linux theme / window manager issue (Ubuntu is kind of notorious for causing problems with wxWidgets).
Use the source, Luke!
Re: Application window refreshing only on mouse movement.
Moving the mouse outside the application window doesn't trigger any events, only moving it over the wxWidgets frame. Could that still be related to the Linux environment not working well with wxWidgets? Are there any potential solutions?Moving the mouse outside any of your application windows should not trigger any events and therefore should not have any effect.
I can see that some people are having issues with several wxWidgets programs under Ubuntu 20.04 LTS:
https://askubuntu.com/questions/1276235 ... h-drawings
Re: Application window refreshing only on mouse movement.
That issue seems to be a different one, you usually get those kind of artifacts when you move or resize a window (with the mouse).I can see that some people are having issues with several wxWidgets programs under Ubuntu 20.04 LTS:
Narrow down the problem even further => create a minimal sample that shows the issue => create a bug reportAre there any potential solutions?
Let's suppose that the content of a wxWidgets app doesn't get refreshed when there is no mouse movement anywhere. In that case it should be reproducible with a simple app that only contains a wxStaticText that is updated from a timer event. Could you test that?
Use the source, Luke!