GLFW Window poll events lag - c++

I have a problem handling GLFW poll events. As far as I know, all user input events are handled via callbacks or via constantly checking keyboard / mouse states. The latter is not so efficient an can even result in missing some input (e. g. when button pressed and then released between checking state). What is more, some events like window resizing cannot be handled without callbacks.
So, the problem is that whenever user starts resizing window (presses mouse button but doesn't move mouse), the app seems to freeze. This is, assuming resize callback is enabled and defined validly (even when copied right from GLFW API). And the problem is not that window doesn't redraw. Redraw on callback can be done with creating and calling own render() function in callback function.
The actual problem is that even when I handle resize event properly and redraw on callback, there is still some lag. This lag is after mouse press on decorated window border and when mouse is not moving. Here's a demonstration (button click is highlighted green):
Sorry for messed up GIF. All callbacks listed in GLFW API are enabled and handled (window-, input-, joystick- and monitor-callbacks) and redraw is called in each one. It seems that I'm missing some of the callbacks or GLFW just works like that.
According to this answer, this can't be done without threading:
That only works when the user moves the mouse while holding - just holding left-click on the resize window part still stalls. To fix that, you need to render in a separate thread in addition to this. (No, you can't do that without threading. Sorry, this is how GLFW works, no one except them can change it.)
So, the questions are:
How can I fix this issue without threading? If I can't, I guess I can emulate resizing with different cursors shapes and resizing zones or smth like that...
If this is still impossible to solve in GLFW, do other GLFW alternatives have this issue?
Are there any problems with GLFW similar to this one?

GLFW is not at fault here. It's how the operating system handles certain user input events like mouse down on the decorator resize handles of a window or moving the whole window.
See this answer for a more elaborate detail: Win32: My Application freezes while the user resizes the window
GLFW uses the standard Windows PeekMessage -> TranslateMessage/DispatchMessage loop which you will find in any GUI Windows application. This will get invoked when you call glfwPollEvents() and it processes all Window event messages that the OS has accumulated so far for all windows in this process. After all messages so far have been processed, the call to glfwPollEvents() will return and will allow your own window/game loop to continue.
What happens is that once the user clicks down the window decoration's resize handles, effectively the call to glfwPollEvents() will block within the OS itself in order for the OS / window-manager to intercept the mouse and keyboard messages to do its window resizing/reshaping thing.
I'm afraid that even though Windows will inform the process about the start of a window resize or move action (after which the OS will have control of the window message processing) and GLFW already handling these events internally, right now GLFW will not notify the client application about this. It would be possible though for GLFW to provide an appropriate event callback to the application, so that the application can start a timer or thread only for as long as the window resize/move action happens (as is also mentioned in the linked other Stackoverflow answer).
So, the only thing that you can do in order to keep rendering while the user holds onto the resize handles or while the user moves the window around, is to render in a separate thread.

Related

Old xlib programs hang the Linux GUI on window resize. Why?

I have noticed, that with the older X programs, when the user start to resize window by dragging its edges, the whole GUI of the OS freezes.
I am testing with glxgears - the gears stop rotating. The same happens with the content update of all other programs - such as the task manager, terminal windows and so on.
After stopping moving the mouse, all activity starts again.
Resizing newer program windows (I mean using GTK or Qt) does not freeze anything.
In the same time, the GUI of the older programs is much more responsive than the new. Only the dragging resize is the problem.
The older programs all use the standard documented way of handling the message queue. Something like the following (more complex, of course):
while (1) {
XNextEvent(d, &e);
if (e.type == Expose) {
XFillRectangle(d, w, DefaultGC(d, s), 20, 20, 10, 10);
XDrawString(d, w, DefaultGC(d, s), 10, 50, msg, strlen(msg));
}
}
I have tried to eliminate the whole message processing by setting XSetWindowAttributes.event_mask = 0 on main window creation. The events stop flowing at all, but on resizing the empty window, all GUI still freezes.
So, the problem is not (only) on the client side. Although, it can be in the way the client and the server interact. For example it can be because the client does not do something.
So, what the newer toolkits do differently? What to change in the older programs in order to avoid such freezes.
Well, after some research I have found the answer.
The problem is that the old programs does not use the _NEW_WM_SYNC_REQUEST protocol in order to synchronize their ability to redraw the window content with the rate of the resize events from the window manager.
Because of this the window manager resizes the window in too high rate and the application can't draw so fast. This way, the window manager effectively loads the X server and provides DoS hanging to the other running applications.
Of course in this case, the rate of the resize events depends on the window manager, but most of them simply resize the window on every mouse move.
The _NET_WM_SYNC_REQUEST protocol is aimed to provide information to the window manager when the application finished drawing its window and to stop it from resizing the window before previous resize is processed.
The implementation is pretty simple.
At first, the application must include the _NET_WM_SYNC_REQUEST in the WM_PROTOCOLS property of the window.
Also, the application should provide one (possibly two) synchronization counters (see SYNC X extension or xcb-sync library or the libX variant)
Then the protocol looks the following way:
Before to resize the window, WM sends to the application ClientMessage with data[0] set to the Atom of _NEW_WM_SYNC_REQUEST string. In the data[2] and data[3] of this event there is an 64 bit number. The application must store this number somewhere.
After processing the following ConfigureNotify and Expose events and having the window surface fully redrawn, it must set the synchronization counter to this 64 bit value.
The window manager checks the value of the counter and after see there its number, knows that it is safe to resize the window again.
Of course, there are some timeout mechanisms and if the program responds too slow or does not responds at all, the window manager switches to fall-back mode and starts to resize the windows the old way.
There is another variant of this protocol with two synchronization counters, but IMHO, it aims to solve another programs. With the window resizing, the first version of the protocol works great.

What does SDL_PollEvent do?

I am reading an introductory book code about SDL and there is sample code like this:
void Game::handleEvents()
{
SDL_Event event;
if (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
m_bRunning = false;
break;
default:
break;
}
}
}
I understand that this will look into the event queue and if there is anything, retrieve it and the run it to the switch statement. Before I added this code, the window was displayed but you cannot drag or drop, close, or resize the window. Now that I added this code, I can close the window which was what I expected. What I didn't expect was I am able to drag and drop the window.
I thought this would be a separate event that I would need to include in the switch statement in the future. Why did drag and drop also work? Its the SDL_PollEvent (because I commented the switch statement but left the 'if', I was still able to drag) but why is that? Also, why only drag and drop was automatically functional? Why not resize?
We do not need to handle all events, some SDL will take care of for us. Events related to the window properties will be taken care of automatically. In order to resize a window, you will have to add the flag SDL_WINDOW_RESIZABLE when creating the window. While SDL will take care of the actual resizing of the window, it might still require some event handling as the surface will have a different size to paint at, it will not automatically resize any images we try to draw in it.
While I have not found an answer in the documentation to why SDL_PollEvent behave as you describe above, or if this is behavior is intended, it works slightly different on different systems. At osx it is possible to move the window without the above function, but the X for closing will not be displayed. By adding the function again, the window can be moved, minimized and closed properly.
According to documentation, SDL_PollEvent is meant to do what you describe, look if there are any events and retrieve them.
Events are not happening right now, they have already occurred in the past, you are getting notifications that they did occur in the order they occured.
The frozen window is a side effect of an implementation detail, set appropriate flags to enable/disable window properties and functionality like resizing, fullscreen, etc.
SDL_PollEvent calls SDL_PumpEvents, removes the first event in the stack and copies it into the pointer given.
SDL_PumpEvents calls into the operating system's event processing API and transforms platform events into SDL_Events, pushing them onto the SDL event stack.
Now the reason windows are frozen on some platforms is that, that is how that platform event loop works, unless you "pump" its event loop it will be considered an unresponsive window and the window manager will want to kill it and its process.

Simulate mouse click without moving the cursor

I wrote an application that detects all active Windows and puts them into a list.
Is there a way to simulate a mouseclick on a spot on the screen relative to the Windows location without actually moving the cursor?
I don't have access to the buttons handle that is supposed to be clicked, only to the handle of the window
Is there a way to simulate a mouseclick on a spot on the screen relative to the Windows location without actually moving the cursor?
To answer your specific question - NO. Mouse clicks can only be directed where the mouse cursor actually resides at the time of the click. The correct way to simulate mouse input is to use SendInput() (or mouse_event() on older systems). But those functions inject simulated events into the same input queue that the actual mouse driver posts to, so they will have a physical effect on the mouse cursor - ie move it around the screen, etc.
How do I simulate input without SendInput?
SendInput operates at the bottom level of the input stack. It is just a backdoor into the same input mechanism that the keyboard and mouse drivers use to tell the window manager that the user has generated input. The SendInput function doesn't know what will happen to the input. That is handled by much higher levels of the window manager, like the components which hit-test mouse input to see which window the message should initially be delivered to.
When something gets added to a queue, it takes time for it to come out the front of the queue
When you call Send­Input, you're putting input packets into the system hardware input queue. (Note: Not the official term. That's just what I'm calling it today.) This is the same input queue that the hardware device driver stack uses when physical devices report events.
The message goes into the hardware input queue, where the Raw Input Thread picks them up. The Raw Input Thread runs at high priority, so it's probably going to pick it up really quickly, but on a multi-core machine, your code can keep running while the second core runs the Raw Input Thread. And the Raw Input thread has some stuff it needs to do once it dequeues the event. If there are low-level input hooks, it has to call each of those hooks to see if any of them want to reject the input. (And those hooks can take who-knows-how-long to decide.) Only after all the low-level hooks sign off on the input is the Raw Input Thread allowed to modify the input state and cause Get­Async­Key­State to report that the key is down.
The only real way to do what you are asking for is to find the HWND of the UI control that is located at the desired screen coordinates. Then you can either:
send WM_LBUTTONDOWN and WM_LBUTTONUP messages directly to it. Or, in the case of a standard Win32 button control, send a single BM_CLICK message instead.
use the AccessibleObjectFromWindow() function of the UI Automation API to access the control's IAccessible interface, and then call its accDoDefaultAction() method, which for a button will click it.
That being said, ...
I don't have access to the buttons handle that is supposed to be clicked.
You can access anything that has an HWND. Have a look at WindowFromPoint(), for instance. You can use it to find the HWND of the button that occupies the desired screen coordinates (with caveats, of course: WindowFromPoint, ChildWindowFromPoint, RealChildWindowFromPoint, when will it all end?).

AFX_WM_DRAW2D messages when screen is asleep

I have a problem with a progress bar that is implemented through adding a D2D object in MFC library.
I set up a message map to my function that keeps redrawing the progress bar based on some calculations:
BEGIN_MESSAGE_MAP(CProgressControl, CStatic)
ON_WM_PAINT()
ON_REGISTERED_MESSAGE(AFX_WM_DRAW2D, &CProgressControl::OnDraw2D)
END_MESSAGE_MAP()
My problem is that when the user locks out of the computer and the screen is asleep my drawing function does not seem to be called. It seems that the D2D notification message AFX_WM_DRAW2D is never sent to redraw when the screen is asleep.
I have tried to search for information on this online but did not find anything good about what might happen differently when the screen is asleep. I would appreciate any insight anyone might have on this.
Seems to me like this could be a normal behavior. Do you get any messages when your app is minimized or the computer is locked? I suspect that not.
Anyways, why should this bother you? Obviously your progress bar is invisible at the time, so why bother with the panting? You should be happy - Windows has an optimization for your program.
However if you do anything else besides painting in the painting messages, then I'd advise moving it elsewhere, as it is not that right place for it anyway. Paint message handlers should ONLY contain paint logic, and be prepared to be called at any time (or not at all).
Search the MFC sources for AFX_WM_DRAW2D and you'll see in wincore.cpp that the message is sent from a method called CWnd::DoD2DPaint() inbetween the render target's BeginDraw and EndDraw calls.
Therefore call DoD2DPaint to force a repaint. I did this on the sample CMFCD2DWalkthroughView (http://msdn.microsoft.com/en-us/library/gg482848.aspx) in the OnSize method to ensure that the gradient is updated and painted when the window is resized instead of the size/paint being out of sync.

Clearing mouseclicks buffer in openGL

I need to clear any mouse clicks which has happened before the end of an animation.Only mouse clicks afterwards have to be considered.
I tried enabling my mouse function after the animation,but any clicks that happened during the animation was considered.
To my understanding there is a buffer where mouseclicks are stored and during any mouse callback , it takes the co-ordinates and any other info of the first click stored in that buffer.so i need to know how to clear this.
I used fflush(stdin) but it doesnt clear keyboard or the mouse buffer.
Am using windowsxp and programming in visualsudio2008 in c language.i also use glut.h
i also use glut.h
Then you can't. If you're doing an animation, it's up to you to process (or choose not to process) any messages.
You should not be animating something by looping within your display method. Instead, you should set up a timer callback or something that will call glutPostRedisplay that will constantly call your drawing method. During this time, you should ignore any messages if you don't want to process them.