w32_common: use sent messages to wake up the Win32 thread

Instead of PostMessage, use SendNotifyMessage from the SendMessage
family of functions to wake up the Win32 thread from the VO thread. When
a message is sent rather than posted between threads, it ends up in a
different queue which is processed before posted messages and can be
processed in more places. This prevents a playback glitch when clicking
on the titlebar, but not moving the window. With PostMessage-based
wakeups, VOCTRLs could be delayed for up to 500ms after the user clicks
on the titlebar, but with SendNotifyMessage, they still complete in
under a millisecond.

Also, instead of handling WM_USER, process the dispatch queue before
every message. This ensures the dispatch queue is processed as soon as
possible. WM_NULL is used to wake up the window procedure in case there
are no other messages being processed.
This commit is contained in:
James Ross-Gowan 2017-07-03 23:29:14 +10:00 committed by James Ross-Gowan
parent abe01fd18a
commit 91079c0e2b
1 changed files with 12 additions and 5 deletions

View File

@ -445,7 +445,14 @@ static void signal_events(struct vo_w32_state *w32, int events)
static void wakeup_gui_thread(void *ctx)
{
struct vo_w32_state *w32 = ctx;
PostMessage(w32->window, WM_USER, 0, 0);
// Wake up the window procedure (which processes the dispatch queue)
if (GetWindowThreadProcessId(w32->window, NULL) == GetCurrentThreadId()) {
PostMessageW(w32->window, WM_NULL, 0, 0);
} else {
// Use a sent message when cross-thread, since the queue of sent
// messages is processed in some cases when posted messages are blocked
SendNotifyMessageW(w32->window, WM_NULL, 0, 0);
}
}
static double get_refresh_rate_from_gdi(const wchar_t *device)
@ -888,11 +895,11 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)w32);
}
// The dispatch queue should be processed as soon as possible to prevent
// playback glitches, since it is likely blocking the VO thread
mp_dispatch_queue_process(w32->dispatch, 0);
switch (message) {
case WM_USER:
// This message is used to wakeup the GUI thread, see wakeup_gui_thread.
mp_dispatch_queue_process(w32->dispatch, 0);
break;
case WM_ERASEBKGND: // no need to erase background separately
return 1;
case WM_PAINT: