The most horrible interface ever
Wednesday, May 6, 2009 | Permalink
Here's one vote for Win32 API handling of cursors. Trying to squeeze a custom cursor through Windows' tight intestines and not getting screwed in the process in one way or another is easier said than done.
So you have a custom cursor and you called SetCursor() to use it. What if you want to hide it?
ShowCursor(FALSE)?
*BZZZZTT* Wrong answer!
SetCursor(NULL)?
*BZZZZTT* Wrong answer!
Correct answer:
PostMessage(hwnd, WM_SETCURSOR, (WPARAM) hwnd, HTCLIENT);
and then
case WM_SETCURSOR:
SetCursor(NULL);
return TRUE;
No, just calling SetCursor(NULL) directly doesn't work. You really need to do it in response to WM_SETCURSOR, or it won't work. Or at least doesn't take effect until you move the mouse or click. Or just wait a few seconds until Windows randomly postes a WM_SETCURSOR message to your window for absolutely no reason. What the heck, does that happen to cover up that things aren't really working under the hood?
glReality
Thursday, May 7, 2009
Hi. Its really not as terrible as it looks
Try:
while (ShowCursor (FALSE) >= 0);
Zerf
Thursday, May 7, 2009
How is that "not as terrible as it looks"?
glReality
Thursday, May 7, 2009
I mean winapi is designed with a good bit of sense. Really.
Humus, If you are doing that feature for your framework, I think you just wasting time on that old outdated black-white crap. Its up to you, but in simular cases I'd rather prefer texture-based custom cursor rendered by you rendering api.
Humus
Thursday, May 7, 2009
No, that was actually for work. I don't know what you mean with "outdated black-white crap", are you talking about old bitmap Windows cursors? Because Windows support 32bit cursors with an alpha channel and everything since WinXP. So the standard cursor can look just as good as any rendered texture cursor. The problem with rendering the cursor yourself is that you get a few frames of input lag, unlike the Windows cursor which is updated and current on every refresh, regardless of framerate or number of buffered frames. If you have vsync enabled or low framerate the cursor can easily feel sluggish if you render it yourself.
Black Knight
Thursday, May 7, 2009
I also switched from rendering my own cursor to win32 cursor.I just load it at with LoadImage and set it as the class cursor.I also reload the cursor each time the window is resized to keep it's size relatively same to the window,works wells so far.The cursor I renderer with d3d lagged like hell even at frames rates around ~30.
John
Monday, May 11, 2009
Yes, custom-drawn cursors lag terribly. The main problem however are things such as first person shooters, where the view will lag and you can't use a hardware cursor to cover you up.
Really, what's up with that? Drivers using flip queues of 10 frames or even more, that's insane. That's too much even for video playback (sound will be desynched) or CAD work.
The other day I played a very old game. It ran V-synched at the screen refresh rate without effort, but was unplayable because there was about half a second of input delay. Most modern games that care about this clap the delay or use techniques which force a pipeline flush (such as visibility queries - but I could swear I saw a game which used visibility queries and still had three frames of lag or so).
This is clearly optimizing for benchmarks. It's as good as useless for anything else. One frame of delay is OK, it's pipelining, it'll improve performance but it won't increase latency. Two is already questionable, it'll improve performance if the workload varies from frame to frame, but 50fps with 40ms input lag sure beats 55fps with 54ms. More is completely inexcusable, whoever is responsible for that should be shot.
Sorry about the rant
random trivia: on Vista, when using the DWM, while you're dragging a window around, the hardware cursor is hidden and a software one is drawn to avoid the window lagging a lot behind the cursor
Humus
Monday, May 11, 2009
DirectX locks the number of buffered frames to at most three. With DXGI 1.1 you can set the number of buffered frames yourself using IDXGIDevice1::SetMaximumFrameLatency(), which could be useful in the future. Today the best way to reduce mouse lag within the game is to use an event query and sync to previous frame, which will give you one frame's latency. And for CrossFire/SLI systems you would typically sync to two frames back, or as many GPUs are being used.