I'm writing a Win32 OpenGL application for painting where it is critical that all mouse movement is handled. As it happens, sometimes the painting operation in my program is not able to perform in real time -- which is fine for me, as long as all mouse events are queued and can be handled later. Now I would have thought that this would simply be a matter of calling PeekMessage making sure to process all events, but when I do this, it is apparent that the mouse movements my application receives are not of the same fidelity that as those being displayed by Windows.
Is this a feature of Windows? Are mouse event dropped when the application is labor intensive? Or am I missing something? In either case, what can I do to remedy this situation? I would like to avoid multi-threading, part of the reason being that, as I understand, Win32 requires the message callback to be in the main thread and I'm not sure about separating the OpenGL-stuff to a different context.
And as for code example, I am essentially using the template code in the link below. The message I'm checking for is WM_MOUSEMOVE.
http://nehe.gamedev.net/tutorial/creating_an_opengl_window_(win32)/13001/
Is this a feature of Windows? Are mouse event dropped when the application is labor intensive?
Yes, this is a feature. WM_MOUSEMOVE messages are not dropped, they are synthesized. In other words, they are not actually posted to the message queue. That wouldn't work very well in practice, a user could generate a great many mouse moves in a second and rapidly fill the message queue to capacity when your program is busy.
You get a WM_MOUSEMOVE message when the mouse was moved since the last time you called GetMessage(). And you get the last known position. So the rate at which you get them, and the number of pixels between them, depend directly on how often you call GetMessage().
An alternative is to use raw input.
WM_MOUSEMOVE is special in that it isn't queued; it's automatically generated as needed when the message queue is empty. (WM_PAINT and WM_TIMER behave the same way.)
Raymond Chen suggests using GetMouseMovePointsEx if you need additional mouse input data.
Additional reading:
Why do I get spurious WM_MOUSEMOVE messages?
Paint messages will come in as fast as you let them
Related
I had a typical SDL event loop calling SDL_WaitEvent, and ran into a much-discussed issue (see here and here) where my application was not able to re-draw during a resize because SDL_WaitEvent doesn't return until a resize is finished on certain platforms (Win32 & Mac OS). In each of these discussions, the technique of using SDL_SetEventFilter to get around it is mentioned and more or less accepted as a solution and a hack.
Using the SDL_SetEventFilter approach works perfectly, but now I'm looking at my code and I've practically moved all the code from my SDL_WaitEvent into my EventFilter and just handling events there.
Architecturally it's fishy as heck.
Are there any gotcha's with this approach of dispatching messages to my application in the function set by SDL_SetEventFilter, besides the possibility of being called on a separate thread?
Bonus question: How is SDL handling this internally? From what I understand, this resize issue is rooted in the underlying platform. For example, Win32 will issue a WM_SIZING and then enter its own internal message pump until WM_SIZE is issued. What is triggering the SDL EventFilter to run?
Answering my own question after more experimentation and sifting through the source.
The way SDL handles events is that when you call SDL_WaitEvent/SDL_PeekEvent/SDL_PeepEvents, it pumps win32 until there's no messages left. During that pump, it will process the win32 messages and turn them into SDL events, which it queues, to return after the pump completes.
The way win32 handles move/resize operations is to go into a message pump until moving/resizing completes. It's a regular message pump, so your WndProc is still invoked during this time. You'll get a WM_ENTERSIZEMOVE, followed by many WM_SIZING or WM_MOVING messages, then finally a WM_EXITSIZEMOVE.
These two things together means that when you call any of the SDL event functions and win32 does a move/resize operation, you're stuck until dragging completes.
The way EventFilter gets around this is that it gets called as part of the WndProc itself. This means that you don't need to queue up messages and get them handed back to you at the end of SDL_Peek/Wait/Peep Event. You get them handed to you immediately as part of the pumping.
In my architecture, this fits perfectly. YMMV.
I need to pump COM messages while waiting for an event to fix a deadlock. It's better to pump as few messages as possible just to process that COM call. The best candidate for this role is CoWaitForMultipleHandles but starting from Vista it pumps WM_PAINT in addition to COM messages. Pumping WM_PAINT is too dangerous for me from re-entrance perspective and I don't want to install a custom shim database as a solution for this problem.
I'm trying to pump COM messages sent to the hidden message-only window manually.
I have found two ways to get HWND of the hidden window:
((SOleTlsData *) NtCurrentTeb()->ReservedForOle)->hwndSTA using ntinfo.h from .NET Core. This seems to be undocumented and not reliable solution in terms of future changes.
Find window of OleMainThreadWndClass as suggested in this question. The problem is that CoInitialize does not create the window. It is created later on first cross-apartment call which may or may not happen in my application. Running the search loop every time I need HWND is bad from performance perspective but caching HWND seems impossible because I don't know when it's created.
Is there a way to determine if the hidden window is created for the current apartment? I suppose it will be cheaper than the loop and then I could find and cache HWND.
Is there a better way to pump COM messages without pumping WM_PAINT?
Update: you can force the window creation by calling CoMarshalInterThreadInterfaceInStream for any interface. Then call CoReleaseMarshalData to release the stream pointer. This is what I end up doing along with the search for OleMainThreadWndClass.
WM_PAINT is generated when there is no other message in the message queue and you execute GetMessage or use PeekMessage.
But WM_PAINT is only sent if you Dispatch it. Also there is no new WM_PAINT message until a window is invalidated again.
So it depends on you if you dispatch a WM_PAINT message or not. But be aware, there are other chances of reentrances like a WM_TIMER message.
The details about this are in the docs for WM_PAINT.
From my point of view the best solution would be to set you application in a "wait" mode, that even can handle WM_PAINT in this undefined waiting state. You know when you are reentered. It is always after a WM_PAINT... or similar messages that arrive like other input messages. So I don't see any problems here. An STA has one thread and you always process messages to an end, until you execute GetMessage, launch a modal dialog or show a MessageBox. When you are inside some message handling, nothing will disturb you.
Maybe an other solution would be to wait inside a second thread for this event. This thread may not have any windows and you can translate the event to anything you need in your application.
So you question may not have enough information how this deadlock really appears. So this answer may not be sufficient.
After writing als this I tend to the opinion that this is an XY problem.
I'd like to understand how callback functions in a windowing application (like FreeGLUT, GLFW) work.
How many times they check for keyboard/mouse/resize events per second?
Does it depend on the frame rate, is it constant or maybe operation system specific?
Speaking generally, without getting into specifics for Unix or Windows implementations, callbacks are invoked from a main event loop which looks roughly like this:
Loop forever {
Get a message from the event queue.
Process the message
}
The stage of "Get a message" will have a very small sleep if it waits for a message to appear in the queue, probably less than a millisecond. The event queue will contain every message relevant to the application, including things like mouse button presses, mouse motion events, keyboard events, and window events like resize and expose.
The "Process the message" step will take an event and dispatch it to whatever is relevant for the event. So for example, a mouse click might result in the callback for a Button widget being called. Or if your OpenGL drawing area has an input handler callback set up, the mouse click would result in that function being called.
Here are a couple of resources to learn more about the process:
For Windows: http://en.wikipedia.org/wiki/Message_loop_in_Microsoft_Windows
For X/Motif: http://www.unix.com/man-page/all/3x/XtAppMainLoop/
If you want to see the specific steps along the way (there are many), you might try setting a breakpoint in a function you're interested in, such as your main OpenGL draw routine or an input callback function. Then the call stack will show you how you got there.
What I am going to do is very simple, I want to hide the mouse cursor after 1 second if the move does not move or click.
I searched and saw someone recommends using WM_MOUSEMOVE. In my app, however, WM_MOUSEMOVE is simply a dectection of whether the mouse is in the client area. If it is, the app receives WM_MOUSEMOVE continually. I've read the MSDN page but I am still confused.
Use WM_SETCURSOR.
Use WM_SETCURSOR for cursor related works. This message is made for that purpose. Your mentioning of client area suggest you probably need to use SetCapture API also.
Another way (or more modern way of doing) is using TrackMouseEvent. It provides WM_MOUSEHOVER.
The recommendation is correct. What you need to do is define a timer (for example, one that triggers the WM_TIMER message).
You activate it in the first mouse movement (WM_MOUSEMOVE). If a mouse movement won't occur within the interval you defined for the timer, the WM_TIMER event will fire and you can then hide the mouse.
Each time the WM_MOUSEMOVE event fires, you simply restart the timer (using its dedicated API). So that WM_MOUSEMONVE events prevent the timer from expiring. If WM_MOUSEMOVE stop arriving (because you don't move the mouse anymore), the timer will tick without interrupts until it elapses and fires.
I have a hook setup for getting mouse events in a plugin I develop. I need to get the WM_LBUTTONDBLCLK, and I expect the message flow to be:
WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK
If I call the next hook when dealing with the first WM_LBUTTONDOWN, then the flow is as expected. However, if I return my own result, then the expected double click comes as a mouse down message. Any idea why this is happening? I need the message to stop after I handle it, and not have it passed to the next hook.
After having done a little reading over at the MSDN, I think the explanation of this behaviour lies in this remark on the WM_LBUTTONDBLCLK page:
Only windows that have the CS_DBLCLKS
style can receive WM_LBUTTONDBLCLK
messages, which the system generates
whenever the user presses, releases,
and again presses the left mouse
button within the system's
double-click time limit.
If your program is returning a nonzero value when it handles WM_LBUTTONDOWN or WM_LBUTTONUP, then those messages aren't sent to the target window -- as expected. However, my inference, based on the above quote, is that since no window with the CS_DBLCLKS style is therefore receiving the messages (since the hook prevents any window from receiving the messages), the system therefore doesn't feel like it needs to generate a WM_LBUTTONDBLCLK.
To put it another way, the system only generates a WM_LBUTTONDBLCLK if and only if (a) a window receives the previous WM_LBUTTONDOWN/WM_LBUTTONUP messages and (b) that window has the CS_DBLCLKS style. Since your hook prevents condition (a) from being satisfied, WM_LBUTTONDBLCLK is never generated and so a WM_LBUTTONDOWN message is sent instead.
As to a workaround, I doubt there's a perfect solution. I assume the reason why you want to receive the WM_LBUTTONDBLCLK message is so your hook knows whether or not a regular WM_LBUTTONDOWN message represents the second click of a double-click, right? In that case, what you could do is read the double-click time from the registry as Faisal suggests and have your hook measure the time between WM_LBUTTONDOWN messages, however there's a large chance that you will get inaccurate results (due to the lag time between the messages being sent). Alternatively if there's some way you could instead redirect the WM_LBUTTONDOWN/WM_LBUTTONUP messages to maybe a hidden window that your hook owns (which has the CS_DBLCLKS style), the system may end up generating a WM_LBUTTONDBLCLK message and sending it to your hidden window, which you can then process in that window's WndProc (though I don't have a lot of experience with hooking so I don't know if this is possible).
Are you calling CallNextHookEx() before returning your own result - according to MSDN's documentation MouseProc it is highly recommended that you call it since when you return your own result you prevent other hooks from being called.
Have you considered using a low level mouse hook? It doesn't require your DLL to be injected into the process being hooked and I find it to be a more consistent and powerful hook (albeit more resource intensive if not coded appropriately) - especially when listening for clicks in some legacy applications (there was one that was coded in ancient delphi) and clicks in applications served via terminal servers (citrix).
The only issue with low level mouse hooks is that they don't receive double clicks per se - which means you have to query the registry for the 'DoubleClickSpeed' and then check for two mouse down events within that interval before triggering a double click.