mirror of
https://github.com/encounter/SDL.git
synced 2025-12-13 15:16:13 +00:00
Modifies WaitEvent and WaitEventTimeout to actually wait instead of polling
When possible use native os functions to make a blocking call waiting for an incoming event. Previous behavior was to continuously poll the event queue with a small delay between each poll. The blocking call uses a new optional video driver event, WaitEventTimeout, if available. It is called only if an window already shown is available. If present the window is designated using the variable wakeup_window to receive a wakeup event if needed. The WaitEventTimeout function accept a timeout parameter. If positive the call will wait for an event or return if the timeout expired without any event. If the timeout is zero it will implement a polling behavior. If the timeout is negative the function will block indefinetely waiting for an event. To let the main thread sees events sent form a different thread a "wake-up" signal is sent to the main thread if the main thread is in a blocking state. The wake-up event is sent to the designated wakeup_window if present. The wake-up event is sent only if the PushEvent call is coming from a different thread. Before sending the wake-up event the ID of the thread making the blocking call is saved using the variable blocking_thread_id and it is compared to the current thread's id to decide if the wake-up event should be sent. Two new optional video device methods are introduced: WaitEventTimeout SendWakeupEvent in addition the mutex wakeup_lock which is defined and initialized but only for the drivers supporting the methods above. If the methods are not present the system behaves as previously performing a periodic polling of the events queue. The blocking call is disabled if a joystick or sensor is detected and falls back to previous behavior.
This commit is contained in:
committed by
Sam Lantinga
parent
40e5ce7fe5
commit
0dd7024d55
@@ -1276,6 +1276,45 @@ void SDL_SetWindowsMessageHook(SDL_WindowsMessageHook callback, void *userdata)
|
||||
g_WindowsMessageHookData = userdata;
|
||||
}
|
||||
|
||||
int
|
||||
WIN_WaitEventTimeout(_THIS, int timeout)
|
||||
{
|
||||
MSG msg;
|
||||
if (g_WindowsEnableMessageLoop) {
|
||||
BOOL message_result;
|
||||
UINT_PTR timer_id = 0;
|
||||
if (timeout > 0) {
|
||||
timer_id = SetTimer(NULL, 0, timeout, NULL);
|
||||
message_result = GetMessage(&msg, 0, 0, 0);
|
||||
KillTimer(NULL, timer_id);
|
||||
} else if (timeout == 0) {
|
||||
message_result = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
|
||||
} else {
|
||||
message_result = GetMessage(&msg, 0, 0, 0);
|
||||
}
|
||||
if (message_result) {
|
||||
if (msg.message == WM_TIMER && msg.hwnd == NULL && msg.wParam == timer_id) {
|
||||
return 0;
|
||||
}
|
||||
if (g_WindowsMessageHook) {
|
||||
g_WindowsMessageHook(g_WindowsMessageHookData, msg.hwnd, msg.message, msg.wParam, msg.lParam);
|
||||
}
|
||||
/* Always translate the message in case it's a non-SDL window (e.g. with Qt integration) */
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
WIN_SendWakeupEvent(_THIS, SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
PostMessage(data->hwnd, data->videodata->_SDL_WAKEUP, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
WIN_PumpEvents(_THIS)
|
||||
{
|
||||
|
||||
@@ -31,6 +31,8 @@ extern LRESULT CALLBACK WIN_KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lP
|
||||
extern LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
LPARAM lParam);
|
||||
extern void WIN_PumpEvents(_THIS);
|
||||
extern void WIN_SendWakeupEvent(_THIS, SDL_Window *window);
|
||||
extern int WIN_WaitEventTimeout(_THIS, int timeout);
|
||||
|
||||
#endif /* SDL_windowsevents_h_ */
|
||||
|
||||
|
||||
@@ -87,7 +87,9 @@ WIN_DeleteDevice(SDL_VideoDevice * device)
|
||||
if (data->shcoreDLL) {
|
||||
SDL_UnloadObject(data->shcoreDLL);
|
||||
}
|
||||
|
||||
if (device->wakeup_lock) {
|
||||
SDL_DestroyMutex(device->wakeup_lock);
|
||||
}
|
||||
SDL_free(device->driverdata);
|
||||
SDL_free(device);
|
||||
}
|
||||
@@ -113,6 +115,7 @@ WIN_CreateDevice(int devindex)
|
||||
return NULL;
|
||||
}
|
||||
device->driverdata = data;
|
||||
device->wakeup_lock = SDL_CreateMutex();
|
||||
|
||||
data->userDLL = SDL_LoadObject("USER32.DLL");
|
||||
if (data->userDLL) {
|
||||
@@ -139,6 +142,8 @@ WIN_CreateDevice(int devindex)
|
||||
device->GetDisplayModes = WIN_GetDisplayModes;
|
||||
device->SetDisplayMode = WIN_SetDisplayMode;
|
||||
device->PumpEvents = WIN_PumpEvents;
|
||||
device->WaitEventTimeout = WIN_WaitEventTimeout;
|
||||
device->SendWakeupEvent = WIN_SendWakeupEvent;
|
||||
device->SuspendScreenSaver = WIN_SuspendScreenSaver;
|
||||
|
||||
device->CreateSDLWindow = WIN_CreateWindow;
|
||||
@@ -226,6 +231,8 @@ VideoBootStrap WINDOWS_bootstrap = {
|
||||
int
|
||||
WIN_VideoInit(_THIS)
|
||||
{
|
||||
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
||||
|
||||
if (WIN_InitModes(_this) < 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -236,6 +243,8 @@ WIN_VideoInit(_THIS)
|
||||
SDL_AddHintCallback(SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP, UpdateWindowsEnableMessageLoop, NULL);
|
||||
SDL_AddHintCallback(SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN, UpdateWindowFrameUsableWhileCursorHidden, NULL);
|
||||
|
||||
data->_SDL_WAKEUP = RegisterWindowMessageA("_SDL_WAKEUP");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -190,6 +190,7 @@ typedef struct SDL_VideoData
|
||||
TSFSink *ime_ippasink;
|
||||
|
||||
BYTE pre_hook_key_state[256];
|
||||
UINT _SDL_WAKEUP;
|
||||
} SDL_VideoData;
|
||||
|
||||
extern SDL_bool g_WindowsEnableMessageLoop;
|
||||
|
||||
Reference in New Issue
Block a user