Revert "win32: one window procedure for every video and input driver"

This reverts commit 3a45e31811.

After it, on Windows with Vulkan, threaded video and the raw input
driver, toggling fullscreen with F and then using the menu left the
picture frozen: the run loop kept running, the menu received input and
was drawn, and Vulkan presented every frame without an error, but the
image on screen no longer changed. It did not happen before this
commit.

The cause inside the commit has not been found. The test that came
with it compares the new message routing with a transcription of the
three old switches, not with the old code running on Windows, so it
cannot show what differs on a real window. The twelve procedures come
back until that is understood and tested against a real window.
This commit is contained in:
LibretroAdmin authored and libretroadmin committed 2026-10-03 02:40:25 +02:00
1 parent a812e7fb44
commit dae95f4cc6
16 files changed
+704 -965

No files matched your search

-23
View File
@@ -615,29 +615,6 @@ jobs:
make clean all SANITIZER=thread
TSAN_OPTIONS=halt_on_error=1 timeout 120 ./gfx_widgets_task_gate_test
echo "[pass] gfx_widgets_task_gate_test (TSan)"
- name: Build and run win32_msg_route_test (ASan + UBSan)
shell: bash
working-directory: samples/gfx/win32_msg_route
run: |
set -eu
# What the Win32 window procedure does with a message.
# gfx/common/win32_common.c had twelve window procedures, one
# for each video family times each kind of input driver,
# built on three copies of one long switch. They are one
# procedure now, which asks win32_msg_route() what to do with
# a message. The three switches are written out in the test
# as they stood, and for every message - with and without the
# hotplug timer's id, on the desktop and on the Xbox, with
# and without threads - the route must be the steps the
# switch for that kind of input driver took. Raw input's
# keys made into keyboard events a second time, which is
# what routing them like another driver's would do, is put
# back and asserted to be caught.
make clean all SANITIZER=address,undefined
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 \
timeout 120 ./win32_msg_route_test
make clean
echo "[pass] win32_msg_route_test (ASan)"
- name: Build and run display_servers_test (ASan + UBSan)
shell: bash
working-directory: samples/gfx/display_servers
+586 -284
View File
@@ -119,7 +119,6 @@ typedef char win32_dwm_timing_info_size_check[
#endif
#include "win32_common.h"
#include "win32_msg_route.h"
#ifdef HAVE_GDI
@@ -1107,91 +1106,13 @@ static LRESULT CALLBACK wnd_proc_common(
return 0;
}
/* The kind of input driver the window's messages are routed for, and
* the video family the window belongs to. Both are set by
* win32_window_proc_setup() before the window is created. */
static enum win32_input_kind win32_wnd_input = WIN32_INPUT_OTHER;
static enum win32_window_family win32_wnd_family = WIN32_WINDOW_D3D;
/* win32_msg_route.h spells out Windows' message numbers so that it can
* be built without the SDK. They are the SDK's. */
typedef char win32_msg_route_numbers_check[
( WIN32_MSG_DESTROY == WM_DESTROY
&& WIN32_MSG_MOVE == WM_MOVE
&& WIN32_MSG_SIZE == WM_SIZE
&& WIN32_MSG_SETFOCUS == WM_SETFOCUS
&& WIN32_MSG_KILLFOCUS == WM_KILLFOCUS
&& WIN32_MSG_CLOSE == WM_CLOSE
&& WIN32_MSG_QUIT == WM_QUIT
&& WIN32_MSG_GETMINMAXINFO == WM_GETMINMAXINFO
&& WIN32_MSG_DISPLAYCHANGE == WM_DISPLAYCHANGE
&& WIN32_MSG_NCLBUTTONDBLCLK == WM_NCLBUTTONDBLCLK
&& WIN32_MSG_KEYDOWN == WM_KEYDOWN
&& WIN32_MSG_KEYUP == WM_KEYUP
&& WIN32_MSG_CHAR == WM_CHAR
&& WIN32_MSG_SYSKEYDOWN == WM_SYSKEYDOWN
&& WIN32_MSG_SYSKEYUP == WM_SYSKEYUP
&& WIN32_MSG_IME_ENDCOMPOSITION == WM_IME_ENDCOMPOSITION
&& WIN32_MSG_IME_COMPOSITION == WM_IME_COMPOSITION
&& WIN32_MSG_COMMAND == WM_COMMAND
&& WIN32_MSG_SYSCOMMAND == WM_SYSCOMMAND
&& WIN32_MSG_TIMER == WM_TIMER
&& WIN32_MSG_MOUSEMOVE == WM_MOUSEMOVE
&& WIN32_MSG_MOUSEWHEEL == WM_MOUSEWHEEL
&& WIN32_MSG_MOUSEHWHEEL == WM_MOUSEHWHEEL
&& WIN32_MSG_ENTERMENULOOP == WM_ENTERMENULOOP
&& WIN32_MSG_EXITMENULOOP == WM_EXITMENULOOP
&& WIN32_MSG_POWERBROADCAST == WM_POWERBROADCAST
&& WIN32_MSG_DEVICECHANGE == WM_DEVICECHANGE
&& WIN32_MSG_ENTERSIZEMOVE == WM_ENTERSIZEMOVE
&& WIN32_MSG_EXITSIZEMOVE == WM_EXITSIZEMOVE
&& WIN32_MSG_DROPFILES == WM_DROPFILES
&& WIN32_MSG_POINTERUPDATE == WM_POINTERUPDATE
&& WIN32_MSG_POINTERDOWN == WM_POINTERDOWN
&& WIN32_MSG_POINTERUP == WM_POINTERUP
#ifdef HAVE_THREADS
&& WIN32_MSG_BROWSER_OPEN_RESULT == WM_BROWSER_OPEN_RESULT
&& WIN32_MSG_BROWSER_CANCELLED == WM_BROWSER_CANCELLED
#endif
&& WIN32_MSG_HOTPLUG_TIMER_ID == WIN32_HOTPLUG_TIMER_ID) ? 1 : -1];
#if defined(_MSC_VER) && !defined(_XBOX)
#pragma comment(lib, "Imm32")
#endif
/* Offer a message to the input driver. True if the driver took it. */
static bool win32_wnd_input_message(UINT message,
WPARAM wparam, LPARAM lparam)
{
switch (win32_wnd_input)
{
#ifdef HAVE_DINPUT
case WIN32_INPUT_DINPUT:
{
void *input_data = (void*)(LONG_PTR)GetWindowLongPtr(
main_window.hwnd, GWLP_USERDATA);
return input_data && dinput_handle_message(input_data,
message, wparam, lparam);
}
#endif
#if defined(HAVE_WINRAWINPUT) && !defined(_XBOX)
case WIN32_INPUT_WINRAW:
return winraw_handle_message(message, wparam, lparam);
#endif
default:
break;
}
return false;
}
/* The window procedure, past the window's creation. What it does with
* a message is win32_msg_route()'s answer for the kind of input driver
* in use; the steps are taken here, in order. */
static LRESULT win32_wnd_proc_route(HWND hwnd,
static LRESULT CALLBACK wnd_proc_common_internal(HWND hwnd,
UINT message, WPARAM wparam, LPARAM lparam)
{
LRESULT ret;
bool keydown = true;
bool quit = false;
win32_common_state_t *g_win32 = (win32_common_state_t*)&win32_st;
unsigned route;
#ifdef HAVE_TASKBAR
if ( !(g_win32_flags & WIN32_CMN_FLAG_TASKBAR_CREATED)
@@ -1200,162 +1121,512 @@ static LRESULT win32_wnd_proc_route(HWND hwnd,
g_win32_flags |= WIN32_CMN_FLAG_TASKBAR_CREATED;
#endif
route = win32_msg_route(win32_wnd_input,
#if defined(_XBOX)
false,
#else
true,
#endif
#ifdef HAVE_THREADS
true,
#else
false,
#endif
(unsigned)message, wparam == WIN32_HOTPLUG_TIMER_ID);
if (!route)
return DefWindowProc(hwnd, message, wparam, lparam);
#ifdef HAVE_DINPUT
if (route & WIN32_ROUTE_IME_END)
input_keyboard_event(true, 1, 0x80000000, 0, RETRO_DEVICE_KEYBOARD);
if (route & WIN32_ROUTE_IME_TEXT)
switch (message)
{
HIMC hIMC = ImmGetContext(hwnd);
/* Process composition and result strings separately;
* ImmGetCompositionStringW expects a single flag per call. */
unsigned gcs_flags[2] = { GCS_RESULTSTR, GCS_COMPSTR };
int f;
for (f = 0; f < 2; f++)
{
unsigned gcs_flag = gcs_flags[f];
if (!(lparam & gcs_flag))
continue;
case WM_KEYUP: /* Key released */
case WM_SYSKEYUP: /* Key released */
keydown = false;
/* fall-through */
case WM_KEYDOWN: /* Key pressed */
case WM_SYSKEYDOWN: /* Key pressed */
quit = true;
{
int i;
/* Request up to 2 wide chars (4 bytes). Return value is in bytes. */
wchar_t wstr[3] = {0, 0, 0};
LONG byte_len = ImmGetCompositionStringW(
hIMC, gcs_flag, wstr, 2 * sizeof(wchar_t));
int char_count;
uint16_t mod = 0;
unsigned keycode = 0;
unsigned keysym = (lparam >> 16) & 0xff;
bool extended = (lparam >> 24) & 0x1;
if (byte_len <= 0 || byte_len > (LONG)(2 * sizeof(wchar_t)))
continue;
/* NumLock vs Pause correction */
if (keysym == 0x45 && (wparam == VK_NUMLOCK || wparam == VK_PAUSE))
extended = !extended;
char_count = byte_len / (int)sizeof(wchar_t);
/* extended keys will map to dinput if the high bit is set */
if (extended)
keysym |= 0x80;
for (i = 0; i < char_count; i++)
{
wchar_t single[2];
char *utf8;
size_t utf8_len;
uint32_t packed = 0;
keycode = input_keymaps_translate_keysym_to_rk(keysym);
single[0] = wstr[i];
single[1] = 0;
utf8 = utf16_to_utf8_string_alloc(single);
if (!utf8)
continue;
utf8_len = strlen(utf8);
/* Pack up to 3 UTF-8 bytes into the low 24 bits and
* the composition/result flag into the high byte.
* This matches what the receiver expects as a uint32. */
if (utf8_len >= 1 && utf8_len <= 3)
{
memcpy(&packed, utf8, utf8_len);
if (utf8_len >= 2)
((unsigned char*)&packed)[3] =
(unsigned char)((gcs_flag) | (gcs_flag >> 4));
input_keyboard_event(true, 1, (uint32_t)packed, 0,
RETRO_DEVICE_KEYBOARD);
}
free(utf8);
}
}
}
ImmReleaseContext(hwnd, hIMC);
return 0;
}
#endif
if (route & WIN32_ROUTE_KEY)
{
if (route & (WIN32_ROUTE_KEY_MODS | WIN32_ROUTE_KEY_EVENT))
{
bool keydown = !(message == WM_KEYUP || message == WM_SYSKEYUP);
unsigned keysym = (lparam >> 16) & 0xff;
bool extended = (lparam >> 24) & 0x1;
/* NumLock vs Pause correction */
if (keysym == 0x45 && (wparam == VK_NUMLOCK || wparam == VK_PAUSE))
extended = !extended;
/* extended keys will map to dinput if the high bit is set */
if (extended)
keysym |= 0x80;
/* tell the driver about shift and alt key events */
if ( (route & WIN32_ROUTE_KEY_MODS)
&& ( keysym == 0x2A/*DIK_LSHIFT*/
|| keysym == 0x36/*DIK_RSHIFT*/
|| keysym == 0x38/*DIK_LMENU*/
|| keysym == 0xB8/*DIK_RMENU*/)
&& win32_wnd_input_message(message, wparam, lparam))
return 0; /* key up already handled by the driver */
if (route & WIN32_ROUTE_KEY_EVENT)
{
unsigned keycode = input_keymaps_translate_keysym_to_rk(keysym);
uint16_t mod = win32_update_keyboard_mods();
mod = win32_update_keyboard_mods();
input_keyboard_event(keydown, keycode,
0, mod, RETRO_DEVICE_KEYBOARD);
if (message != WM_SYSKEYDOWN)
return 0;
if (
wparam == VK_F10
|| wparam == VK_MENU
|| wparam == VK_RSHIFT
)
return 0;
}
}
if (message != WM_SYSKEYDOWN)
return 0;
if ( wparam == VK_F10
|| wparam == VK_MENU
|| wparam == VK_RSHIFT)
return 0;
}
#ifdef HAVE_CLIP_WINDOW
if ( (route & (WIN32_ROUTE_CLIP_ON | WIN32_ROUTE_CLIP_OFF))
&& (input_state_get_ptr()->flags & INP_FLAG_GRAB_MOUSE_STATE))
win32_clip_window((route & WIN32_ROUTE_CLIP_ON) != 0);
break;
case WM_MOUSEMOVE:
case WM_POINTERDOWN:
case WM_POINTERUP:
case WM_POINTERUPDATE:
case WM_DEVICECHANGE:
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
case WM_NCLBUTTONDBLCLK:
break;
case WM_DROPFILES:
case WM_SYSCOMMAND:
case WM_CHAR:
case WM_CLOSE:
case WM_DESTROY:
case WM_QUIT:
case WM_MOVE:
case WM_SIZE:
#if !defined(_XBOX)
case WM_ENTERSIZEMOVE:
case WM_EXITSIZEMOVE:
case WM_ENTERMENULOOP:
case WM_EXITMENULOOP:
case WM_TIMER:
case WM_POWERBROADCAST:
#endif
if ( (route & WIN32_ROUTE_INPUT)
&& win32_wnd_input_message(message, wparam, lparam))
return 0;
if (route & WIN32_ROUTE_COMMON)
{
bool quit = false;
LRESULT ret = wnd_proc_common(&quit, hwnd, message, wparam, lparam);
if (quit)
return ret;
}
if (route & WIN32_ROUTE_DISPLAY)
{
/* Fix size after display mode switch when using SR */
HMONITOR mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (mon)
win32_resize_after_display_change(hwnd, mon);
video_driver_window_output_changed();
case WM_GETMINMAXINFO:
case WM_COMMAND:
#ifdef HAVE_THREADS
case WM_BROWSER_OPEN_RESULT:
case WM_BROWSER_CANCELLED:
#endif
ret = wnd_proc_common(&quit, hwnd, message, wparam, lparam);
if (quit)
return ret;
break;
case WM_SETFOCUS:
#ifdef HAVE_CLIP_WINDOW
if (input_state_get_ptr()->flags & INP_FLAG_GRAB_MOUSE_STATE)
win32_clip_window(true);
#endif
break;
case WM_KILLFOCUS:
#ifdef HAVE_CLIP_WINDOW
if (input_state_get_ptr()->flags & INP_FLAG_GRAB_MOUSE_STATE)
win32_clip_window(false);
#endif
break;
case WM_DISPLAYCHANGE: /* Fix size after display mode switch when using SR */
{
HMONITOR mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (mon)
win32_resize_after_display_change(hwnd, mon);
}
video_driver_window_output_changed();
break;
}
return DefWindowProc(hwnd, message, wparam, lparam);
}
#ifdef HAVE_WINRAWINPUT
static LRESULT CALLBACK wnd_proc_winraw_common_internal(HWND hwnd,
UINT message, WPARAM wparam, LPARAM lparam)
{
LRESULT ret;
bool quit = false;
win32_common_state_t *g_win32 = (win32_common_state_t*)&win32_st;
#ifdef HAVE_TASKBAR
if ( !(g_win32_flags & WIN32_CMN_FLAG_TASKBAR_CREATED)
&& g_win32->taskbar_message
&& message == g_win32->taskbar_message)
g_win32_flags |= WIN32_CMN_FLAG_TASKBAR_CREATED;
#endif
switch (message)
{
case WM_KEYUP: /* Key released */
case WM_SYSKEYUP: /* Key released */
/* fall-through */
case WM_KEYDOWN: /* Key pressed */
case WM_SYSKEYDOWN: /* Key pressed */
quit = true;
if (message != WM_SYSKEYDOWN)
return 0;
/* keyboard_event in winraw_callback */
if (
wparam == VK_F10
|| wparam == VK_MENU
|| wparam == VK_RSHIFT
)
return 0;
break;
case WM_MOUSEMOVE:
case WM_POINTERDOWN:
case WM_POINTERUP:
case WM_POINTERUPDATE:
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
case WM_NCLBUTTONDBLCLK:
break;
case WM_DROPFILES:
case WM_SYSCOMMAND:
case WM_CHAR:
case WM_CLOSE:
case WM_DESTROY:
case WM_QUIT:
case WM_MOVE:
case WM_SIZE:
#if !defined(_XBOX)
case WM_TIMER:
if ( wparam == WIN32_HOTPLUG_TIMER_ID
&& winraw_handle_message(message, wparam, lparam))
return 0;
ret = wnd_proc_common(&quit, hwnd, message, wparam, lparam);
if (quit)
return ret;
break;
#endif
#if !defined(_XBOX)
case WM_ENTERSIZEMOVE:
case WM_EXITSIZEMOVE:
case WM_ENTERMENULOOP:
case WM_EXITMENULOOP:
case WM_POWERBROADCAST:
#endif
case WM_GETMINMAXINFO:
case WM_COMMAND:
#ifdef HAVE_THREADS
case WM_BROWSER_OPEN_RESULT:
case WM_BROWSER_CANCELLED:
#endif
ret = wnd_proc_common(&quit, hwnd, message, wparam, lparam);
if (quit)
return ret;
break;
case WM_SETFOCUS:
#ifdef HAVE_CLIP_WINDOW
if (input_state_get_ptr()->flags & INP_FLAG_GRAB_MOUSE_STATE)
win32_clip_window(true);
#endif
#if !defined(_XBOX)
if (winraw_handle_message(message, wparam, lparam))
return 0;
#endif
break;
case WM_KILLFOCUS:
#ifdef HAVE_CLIP_WINDOW
if (input_state_get_ptr()->flags & INP_FLAG_GRAB_MOUSE_STATE)
win32_clip_window(false);
#endif
#if !defined(_XBOX)
if (winraw_handle_message(message, wparam, lparam))
return 0;
#endif
break;
case WM_DISPLAYCHANGE: /* Fix size after display mode switch when using SR */
{
HMONITOR mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (mon)
win32_resize_after_display_change(hwnd, mon);
}
video_driver_window_output_changed();
break;
case WM_DEVICECHANGE:
#if !defined(_XBOX)
if (winraw_handle_message(message, wparam, lparam))
return 0;
#endif
break;
}
return DefWindowProc(hwnd, message, wparam, lparam);
}
#endif
#if defined(_MSC_VER) && !defined(_XBOX)
#pragma comment(lib, "Imm32")
#endif
#ifdef HAVE_DINPUT
static LRESULT CALLBACK wnd_proc_common_dinput_internal(HWND hwnd,
UINT message, WPARAM wparam, LPARAM lparam)
{
LRESULT ret;
bool keydown = true;
bool quit = false;
win32_common_state_t *g_win32 = (win32_common_state_t*)&win32_st;
#ifdef HAVE_TASKBAR
if ( !(g_win32_flags & WIN32_CMN_FLAG_TASKBAR_CREATED)
&& g_win32->taskbar_message
&& message == g_win32->taskbar_message)
g_win32_flags |= WIN32_CMN_FLAG_TASKBAR_CREATED;
#endif
switch (message)
{
case WM_IME_ENDCOMPOSITION:
input_keyboard_event(true, 1, 0x80000000, 0, RETRO_DEVICE_KEYBOARD);
break;
case WM_IME_COMPOSITION:
{
HIMC hIMC = ImmGetContext(hwnd);
/* Process composition and result strings separately;
* ImmGetCompositionStringW expects a single flag per call. */
unsigned gcs_flags[2] = { GCS_RESULTSTR, GCS_COMPSTR };
int f;
for (f = 0; f < 2; f++)
{
unsigned gcs_flag = gcs_flags[f];
if (!(lparam & gcs_flag))
continue;
{
int i;
/* Request up to 2 wide chars (4 bytes). Return value is in bytes. */
wchar_t wstr[3] = {0, 0, 0};
LONG byte_len = ImmGetCompositionStringW(
hIMC, gcs_flag, wstr, 2 * sizeof(wchar_t));
int char_count;
if (byte_len <= 0 || byte_len > (LONG)(2 * sizeof(wchar_t)))
continue;
char_count = byte_len / (int)sizeof(wchar_t);
for (i = 0; i < char_count; i++)
{
wchar_t single[2];
char *utf8;
size_t utf8_len;
uint32_t packed = 0;
single[0] = wstr[i];
single[1] = 0;
utf8 = utf16_to_utf8_string_alloc(single);
if (!utf8)
continue;
utf8_len = strlen(utf8);
/* Pack up to 3 UTF-8 bytes into the low 24 bits and
* the composition/result flag into the high byte.
* This matches what the receiver expects as a uint32. */
if (utf8_len >= 1 && utf8_len <= 3)
{
memcpy(&packed, utf8, utf8_len);
if (utf8_len >= 2)
((unsigned char*)&packed)[3] =
(unsigned char)((gcs_flag) | (gcs_flag >> 4));
input_keyboard_event(true, 1, (uint32_t)packed, 0,
RETRO_DEVICE_KEYBOARD);
}
free(utf8);
}
}
}
ImmReleaseContext(hwnd, hIMC);
return 0;
}
break;
case WM_KEYUP: /* Key released */
case WM_SYSKEYUP: /* Key released */
keydown = false;
/* fall-through */
case WM_KEYDOWN: /* Key pressed */
case WM_SYSKEYDOWN: /* Key pressed */
quit = true;
{
uint16_t mod = 0;
unsigned keycode = 0;
unsigned keysym = (lparam >> 16) & 0xff;
bool extended = (lparam >> 24) & 0x1;
/* NumLock vs Pause correction */
if (keysym == 0x45 && (wparam == VK_NUMLOCK || wparam == VK_PAUSE))
extended = !extended;
/* extended keys will map to dinput if the high bit is set */
if (extended)
keysym |= 0x80;
/* tell the driver about shift and alt key events */
if ( keysym == 0x2A/*DIK_LSHIFT*/
|| keysym == 0x36/*DIK_RSHIFT*/
|| keysym == 0x38/*DIK_LMENU*/
|| keysym == 0xB8/*DIK_RMENU*/)
{
void* input_data = (void*)(LONG_PTR)GetWindowLongPtr(main_window.hwnd, GWLP_USERDATA);
if (input_data && dinput_handle_message(input_data,
message, wparam, lparam))
return 0; /* key up already handled by the driver */
}
keycode = input_keymaps_translate_keysym_to_rk(keysym);
mod = win32_update_keyboard_mods();
input_keyboard_event(keydown, keycode,
0, mod, RETRO_DEVICE_KEYBOARD);
if (message != WM_SYSKEYDOWN)
return 0;
if (
wparam == VK_F10
|| wparam == VK_MENU
|| wparam == VK_RSHIFT
)
return 0;
}
break;
case WM_MOUSEMOVE:
case WM_POINTERDOWN:
case WM_POINTERUP:
case WM_POINTERUPDATE:
case WM_DEVICECHANGE:
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
case WM_NCLBUTTONDBLCLK:
#if !defined(_XBOX)
{
void* input_data = (void*)(LONG_PTR)GetWindowLongPtr(main_window.hwnd, GWLP_USERDATA);
if (input_data && dinput_handle_message(input_data,
message, wparam, lparam))
return 0;
}
#endif
break;
case WM_DROPFILES:
case WM_SYSCOMMAND:
case WM_CHAR:
case WM_CLOSE:
case WM_DESTROY:
case WM_QUIT:
case WM_MOVE:
case WM_SIZE:
#if !defined(_XBOX)
case WM_TIMER:
if (wparam == WIN32_HOTPLUG_TIMER_ID)
{
void* input_data = (void*)(LONG_PTR)GetWindowLongPtr(main_window.hwnd, GWLP_USERDATA);
if (input_data && dinput_handle_message(input_data,
message, wparam, lparam))
return 0;
}
ret = wnd_proc_common(&quit, hwnd, message, wparam, lparam);
if (quit)
return ret;
break;
#endif
#if !defined(_XBOX)
case WM_ENTERSIZEMOVE:
case WM_EXITSIZEMOVE:
case WM_ENTERMENULOOP:
case WM_EXITMENULOOP:
case WM_POWERBROADCAST:
#endif
case WM_GETMINMAXINFO:
case WM_COMMAND:
#ifdef HAVE_THREADS
case WM_BROWSER_OPEN_RESULT:
case WM_BROWSER_CANCELLED:
#endif
ret = wnd_proc_common(&quit, hwnd, message, wparam, lparam);
if (quit)
return ret;
break;
case WM_SETFOCUS:
#ifdef HAVE_CLIP_WINDOW
if (input_state_get_ptr()->flags & INP_FLAG_GRAB_MOUSE_STATE)
win32_clip_window(true);
#endif
#if !defined(_XBOX)
{
void* input_data = (void*)(LONG_PTR)GetWindowLongPtr(main_window.hwnd, GWLP_USERDATA);
if (input_data && dinput_handle_message(input_data,
message, wparam, lparam))
return 0;
}
#endif
break;
case WM_KILLFOCUS:
#ifdef HAVE_CLIP_WINDOW
if (input_state_get_ptr()->flags & INP_FLAG_GRAB_MOUSE_STATE)
win32_clip_window(false);
#endif
#if !defined(_XBOX)
{
void* input_data = (void*)(LONG_PTR)GetWindowLongPtr(main_window.hwnd, GWLP_USERDATA);
if (input_data && dinput_handle_message(input_data,
message, wparam, lparam))
return 0;
}
#endif
break;
case WM_DISPLAYCHANGE: /* Fix size after display mode switch when using SR */
{
HMONITOR mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (mon)
win32_resize_after_display_change(hwnd, mon);
}
video_driver_window_output_changed();
break;
}
return DefWindowProc(hwnd, message, wparam, lparam);
}
#endif
#if defined(HAVE_D3D) || defined(HAVE_D3D8) || defined(HAVE_D3D9) || defined (HAVE_D3D10) || defined (HAVE_D3D11) || defined (HAVE_D3D12)
LRESULT CALLBACK wnd_proc_d3d_common(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
{
if (DragAcceptFiles_func)
DragAcceptFiles_func(hwnd, true);
g_win32_flags |= WIN32_CMN_FLAG_INITED;
return 0;
}
return wnd_proc_common_internal(hwnd, message, wparam, lparam);
}
#ifdef HAVE_WINRAWINPUT
LRESULT CALLBACK wnd_proc_d3d_winraw(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
{
if (DragAcceptFiles_func)
DragAcceptFiles_func(hwnd, true);
g_win32_flags |= WIN32_CMN_FLAG_INITED;
return 0;
}
return wnd_proc_winraw_common_internal(hwnd, message, wparam, lparam);
}
#endif
#ifdef HAVE_DINPUT
LRESULT CALLBACK wnd_proc_d3d_dinput(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
{
if (DragAcceptFiles_func)
DragAcceptFiles_func(hwnd, true);
g_win32_flags |= WIN32_CMN_FLAG_INITED;
return 0;
}
return wnd_proc_common_dinput_internal(hwnd, message, wparam, lparam);
}
#endif
#endif
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGL1) || defined(HAVE_OPENGL_CORE)
extern void create_gl_context(HWND hwnd, bool *quit);
extern void create_gles_context(HWND hwnd, bool *quit);
@@ -1390,6 +1661,33 @@ static LRESULT wnd_proc_wgl_wm_create(HWND hwnd)
return 0;
}
#ifdef HAVE_DINPUT
LRESULT CALLBACK wnd_proc_wgl_dinput(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
return wnd_proc_wgl_wm_create(hwnd);
return wnd_proc_common_dinput_internal(hwnd, message, wparam, lparam);
}
#endif
#ifdef HAVE_WINRAWINPUT
LRESULT CALLBACK wnd_proc_wgl_winraw(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
return wnd_proc_wgl_wm_create(hwnd);
return wnd_proc_winraw_common_internal(hwnd, message, wparam, lparam);
}
#endif
LRESULT CALLBACK wnd_proc_wgl_common(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
return wnd_proc_wgl_wm_create(hwnd);
return wnd_proc_common_internal(hwnd, message, wparam, lparam);
}
#endif
#ifdef HAVE_VULKAN
@@ -1420,6 +1718,33 @@ static LRESULT wnd_proc_wm_vk_create(HWND hwnd)
return 0;
}
#ifdef HAVE_DINPUT
LRESULT CALLBACK wnd_proc_vk_dinput(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
return wnd_proc_wm_vk_create(hwnd);
return wnd_proc_common_dinput_internal(hwnd, message, wparam, lparam);
}
#endif
#ifdef HAVE_WINRAWINPUT
LRESULT CALLBACK wnd_proc_vk_winraw(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
return wnd_proc_wm_vk_create(hwnd);
return wnd_proc_winraw_common_internal(hwnd, message, wparam, lparam);
}
#endif
LRESULT CALLBACK wnd_proc_vk_common(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
return wnd_proc_wm_vk_create(hwnd);
return wnd_proc_common_internal(hwnd, message, wparam, lparam);
}
#endif
#ifdef HAVE_GDI
@@ -1434,7 +1759,8 @@ static LRESULT wnd_proc_wm_gdi_create(HWND hwnd)
return 0;
}
/* The WM_PAINT body for a GDI window. Presents gdi->bmp scaled into the
/* Shared WM_PAINT body for all three GDI window procs (dinput,
* winraw, common). Presents gdi->bmp scaled into the
* aspect-ratio-aware viewport rect (gdi->vp), filling the area
* outside the rect with black to produce letterbox / pillarbox
* bars. Reads bmp_dims for the source rect (the DDB's actual
@@ -1503,79 +1829,55 @@ static void wnd_proc_gdi_paint(gdi_t *gdi)
SelectObject(gdi->memDC, gdi->bmp_old);
}
#endif
/* The window procedure: one, for every video driver and every input
* driver.
*
* A video family differs from another in what creating the window
* sets up - a GL context, a Vulkan surface, a device context - and GDI
* also paints from here. Everything else is win32_wnd_proc_route(). */
LRESULT CALLBACK win32_window_proc(HWND hwnd, UINT message,
#ifdef HAVE_DINPUT
LRESULT CALLBACK wnd_proc_gdi_dinput(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
{
switch (win32_wnd_family)
{
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGL1) || defined(HAVE_OPENGL_CORE)
case WIN32_WINDOW_WGL:
return wnd_proc_wgl_wm_create(hwnd);
#endif
#ifdef HAVE_VULKAN
case WIN32_WINDOW_VULKAN:
return wnd_proc_wm_vk_create(hwnd);
#endif
#ifdef HAVE_GDI
case WIN32_WINDOW_GDI:
return wnd_proc_wm_gdi_create(hwnd);
#endif
case WIN32_WINDOW_D3D:
default:
break;
}
if (DragAcceptFiles_func)
DragAcceptFiles_func(hwnd, true);
g_win32_flags |= WIN32_CMN_FLAG_INITED;
return 0;
}
#ifdef HAVE_GDI
if (message == WM_PAINT && win32_wnd_family == WIN32_WINDOW_GDI)
return wnd_proc_wm_gdi_create(hwnd);
else if (message == WM_PAINT)
{
gdi_t *gdi = (gdi_t*)video_driver_get_ptr();
if (gdi && gdi->memDC)
wnd_proc_gdi_paint(gdi);
}
#endif
return win32_wnd_proc_route(hwnd, message, wparam, lparam);
return wnd_proc_common_dinput_internal(hwnd, message, wparam, lparam);
}
/* Called by a video driver before it creates its window: which family
* the window is, so that its creation sets up the right thing.
*
* The kind of input driver is read from the setting here, once, the
* way each video driver used to read it to choose among its three
* procedures. */
void win32_window_proc_setup(enum win32_window_family family)
{
settings_t *settings = config_get_ptr();
win32_wnd_family = family;
win32_wnd_input = WIN32_INPUT_OTHER;
#ifdef HAVE_DINPUT
if (string_is_equal(settings->arrays.input_driver, "dinput"))
win32_wnd_input = WIN32_INPUT_DINPUT;
#endif
#ifdef HAVE_WINRAWINPUT
if (string_is_equal(settings->arrays.input_driver, "raw"))
win32_wnd_input = WIN32_INPUT_WINRAW;
#endif
(void)settings;
LRESULT CALLBACK wnd_proc_gdi_winraw(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
return wnd_proc_wm_gdi_create(hwnd);
else if (message == WM_PAINT)
{
gdi_t *gdi = (gdi_t*)video_driver_get_ptr();
if (gdi && gdi->memDC)
wnd_proc_gdi_paint(gdi);
}
return wnd_proc_winraw_common_internal(hwnd, message, wparam, lparam);
}
#endif
LRESULT CALLBACK wnd_proc_gdi_common(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
return wnd_proc_wm_gdi_create(hwnd);
else if (message == WM_PAINT)
{
gdi_t *gdi = (gdi_t*)video_driver_get_ptr();
if (gdi && gdi->memDC)
wnd_proc_gdi_paint(gdi);
}
return wnd_proc_common_internal(hwnd, message, wparam, lparam);
}
#endif
static bool win32_window_create(void *data, unsigned style,
RECT *mon_rect, unsigned width,
+25 -14
View File
@@ -177,21 +177,32 @@ uint16_t win32_update_keyboard_mods(void);
* Safe from any thread. */
uint16_t win32_get_keyboard_mods(void);
/* The video family a window belongs to: what creating it sets up. */
enum win32_window_family
{
WIN32_WINDOW_D3D = 0,
WIN32_WINDOW_WGL,
WIN32_WINDOW_VULKAN,
WIN32_WINDOW_GDI
};
/* The window procedure, for every video driver. A driver registers it
* for its window class and says which family the window is before
* creating it. */
LRESULT CALLBACK win32_window_proc(HWND hwnd, UINT message,
#if defined(HAVE_D3D8) || defined(HAVE_D3D9) || defined (HAVE_D3D10) || defined (HAVE_D3D11) || defined (HAVE_D3D12)
LRESULT CALLBACK wnd_proc_d3d_dinput(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam);
void win32_window_proc_setup(enum win32_window_family family);
LRESULT CALLBACK wnd_proc_d3d_winraw(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam);
LRESULT CALLBACK wnd_proc_d3d_common(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam);
#endif
#if defined(HAVE_VULKAN)
LRESULT CALLBACK wnd_proc_vk_dinput(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam);
LRESULT CALLBACK wnd_proc_vk_winraw(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam);
LRESULT CALLBACK wnd_proc_vk_common(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam);
#endif
#if defined(HAVE_GDI)
LRESULT CALLBACK wnd_proc_gdi_dinput(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam);
LRESULT CALLBACK wnd_proc_gdi_winraw(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam);
LRESULT CALLBACK wnd_proc_gdi_common(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam);
#endif
#ifdef _XBOX
BOOL IsIconic(HWND hwnd);
-220
View File
@@ -1,220 +0,0 @@
/* RetroArch - A frontend for libretro.
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _WIN32_MSG_ROUTE_H
#define _WIN32_MSG_ROUTE_H
#include <boolean.h>
#include <retro_inline.h>
/* What the Win32 window procedure does with a message.
*
* There used to be twelve window procedures: one for each video family
* (Direct3D, WGL, Vulkan, GDI) times each kind of input driver
* (DirectInput, raw input, any other), built on three copies of one
* long switch that differed in a few cases each. A video driver chose
* its procedure by comparing the input driver's name.
*
* There is one procedure now, and this says what it does. For a
* message and the kind of input driver in use, win32_msg_route()
* answers with the steps to take, which the procedure carries out in
* a fixed order:
*
* IME, key, clip, input, common, display - then DefWindowProc.
*
* Any step may answer the message and end it there, as marked below.
* The three switches are gone; what each did is the route for its
* kind, and samples/gfx/win32_msg_route holds the routes to the
* switches they replace, message by message.
*
* No Windows types, so that the sample can build it on a host. The
* message numbers are Windows' own, spelled out; win32_common.c checks
* them against the SDK's at compile time. */
enum win32_input_kind
{
WIN32_INPUT_OTHER = 0, /* neither of the two below */
WIN32_INPUT_DINPUT, /* the "dinput" input driver */
WIN32_INPUT_WINRAW /* the "raw" input driver */
};
/* The steps, in the order they are taken. */
/* An IME composition ended: a keyboard event says so. */
#define WIN32_ROUTE_IME_END (1 << 0)
/* IME composition text: a keyboard event per character. Answers 0. */
#define WIN32_ROUTE_IME_TEXT (1 << 1)
/* A key message. Answers 0 unless it is a system key press other than
* F10, Alt and right Shift, which goes on to the default. */
#define WIN32_ROUTE_KEY (1 << 2)
/* ...whose Shift and Alt keys are offered to the input driver first;
* answers 0 if the driver takes one. */
#define WIN32_ROUTE_KEY_MODS (1 << 3)
/* ...and which is turned into a keyboard event here. (The raw input
* driver makes its own from WM_INPUT.) */
#define WIN32_ROUTE_KEY_EVENT (1 << 4)
/* Focus gained or lost: confine the cursor, or let it go, if the
* mouse is grabbed. */
#define WIN32_ROUTE_CLIP_ON (1 << 5)
#define WIN32_ROUTE_CLIP_OFF (1 << 6)
/* Offered to the input driver. Answers 0 if the driver takes it. */
#define WIN32_ROUTE_INPUT (1 << 7)
/* wnd_proc_common(): the window's own business. Answers with its
* result if it says the message is done. */
#define WIN32_ROUTE_COMMON (1 << 8)
/* The display mode changed. */
#define WIN32_ROUTE_DISPLAY (1 << 9)
/* Windows' message numbers. */
#define WIN32_MSG_DESTROY 0x0002
#define WIN32_MSG_MOVE 0x0003
#define WIN32_MSG_SIZE 0x0005
#define WIN32_MSG_SETFOCUS 0x0007
#define WIN32_MSG_KILLFOCUS 0x0008
#define WIN32_MSG_CLOSE 0x0010
#define WIN32_MSG_QUIT 0x0012
#define WIN32_MSG_GETMINMAXINFO 0x0024
#define WIN32_MSG_DISPLAYCHANGE 0x007E
#define WIN32_MSG_NCLBUTTONDBLCLK 0x00A3
#define WIN32_MSG_KEYDOWN 0x0100
#define WIN32_MSG_KEYUP 0x0101
#define WIN32_MSG_CHAR 0x0102
#define WIN32_MSG_SYSKEYDOWN 0x0104
#define WIN32_MSG_SYSKEYUP 0x0105
#define WIN32_MSG_IME_ENDCOMPOSITION 0x010E
#define WIN32_MSG_IME_COMPOSITION 0x010F
#define WIN32_MSG_COMMAND 0x0111
#define WIN32_MSG_SYSCOMMAND 0x0112
#define WIN32_MSG_TIMER 0x0113
#define WIN32_MSG_MOUSEMOVE 0x0200
#define WIN32_MSG_MOUSEWHEEL 0x020A
#define WIN32_MSG_MOUSEHWHEEL 0x020E
#define WIN32_MSG_ENTERMENULOOP 0x0211
#define WIN32_MSG_EXITMENULOOP 0x0212
#define WIN32_MSG_POWERBROADCAST 0x0218
#define WIN32_MSG_DEVICECHANGE 0x0219
#define WIN32_MSG_ENTERSIZEMOVE 0x0231
#define WIN32_MSG_EXITSIZEMOVE 0x0232
#define WIN32_MSG_DROPFILES 0x0233
#define WIN32_MSG_POINTERUPDATE 0x0245
#define WIN32_MSG_POINTERDOWN 0x0246
#define WIN32_MSG_POINTERUP 0x0247
/* WM_USER + 0 and + 1: the file browser thread's answers */
#define WIN32_MSG_BROWSER_OPEN_RESULT 0x0400
#define WIN32_MSG_BROWSER_CANCELLED 0x0401
/* The timer that re-checks controllers after a device change; its id
* arrives as a timer message's wparam. */
#define WIN32_MSG_HOTPLUG_TIMER_ID 0x5242
/* @desktop is false on the Xbox, where the window has no move or menu
* loops, timers or power messages and the input drivers are not
* offered anything. @threads says whether the file browser's messages
* exist. @wparam_is_hotplug_timer is (wparam == WIN32_MSG_HOTPLUG_TIMER_ID). */
static INLINE unsigned win32_msg_route(enum win32_input_kind input,
bool desktop, bool threads, unsigned message,
bool wparam_is_hotplug_timer)
{
bool driver = (input != WIN32_INPUT_OTHER);
switch (message)
{
case WIN32_MSG_IME_ENDCOMPOSITION:
return (input == WIN32_INPUT_DINPUT) ? WIN32_ROUTE_IME_END : 0;
case WIN32_MSG_IME_COMPOSITION:
return (input == WIN32_INPUT_DINPUT) ? WIN32_ROUTE_IME_TEXT : 0;
case WIN32_MSG_KEYDOWN:
case WIN32_MSG_KEYUP:
case WIN32_MSG_SYSKEYDOWN:
case WIN32_MSG_SYSKEYUP:
switch (input)
{
case WIN32_INPUT_DINPUT:
return WIN32_ROUTE_KEY | WIN32_ROUTE_KEY_MODS
| WIN32_ROUTE_KEY_EVENT;
case WIN32_INPUT_WINRAW:
return WIN32_ROUTE_KEY;
default:
break;
}
return WIN32_ROUTE_KEY | WIN32_ROUTE_KEY_EVENT;
/* the mouse and the pen: DirectInput reads them from here */
case WIN32_MSG_MOUSEMOVE:
case WIN32_MSG_POINTERDOWN:
case WIN32_MSG_POINTERUP:
case WIN32_MSG_POINTERUPDATE:
case WIN32_MSG_MOUSEWHEEL:
case WIN32_MSG_MOUSEHWHEEL:
case WIN32_MSG_NCLBUTTONDBLCLK:
return (desktop && input == WIN32_INPUT_DINPUT)
? WIN32_ROUTE_INPUT : 0;
case WIN32_MSG_DEVICECHANGE:
return (desktop && driver) ? WIN32_ROUTE_INPUT : 0;
/* The window's own business. With an input driver these are
* also where the hotplug timer is looked for - under the timer
* message, and under the rest of this group by the id alone,
* which is how the switches had it. */
case WIN32_MSG_DROPFILES:
case WIN32_MSG_SYSCOMMAND:
case WIN32_MSG_CHAR:
case WIN32_MSG_CLOSE:
case WIN32_MSG_DESTROY:
case WIN32_MSG_QUIT:
case WIN32_MSG_MOVE:
case WIN32_MSG_SIZE:
return WIN32_ROUTE_COMMON
| ((desktop && driver && wparam_is_hotplug_timer)
? WIN32_ROUTE_INPUT : 0);
case WIN32_MSG_TIMER:
if (!desktop)
return 0;
return WIN32_ROUTE_COMMON
| ((driver && wparam_is_hotplug_timer) ? WIN32_ROUTE_INPUT : 0);
case WIN32_MSG_ENTERSIZEMOVE:
case WIN32_MSG_EXITSIZEMOVE:
case WIN32_MSG_ENTERMENULOOP:
case WIN32_MSG_EXITMENULOOP:
case WIN32_MSG_POWERBROADCAST:
return desktop ? WIN32_ROUTE_COMMON : 0;
case WIN32_MSG_GETMINMAXINFO:
case WIN32_MSG_COMMAND:
return WIN32_ROUTE_COMMON;
case WIN32_MSG_BROWSER_OPEN_RESULT:
case WIN32_MSG_BROWSER_CANCELLED:
return threads ? WIN32_ROUTE_COMMON : 0;
case WIN32_MSG_SETFOCUS:
return WIN32_ROUTE_CLIP_ON
| ((desktop && driver) ? WIN32_ROUTE_INPUT : 0);
case WIN32_MSG_KILLFOCUS:
return WIN32_ROUTE_CLIP_OFF
| ((desktop && driver) ? WIN32_ROUTE_INPUT : 0);
case WIN32_MSG_DISPLAYCHANGE:
return WIN32_ROUTE_DISPLAY;
default:
break;
}
return 0;
}
#endif
+9 -4
View File
@@ -2270,10 +2270,15 @@ static void *d3d10_gfx_init(const video_info_t* video,
#endif
#ifdef HAVE_MONITOR
win32_monitor_init();
/* one window procedure for every video and input driver; the
* family says what creating the window sets up */
wndclass.lpfnWndProc = win32_window_proc;
win32_window_proc_setup(WIN32_WINDOW_D3D);
wndclass.lpfnWndProc = wnd_proc_d3d_common;
#ifdef HAVE_DINPUT
if (string_is_equal(settings->arrays.input_driver, "dinput"))
wndclass.lpfnWndProc = wnd_proc_d3d_dinput;
#endif
#ifdef HAVE_WINRAWINPUT
if (string_is_equal(settings->arrays.input_driver, "raw"))
wndclass.lpfnWndProc = wnd_proc_d3d_winraw;
#endif
#ifdef HAVE_WINDOW
win32_window_init(&wndclass, true, NULL);
#endif
+9 -4
View File
@@ -3558,10 +3558,15 @@ static void *d3d11_gfx_init(const video_info_t* video,
#endif
#ifdef HAVE_MONITOR
win32_monitor_init();
/* one window procedure for every video and input driver; the
* family says what creating the window sets up */
wndclass.lpfnWndProc = win32_window_proc;
win32_window_proc_setup(WIN32_WINDOW_D3D);
wndclass.lpfnWndProc = wnd_proc_d3d_common;
#ifdef HAVE_DINPUT
if (string_is_equal(settings->arrays.input_driver, "dinput"))
wndclass.lpfnWndProc = wnd_proc_d3d_dinput;
#endif
#ifdef HAVE_WINRAWINPUT
if (string_is_equal(settings->arrays.input_driver, "raw"))
wndclass.lpfnWndProc = wnd_proc_d3d_winraw;
#endif
#ifdef HAVE_WINDOW
win32_window_init(&wndclass, true, NULL);
#endif
+9 -4
View File
@@ -4972,10 +4972,15 @@ static void *d3d12_gfx_init(const video_info_t* video,
#endif
#ifdef HAVE_MONITOR
win32_monitor_init();
/* one window procedure for every video and input driver; the
* family says what creating the window sets up */
wndclass.lpfnWndProc = win32_window_proc;
win32_window_proc_setup(WIN32_WINDOW_D3D);
wndclass.lpfnWndProc = wnd_proc_d3d_common;
#ifdef HAVE_DINPUT
if (string_is_equal(settings->arrays.input_driver, "dinput"))
wndclass.lpfnWndProc = wnd_proc_d3d_dinput;
#endif
#ifdef HAVE_WINRAWINPUT
if (string_is_equal(settings->arrays.input_driver, "raw"))
wndclass.lpfnWndProc = wnd_proc_d3d_winraw;
#endif
#ifdef HAVE_WINDOW
win32_window_init(&wndclass, true, NULL);
#endif
+9 -4
View File
@@ -2405,10 +2405,15 @@ static bool d3d8_init_internal(d3d8_video_t *d3d,
#ifdef HAVE_WINDOW
memset(&d3d->windowClass, 0, sizeof(d3d->windowClass));
/* one window procedure for every video and input driver; the
* family says what creating the window sets up */
d3d->windowClass.lpfnWndProc = win32_window_proc;
win32_window_proc_setup(WIN32_WINDOW_D3D);
d3d->windowClass.lpfnWndProc = wnd_proc_d3d_common;
#ifdef HAVE_DINPUT
if (string_is_equal(settings->arrays.input_driver, "dinput"))
d3d->windowClass.lpfnWndProc = wnd_proc_d3d_dinput;
#endif
#ifdef HAVE_WINRAWINPUT
if (string_is_equal(settings->arrays.input_driver, "raw"))
d3d->windowClass.lpfnWndProc = wnd_proc_d3d_winraw;
#endif
win32_window_init(&d3d->windowClass, true, NULL);
#endif
+9 -4
View File
@@ -3785,10 +3785,15 @@ static bool d3d9_cg_init_internal(d3d9_video_t *d3d,
#ifdef HAVE_WINDOW
memset(&d3d->windowClass, 0, sizeof(d3d->windowClass));
/* one window procedure for every video and input driver; the
* family says what creating the window sets up */
d3d->windowClass.lpfnWndProc = win32_window_proc;
win32_window_proc_setup(WIN32_WINDOW_D3D);
d3d->windowClass.lpfnWndProc = wnd_proc_d3d_common;
#ifdef HAVE_DINPUT
if (string_is_equal(settings->arrays.input_driver, "dinput"))
d3d->windowClass.lpfnWndProc = wnd_proc_d3d_dinput;
#endif
#ifdef HAVE_WINRAWINPUT
if (string_is_equal(settings->arrays.input_driver, "raw"))
d3d->windowClass.lpfnWndProc = wnd_proc_d3d_winraw;
#endif
win32_window_init(&d3d->windowClass, true, NULL);
#endif
+9 -4
View File
@@ -7140,10 +7140,15 @@ static bool d3d9_hlsl_init_internal(d3d9_video_t *d3d,
#ifdef HAVE_WINDOW
memset(&d3d->windowClass, 0, sizeof(d3d->windowClass));
/* one window procedure for every video and input driver; the
* family says what creating the window sets up */
d3d->windowClass.lpfnWndProc = win32_window_proc;
win32_window_proc_setup(WIN32_WINDOW_D3D);
d3d->windowClass.lpfnWndProc = wnd_proc_d3d_common;
#ifdef HAVE_DINPUT
if (string_is_equal(settings->arrays.input_driver, "dinput"))
d3d->windowClass.lpfnWndProc = wnd_proc_d3d_dinput;
#endif
#ifdef HAVE_WINRAWINPUT
if (string_is_equal(settings->arrays.input_driver, "raw"))
d3d->windowClass.lpfnWndProc = wnd_proc_d3d_winraw;
#endif
win32_window_init(&d3d->windowClass, true, NULL);
#endif
+9 -4
View File
@@ -2319,10 +2319,15 @@ static bool gfx_ctx_gdi_init(void)
win32_window_reset();
win32_monitor_init();
/* one window procedure for every video and input driver; the
* family says what creating the window sets up */
wndclass.lpfnWndProc = win32_window_proc;
win32_window_proc_setup(WIN32_WINDOW_GDI);
wndclass.lpfnWndProc = wnd_proc_gdi_common;
#ifdef HAVE_DINPUT
if (string_is_equal(settings->arrays.input_driver, "dinput"))
wndclass.lpfnWndProc = wnd_proc_gdi_dinput;
#endif
#ifdef HAVE_WINRAWINPUT
if (string_is_equal(settings->arrays.input_driver, "raw"))
wndclass.lpfnWndProc = wnd_proc_gdi_winraw;
#endif
if (!win32_window_init(&wndclass, true, NULL))
return false;
return true;
+1 -1
View File
@@ -398,7 +398,7 @@ static void *sdl2_gfx_init(const video_info_t *video,
*
* Unlike the d3d8 / d3d9 / d3d11 / d3d12 drivers - which create
* their main window with a winraw-aware WndProc
* (win32_window_proc, see gfx/common/win32_common.c) - the SDL2
* (wnd_proc_d3d_winraw, see gfx/common/win32_common.c) - the SDL2
* window's WndProc is owned by SDL and we cannot replace it.
*
* Warn loudly so users hitting silent broken-input understand
+12 -4
View File
@@ -196,10 +196,18 @@ static void *gfx_ctx_w_vk_init(void *video_driver)
win32_window_reset();
win32_monitor_init();
/* one window procedure for every video and input driver; the
* family says what creating the window sets up */
wndclass.lpfnWndProc = win32_window_proc;
win32_window_proc_setup(WIN32_WINDOW_VULKAN);
{
settings_t *settings = config_get_ptr();
wndclass.lpfnWndProc = wnd_proc_vk_common;
#ifdef HAVE_DINPUT
if (string_is_equal(settings->arrays.input_driver, "dinput"))
wndclass.lpfnWndProc = wnd_proc_vk_dinput;
#endif
#ifdef HAVE_WINRAWINPUT
if (string_is_equal(settings->arrays.input_driver, "raw"))
wndclass.lpfnWndProc = wnd_proc_vk_winraw;
#endif
}
if (!win32_window_init(&wndclass, true, NULL))
goto error;
+17 -4
View File
@@ -135,6 +135,14 @@ WINGDIAPI BOOL WINAPI wglSwapBuffers(HDC);
#endif
#endif
/* Forward declarations */
LRESULT CALLBACK wnd_proc_wgl_common(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam);
LRESULT CALLBACK wnd_proc_wgl_dinput(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam);
LRESULT CALLBACK wnd_proc_wgl_winraw(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam);
static BOOL (APIENTRY *p_swap_interval)(int);
enum wgl_flags
@@ -654,10 +662,15 @@ static void *gfx_ctx_wgl_init(void *video_driver)
win32_monitor_init();
/* one window procedure for every video and input driver; the
* family says what creating the window sets up */
wndclass.lpfnWndProc = win32_window_proc;
win32_window_proc_setup(WIN32_WINDOW_WGL);
wndclass.lpfnWndProc = wnd_proc_wgl_common;
#ifdef HAVE_DINPUT
if (string_is_equal(settings->arrays.input_driver, "dinput"))
wndclass.lpfnWndProc = wnd_proc_wgl_dinput;
#endif
#ifdef HAVE_WINRAWINPUT
if (string_is_equal(settings->arrays.input_driver, "raw"))
wndclass.lpfnWndProc = wnd_proc_wgl_winraw;
#endif
if (!win32_window_init(&wndclass, true, NULL))
{
-34
View File
@@ -1,34 +0,0 @@
TARGET := win32_msg_route_test
LIBRETRO_COMM_DIR := ../../../libretro-common
COMMON_DIR := ../../../gfx/common
# The routing is the window procedure's own (win32_msg_route.h, which
# takes no Windows types); the three switches it replaced are written
# out in the test, as they stood, to hold it to them.
SOURCES := win32_msg_route_test.c
OBJS := $(SOURCES:.c=.o)
CFLAGS += -Wall -Wextra -std=c89 -pedantic -g -O1 \
-I$(LIBRETRO_COMM_DIR)/include -I$(COMMON_DIR)
ifneq ($(SANITIZER),)
CFLAGS := -fsanitize=$(SANITIZER) -fno-omit-frame-pointer $(CFLAGS)
LDFLAGS := -fsanitize=$(SANITIZER) $(LDFLAGS)
endif
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) -o $@ $(OBJS) $(LDFLAGS)
win32_msg_route_test.o: $(COMMON_DIR)/win32_msg_route.h
check: all
./$(TARGET)
clean:
rm -f $(OBJS) $(TARGET)
.PHONY: all check clean
@@ -1,353 +0,0 @@
/* win32_msg_route_test.c -- what the Win32 window procedure does with
* a message, held to the three switches it replaced.
*
* gfx/common/win32_common.c had three window procedures that were one
* long switch each - for the DirectInput driver, the raw input driver,
* and any other - and twelve exported ones built on them. They are one
* procedure now, which asks win32_msg_route() what to do with a
* message.
*
* The three switches are written out below as they stood, case list
* for case list and #if for #if, each returning the steps its case
* took. The claim:
*
* For every message, with and without the hotplug timer's id in
* wparam, on the desktop and on the Xbox, with and without threads,
* win32_msg_route() gives the steps the old switch for that kind of
* input driver took.
*
* A sabotage mode routes one message the way another kind's switch did
* - raw input's keys made into keyboard events here, which would give
* every key press twice - and is asserted to be caught. */
#include <stdio.h>
#include <boolean.h>
#include "win32_msg_route.h"
/* winuser.h, as far as the switches use it */
#define WM_DESTROY 0x0002
#define WM_MOVE 0x0003
#define WM_SIZE 0x0005
#define WM_SETFOCUS 0x0007
#define WM_KILLFOCUS 0x0008
#define WM_CLOSE 0x0010
#define WM_QUIT 0x0012
#define WM_GETMINMAXINFO 0x0024
#define WM_DISPLAYCHANGE 0x007E
#define WM_NCLBUTTONDBLCLK 0x00A3
#define WM_KEYDOWN 0x0100
#define WM_KEYUP 0x0101
#define WM_CHAR 0x0102
#define WM_SYSKEYDOWN 0x0104
#define WM_SYSKEYUP 0x0105
#define WM_IME_ENDCOMPOSITION 0x010E
#define WM_IME_COMPOSITION 0x010F
#define WM_COMMAND 0x0111
#define WM_SYSCOMMAND 0x0112
#define WM_TIMER 0x0113
#define WM_MOUSEMOVE 0x0200
#define WM_MOUSEWHEEL 0x020A
#define WM_MOUSEHWHEEL 0x020E
#define WM_ENTERMENULOOP 0x0211
#define WM_EXITMENULOOP 0x0212
#define WM_POWERBROADCAST 0x0218
#define WM_DEVICECHANGE 0x0219
#define WM_ENTERSIZEMOVE 0x0231
#define WM_EXITSIZEMOVE 0x0232
#define WM_DROPFILES 0x0233
#define WM_POINTERUPDATE 0x0245
#define WM_POINTERDOWN 0x0246
#define WM_POINTERUP 0x0247
#define WM_USER 0x0400
#define WM_BROWSER_OPEN_RESULT (WM_USER + 0)
#define WM_BROWSER_CANCELLED (WM_USER + 1)
static unsigned failures = 0;
static bool quiet = false;
/* The steps a case took, in the new names. */
#define IME_END WIN32_ROUTE_IME_END
#define IME_TEXT WIN32_ROUTE_IME_TEXT
#define KEY WIN32_ROUTE_KEY
#define KEY_MODS WIN32_ROUTE_KEY_MODS
#define KEY_EVENT WIN32_ROUTE_KEY_EVENT
#define CLIP_ON WIN32_ROUTE_CLIP_ON
#define CLIP_OFF WIN32_ROUTE_CLIP_OFF
#define INPUT WIN32_ROUTE_INPUT
#define COMMON WIN32_ROUTE_COMMON
#define DISPLAY WIN32_ROUTE_DISPLAY
/* wnd_proc_common_internal(), as it stood. `xbox` stands for
* defined(_XBOX) and `threads` for defined(HAVE_THREADS). */
static unsigned old_common(unsigned message, bool hotplug, bool xbox, bool threads)
{
(void)hotplug;
switch (message)
{
case WM_KEYUP:
case WM_SYSKEYUP:
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
return KEY | KEY_EVENT;
case WM_MOUSEMOVE:
case WM_POINTERDOWN:
case WM_POINTERUP:
case WM_POINTERUPDATE:
case WM_DEVICECHANGE:
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
case WM_NCLBUTTONDBLCLK:
return 0;
case WM_DROPFILES:
case WM_SYSCOMMAND:
case WM_CHAR:
case WM_CLOSE:
case WM_DESTROY:
case WM_QUIT:
case WM_MOVE:
case WM_SIZE:
return COMMON;
/* #if !defined(_XBOX) */
case WM_ENTERSIZEMOVE:
case WM_EXITSIZEMOVE:
case WM_ENTERMENULOOP:
case WM_EXITMENULOOP:
case WM_TIMER:
case WM_POWERBROADCAST:
return xbox ? 0 : COMMON;
/* #endif */
case WM_GETMINMAXINFO:
case WM_COMMAND:
return COMMON;
/* #ifdef HAVE_THREADS */
case WM_BROWSER_OPEN_RESULT:
case WM_BROWSER_CANCELLED:
return threads ? COMMON : 0;
/* #endif */
case WM_SETFOCUS:
return CLIP_ON;
case WM_KILLFOCUS:
return CLIP_OFF;
case WM_DISPLAYCHANGE:
return DISPLAY;
}
return 0;
}
/* wnd_proc_winraw_common_internal(), as it stood. */
static unsigned old_winraw(unsigned message, bool hotplug, bool xbox, bool threads)
{
switch (message)
{
case WM_KEYUP:
case WM_SYSKEYUP:
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
/* keyboard_event in winraw_callback */
return KEY;
case WM_MOUSEMOVE:
case WM_POINTERDOWN:
case WM_POINTERUP:
case WM_POINTERUPDATE:
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
case WM_NCLBUTTONDBLCLK:
return 0;
case WM_DROPFILES:
case WM_SYSCOMMAND:
case WM_CHAR:
case WM_CLOSE:
case WM_DESTROY:
case WM_QUIT:
case WM_MOVE:
case WM_SIZE:
/* On the Xbox the timer block below is compiled out and these
* fall through to the group that only calls wnd_proc_common. */
if (xbox)
return COMMON;
/* fall-through */
case WM_TIMER:
if (xbox)
return 0; /* not a case there */
/* if (wparam == WIN32_HOTPLUG_TIMER_ID
* && winraw_handle_message(...)) return 0; */
return (hotplug ? INPUT : 0) | COMMON;
case WM_ENTERSIZEMOVE:
case WM_EXITSIZEMOVE:
case WM_ENTERMENULOOP:
case WM_EXITMENULOOP:
case WM_POWERBROADCAST:
return xbox ? 0 : COMMON;
case WM_GETMINMAXINFO:
case WM_COMMAND:
return COMMON;
case WM_BROWSER_OPEN_RESULT:
case WM_BROWSER_CANCELLED:
return threads ? COMMON : 0;
case WM_SETFOCUS:
return CLIP_ON | (xbox ? 0 : INPUT);
case WM_KILLFOCUS:
return CLIP_OFF | (xbox ? 0 : INPUT);
case WM_DISPLAYCHANGE:
return DISPLAY;
case WM_DEVICECHANGE:
return xbox ? 0 : INPUT;
}
return 0;
}
/* wnd_proc_common_dinput_internal(), as it stood. */
static unsigned old_dinput(unsigned message, bool hotplug, bool xbox, bool threads)
{
switch (message)
{
case WM_IME_ENDCOMPOSITION:
return IME_END;
case WM_IME_COMPOSITION:
return IME_TEXT;
case WM_KEYUP:
case WM_SYSKEYUP:
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
/* tell the driver about shift and alt key events */
return KEY | KEY_MODS | KEY_EVENT;
case WM_MOUSEMOVE:
case WM_POINTERDOWN:
case WM_POINTERUP:
case WM_POINTERUPDATE:
case WM_DEVICECHANGE:
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
case WM_NCLBUTTONDBLCLK:
return xbox ? 0 : INPUT;
case WM_DROPFILES:
case WM_SYSCOMMAND:
case WM_CHAR:
case WM_CLOSE:
case WM_DESTROY:
case WM_QUIT:
case WM_MOVE:
case WM_SIZE:
if (xbox)
return COMMON;
/* fall-through */
case WM_TIMER:
if (xbox)
return 0;
/* if (wparam == WIN32_HOTPLUG_TIMER_ID) { ...
* dinput_handle_message(...) -> return 0 } */
return (hotplug ? INPUT : 0) | COMMON;
case WM_ENTERSIZEMOVE:
case WM_EXITSIZEMOVE:
case WM_ENTERMENULOOP:
case WM_EXITMENULOOP:
case WM_POWERBROADCAST:
return xbox ? 0 : COMMON;
case WM_GETMINMAXINFO:
case WM_COMMAND:
return COMMON;
case WM_BROWSER_OPEN_RESULT:
case WM_BROWSER_CANCELLED:
return threads ? COMMON : 0;
case WM_SETFOCUS:
return CLIP_ON | (xbox ? 0 : INPUT);
case WM_KILLFOCUS:
return CLIP_OFF | (xbox ? 0 : INPUT);
case WM_DISPLAYCHANGE:
return DISPLAY;
}
return 0;
}
/* raw input's keys routed the way the other switches route theirs */
static bool sabotage_winraw_keys = false;
static unsigned route(enum win32_input_kind kind, bool desktop,
bool threads, unsigned message, bool hotplug)
{
if ( sabotage_winraw_keys
&& kind == WIN32_INPUT_WINRAW
&& message == WM_KEYDOWN)
kind = WIN32_INPUT_OTHER;
return win32_msg_route(kind, desktop, threads, message, hotplug);
}
static void lane_all_messages(void)
{
static const char *const kind_name[3] = { "other", "dinput", "raw" };
unsigned kind, xbox, threads, hotplug, message;
unsigned long compared = 0, wrong = 0;
for (kind = 0; kind < 3; kind++)
for (xbox = 0; xbox < 2; xbox++)
for (threads = 0; threads < 2; threads++)
for (hotplug = 0; hotplug < 2; hotplug++)
for (message = 0; message <= 0xffff; message++)
{
unsigned was, is;
switch (kind)
{
case WIN32_INPUT_DINPUT:
was = old_dinput(message, hotplug != 0, xbox != 0, threads != 0);
break;
case WIN32_INPUT_WINRAW:
was = old_winraw(message, hotplug != 0, xbox != 0, threads != 0);
break;
default:
was = old_common(message, hotplug != 0, xbox != 0, threads != 0);
break;
}
is = route((enum win32_input_kind)kind, !xbox,
threads != 0, message, hotplug != 0);
compared++;
if (was != is)
{
if (!wrong && !quiet)
fprintf(stderr, "FAIL: message 0x%04x, %s input,"
" %s%s%s: the switch took steps 0x%03x,"
" the route says 0x%03x\n",
message, kind_name[kind],
xbox ? "Xbox" : "desktop",
threads ? ", threads" : "",
hotplug ? ", hotplug timer id" : "",
was, is);
wrong++;
}
}
if (wrong)
failures += (unsigned)wrong;
else if (!quiet)
fprintf(stderr, "[pass] %lu message routes are what the three"
" switches did\n", compared);
}
int main(void)
{
lane_all_messages();
if (failures)
{
fprintf(stderr, "FAIL win32_msg_route_test: %u routes differ\n", failures);
return 1;
}
quiet = true;
sabotage_winraw_keys = true;
lane_all_messages();
quiet = false;
sabotage_winraw_keys = false;
if (!failures)
{
fprintf(stderr, "FAIL win32_msg_route_test: raw input's keys made"
" into keyboard events a second time went unnoticed\n");
return 1;
}
fprintf(stderr, "PASS win32_msg_route_test (sabotage caught by %u"
" checks)\n", failures);
return 0;
}