What does SDL_PollEvent do? - c++

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.

Related

GLFW Window poll events lag

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.

When resizing, make the window transparent with a dotted-line border

I'm asking this question ahead of time, since I haven't gotten around to attempting an actual, real implementation yet. Win32 (C++) is turning out to be a colossal pain to program. But, my question is this:
I want to make my application's window become fully transparent with a dotted perimeter when resizing the window. How would I accomplish this? Think of what happens in Windows 3/3.1 (I believe it was this version) when resizing a window. Everything goes transparent, with a dotted-outline where the mouse is moving, then it repaints the entire contents. That's what I'm trying to achieve.
A while ago, I tried handling the WM_(ENTER/EXIT)SIZEMOVE messages and make use of SetWindowLong() to set the WS_EX_TRANSPARENT extended style, but my window became (indefinitely) pass-through, and when the window's focus was killed, it could never again regain focus.
Do I need to handle other messages like WM_NCLBUTTON(DOWN/UP)? I have a boolean flag to tell me when to halt drawing during resizing, and the logic for determining when I'm resizing works perfectly, but I cannot get the visuals to work. I'm not sure which parts of the Win32 API to actually use. I've done some research, and uxtheme.lib/.h seems promising, but I'm not sure how that would work with WM_NCPAINT, which I have been using with (some) luck.
EDIT
I need to clarify something, in case anyone was confused or unsure of what I meant. What I meant by the Windows 3.1/3 resizing scenario is that once WM_ENTERSIZEMOVE has occurred, the window (controls, caption, frame) should be made entirely invisible, and the window's nonclient-region's perimeter should display a dotted-outline of sorts. Then, only until the resize has been finished, when WM_EXITSIZEMOVE has occurred should the entire window (controls, caption, frame) be fully redrawn, updated, and returned to its normal, functional state. Sorry for any miscommunication!
I found the answer... After so long, finally found it. Here's where I found it! http://www.catch22.net/tuts/win32/docking-toolbars-part-2# - Hope it helps anyone else possibly in my shoes!
And it turns out that the solution was rather simple. In fact, the core concept of what is explained is near-completely what I was thinking, yet I just had no idea how to implement it. The solution involves overriding the default WM_NCLBUTTONDOWN, WM_MOUSEMOVE, WM_LBUTTONUP (specifically when initiating a window movement) messages, and drawing a patterned rectangle which follows the position of the cursor. Then, afterwards, calling SetWindowPos or some other similar function to relocate the window.
Basically, block Windows from attempting to display anything graphics related until the resizing has been finished. Then, and only then, make Windows move the entire window in one huge, foul swoop.
Based on Remy's comment, there is a global option and corresponding registry setting for this, so perhaps try setting the registry setting when the move starts and restoring it when the move finishes.
Unfortunately this doesn't work as Windows appears only to pick up the setting on restart, broadcasting WM_SETTINGCHANGE also doesn't trigger it, which is a pity as doing something yourself that the OS already has an implementation of do is rather a poor state of affairs.

Detect when window gets overlapped by another window from the same or different process

Background
We are running our application in XenDesktop mode and our window shows some real time information. But if some other application is also launched in that XenDekstop and that application is overlapping our window then we want to stop rendering. And once its moved out of our window then we want to start rendering again. Unfortunately, right now these kind of notifications are not supported by Citrix.
Question
How can we detect when a part or the whole of the application window has been overlapped by other windows, and also detect when that's no longer the case?
I found the WindowFromPoint family of functions when Googling, however, that is not practical for my purpose because I'd need to keep polling all co-ordinates that my window covers.
Bonus points: For a start, it's enough if I can just detect when such overlapping occurs. However, if I can detect exactly which area(s) of my window is/are covered that would be great.
There is no such API function. And usually the it isn't needed. WM_PAINT cares for itself.
If you get a WM_PAINT message you receive a region and a update rectangle of the area that needs a repaint. But it is a rectangle only, no complex region. Also there is a clipping region too.
But it should be possible to calculate the region by yourself. If we are talking about a top level window.
Create a rectangular region that is consists of your window rect
Walk all top level windows from back to front
Ignore all windows until you find your top level window
For each visible top level window create a rectangular region and XOR it with your current one.
Should be easy with GetWindow GW_HWNDNEXT
The resulting region is what you are searching for.
Again: There is no such function or message that determine, that is fired or can be executed to find such overlapping. There is no need for such an information. The system cares for itself with the appropriate WM_PAINT message. If an area is covered. There is no need for an action. If an area is uncovered WM_PAINT gets fired.
I think you should be able to get this kind of information when processing the WM_PAINT message, since normally the clipping region would be set accordingly. Calls to the RectVisible() function should tell you, for any part of your window, whether it "should be painted" (and so, whether it was just uncovered).
Despite this is not a solution to the OP's problem, I want to remark that once an overlapping window reveals part of your window (and also if you drag more area of your window back to screen), you will get a WM_ERASEBKGND message before the WM_PAINT.

Opengl program not looping when window is focused

I'm having problems running my opengl 4 program. When the window is in focus, nothing appears to happen (even alt+f4 doesn't register until the window is out of focus).
If the window containing my program is in focus, then the main loop for my program stops executing (I checked using printf statements, within my while(true) loop, and the output stops completely when focused on the window). When the window is not focused, the program runs as expected (including mouse movements inside the window changing the camera direction).
I've narrowed it down to this line of code, which is executed within my mouse callback method
glfwSetCursorPos ( window, middleX, middleY);
If this is commented out, the program runs fine when in focus, but the mouse is no longer centred, so the camera logic no longer works.
I'm using 32 bit versions of glfw3 and glew.
This program has worked on other machines in the past. Is there any way to fix this without restructuring the code to poll the mouse input?
If you execute glfwSetCursorPos() inside your mouse callback, you can get to the situation that this creates a new mouse event, and after your callback exited, glfwPollEvents() will loop over the remaining events, so you effectively enter some endless loop here. You should just delay such actions after the input callbacks have been handled.
However, even with that approach, you will generate a new event for each frame, so that I suggest dropping the callback overhead alltogether and just quering the mouse position with glfwGetCursorPos() directly every frame.

Can I run code *after* a built-in wxWidgets event is handled?

I suspect there must be a built-in way to do this, but my Google-fu has failed me.
I'm using a wxScrolledWindow, and I have to paint an unscrolled background picture behind the contents each time the window is scrolled. I've made a scroll handler like this...
void homewindow_t::onScroll(wxScrollEvent &evt) {
Refresh();
evt.Skip();
}
...which works to force it to redraw the entire window each time. Unfortunately, it draws the window before the scroll is handled, so the background is repainted and then scrolled up or down, screwing up the alignment. The documentation suggests that Refresh just invalidates the screen, meaning that the scroll handler must be forcing a redraw.
The only way around this that I can see is to handle the scrolling code myself, which I'd rather not do if I don't have to.
Ideas, suggestions, clues...?
The only general solution I've found to running code after an event is handled is to post a second, different event to the event queue before skipping the current event (so that it gets handled by the default handler), and handle that when it comes up.
However, perusing the wxWidgets source code, I've found an answer to my specific problem: there's a function, wxScrolledWindow::EnableScrolling. Although it's not obvious from the name, this will enable or disable the "physical scrolling," which is what forces the instant redraw. So calling EnableScrolling(false, false); in the window's constructor solves the issue entirely.
To paint a "fixed" background in wxScrolledWindow you should just offset the DC origin to compensate for scrolling before drawing it (and then reset it back, of course), there is really no need to deal with events at all.
However if you really need to define a "post handler", then there is a way to do it, see this blog post. While the API described in it will only be available in wx 2.9.5, you do the same thing in the previous wx versions manually using wxEVT_IDLE.