Main window does not repaint on show when there is another secondary window

windows

#1

Well, this is a bit more complicated issue. I guess it is Windows specific.

I have a main window on the main screen and a secondary window that I display on another monitor in full-screen. But what happens when I do this is that the main window is all white and does not paint until I click anywhere within. From this point on, everything works as normal.

This is what I do in the constructor of the window that is displayed on the secondary monitor:

PreviewWindow() : DocumentWindow("PreviewWindow", Colours::black, allButtons) {		
	setContentNonOwned(&content, false);
	setSize(800, 800);
		
	const Desktop::Displays& ds = Desktop::getInstance().getDisplays();

	if (ds.displays.size() > 1) {
		for (auto i :ds.displays) {
			if (!i.isMain) {
				setBounds(i.userArea);
				setFullScreen(true);
				setTitleBarHeight(0);
				break;
			}
		}
	}
	setVisible(true);
}

Well, if I remove that “setVisible” line, the secondary window is of course not shown, but there is no problem with the main window.

I have also tried explicitly calling repaint() on the main window after it is created but that does not help.

And it’s really more complicated then it looks. It started after I implemented HighResolutionTimer within my main window (that is, the window inherits from HighResolutionTimer) as described here:

Note that after I click the main window everything works fine. But before that, no repaint call makes any difference. It looks as if the main window didn’t know it is visible.

If I call mainWindow->grabKeyboardFocus() at the end of my Application::initialize function, the problem with the main window not being refreshed at the app startup is gone, but the secondary window is not visible. I can see it on the taskbar, but it does not show until I click on it… So it’s either that or that. When I say the secondary window is not visible I mean… It is there, but it is completely transparent until I click anywhere on the monitor where it should be. This is probably the same what happens with the main window when I do not grab the focus with it. The only difference is that the secondary window is in fullscreen so probably that’s the reason I cannot see at least the white rectangle as with the main window. In other words I am just not able to show both windows on startup… Only one of them.

Again, when the content component on the main window does not inherit from the HighResolutionTimer but rather from standard Timer, both problems go away. Any hints what I could try?


#2

That sounds very fishy. Are you trying to do something on the timer callback that involves the GUI? Because obviously with a high-res timer that’ll be on a thread, so could be causing all kinds of race conditions.


#3

Hi Jules,

no I don’t. And I am also quite sure I would get an assert if I would because you have your code loaded with these kinds of macros checking that your message thread is locked.

I update box2D and render the image from that thread. And by the way, I noticed that you cannot actually render any text from there, because it complains at one of these asserts. You can render anything else though. (so, at this point I just don’t render any text).

I have however found a workaround that works for me at this point. If I call grabKeyboardFocus on the content component of the main window instead of the main window itself, it works for some reason (though it makes little sense to me) and both windows are refreshed right from the start. In the version with message based timer, I don’t need to do this.


#4

I really can’t think of any way either kind of timer could interact with window focus… unless there’s some subtle order-of-message-delivery thing going on involving the internal event that the Timer class sends. If you could create a minimal code example that reproduces this, it might be interesting to narrow down what’s going on.


#5

Hi,I have met the same problem when I update the wav in many windows at the same time.Can you tell me how to do if you have solved the problem ?


#6

Hm, sorry, I don’t remember. And it’s difficult to find out at this point. I guess I made some kind of workaround…

//edit: looking at the svn log, I found this:

/* workaround from v0.86 */
mainWindow->getContentComponent()->grabKeyboardFocus(); /* this is necessary so that the main window gets refreshed */

being called from the very bottom of the MyApplication::initialise().


#7

Thank you very much,and I will have a try!


#8

TBH I doubt that line will help, and I would check some other things first:

If you wait for a repaint() from a timer, first check if the timer is actually running by adding the line
DBG ("timer running");
in your timerCallback() method.

Next question: you say, it happens, when you change many wave files, that makes me wonder, if you use the AudioThumbnail?
In that case, note that the waves are generated in the background. Instead of using a timer, inherit from ChangeListener and listen to changes from the AudioThumbnail, simply call repaint() in the callback. It will be called each time a portion from the wav files is read, until the reading is completed.

HTH


#9

What I want to do is to get the audio from the asio driver, I need to plot data from 28 channels.In fact, I use handleAsyncUpdate() in AsyncUpdater class to call the repaint() function every time. I want to show them at the same time ,but have met the above problems.


#10

I draw the rect ,and axis ,and use lineto() to draw my wav.


#11

So is there something painted at all, or are fragments missing?
What I often do, when I am uncertain about that question, I put something brutal in there, e.g. g.fillAll (Colours::red); as a starting point.

But in any case, you can make your life easier using the AudioThumbnail.
In your getNextAudioBlock, simply push the new data using AudioThumbnail::addBlock(), and this will trigger the ChangeListener callback for the repaint() call.

If all that doesn’t help, please post the relevant bits of your code, e.g. the paint() method as a start.


#12

Yes, the wav is painted and change, but I am not sure if there are some fragments missing and this is also the problem I considered. Thank you for your help, I will try your metods .And if Ihave the problems, I will ask you for help ,thank you!


#13

Hey. I have a similar issue. My mainwindow content is a MIDI sequencer using a highresolution timer. A secondary window is supposed to display continuous monitoring data on regular timer callback. This secondary window stops repainting as soon the mainwindow’s hires timer is running, except if I click on the secondary window to give it keyboard focus. In this case, both windows are repainting properly (the main window repaint is triggered using an AsyncUpdater). But the secondary window stops again to repaint if I give back the focus to the main window… Note that the regular (message based) timer is continuously called on the secondary window (tested with DBG output), so the repaint() is called too, but the paint() is not until this window gets the keyboard focus.
That’s really strange, and it does not seem to be related to the hires timer interval, I tried with several values from 1ms to 1sec and I got exactly the same behavior.