From 42e759ade491813588fda7cb185878d80a831a05 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Tue, 28 Feb 2023 05:16:13 +1100 Subject: [PATCH] osd/modules/input: Always use DirectInput with desktop window in background mode. There are multiple issues with what MAME was doing, but the most glaring is that it violates the DirectInput interface contract that requires the window associated with an open device must not be destroyed. See documentation for IDirectInputDevice8::SetCooperativeLevel: "This parameter must be a valid top-level window handle that belongs to the process. The window associated with the device must not be destroyed while it is still active in a DirectInput device." The previous code also prevented DirectInput controllers from working when using multiple windows if any window other than the first window had focus. Also fixed SDL builds not correctly recognising when all windows lose focus, and save state menu not appearing. --- src/frontend/mame/ui/ui.cpp | 18 ++++-------------- src/osd/modules/input/input_dinput.cpp | 15 +++++++++++---- src/osd/sdl/osdsdl.cpp | 2 ++ 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp index 37f60a8795d..3907ad6ae71 100644 --- a/src/frontend/mame/ui/ui.cpp +++ b/src/frontend/mame/ui/ui.cpp @@ -53,18 +53,6 @@ #include -/*************************************************************************** - CONSTANTS -***************************************************************************/ - -enum -{ - LOADSAVE_NONE, - LOADSAVE_LOAD, - LOADSAVE_SAVE -}; - - /*************************************************************************** LOCAL VARIABLES ***************************************************************************/ @@ -1376,15 +1364,17 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) // handle a save state request if (machine().ui_input().pressed(IPT_UI_SAVE_STATE)) { + osd_printf_info("Save requested\n"); start_save_state(); - return LOADSAVE_SAVE; + return 0; } // handle a load state request if (machine().ui_input().pressed(IPT_UI_LOAD_STATE)) { + osd_printf_info("Load requested\n"); start_load_state(); - return LOADSAVE_LOAD; + return 0; } // handle a save snapshot request diff --git a/src/osd/modules/input/input_dinput.cpp b/src/osd/modules/input/input_dinput.cpp index 9bc417caf0f..6cbe668c108 100644 --- a/src/osd/modules/input/input_dinput.cpp +++ b/src/osd/modules/input/input_dinput.cpp @@ -1221,7 +1221,7 @@ std::pair, LPCDIDATAFORMAT> dinput_a // attempt to create a device Microsoft::WRL::ComPtr device; - result = m_dinput->CreateDevice(instance->guidInstance, device.GetAddressOf(), nullptr); + result = m_dinput->CreateDevice(instance->guidInstance, &device, nullptr); if (result != DI_OK) { osd_printf_error("DirectInput: Unable to create device.\n"); @@ -1245,7 +1245,13 @@ std::pair, LPCDIDATAFORMAT> dinput_a } // default window to the first window in the list - HWND window_handle; + // For now, we always use the desktop window due to multiple issues: + // * MAME recreates windows on toggling fullscreen. DirectInput really doesn't like this. + // * DirectInput doesn't like the window used for D3D fullscreen exclusive mode. + // * With multiple windows, the first window needs to have focus when using foreground mode. + // This makes it impossible to use force feedback as that requires foreground exclusive mode. + // The only way to get around this would be to reopen devices on focus changes. + [[maybe_unused]] HWND window_handle; DWORD di_cooperative_level; #if defined(OSD_WINDOWS) auto const &window = dynamic_cast(*osd_common_t::window_list().front()); @@ -1278,7 +1284,8 @@ std::pair, LPCDIDATAFORMAT> dinput_a di_cooperative_level = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE; break; case dinput_cooperative_level::FOREGROUND: - di_cooperative_level = DISCL_FOREGROUND | DISCL_NONEXCLUSIVE; + //di_cooperative_level = DISCL_FOREGROUND | DISCL_NONEXCLUSIVE; + di_cooperative_level = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE; break; default: throw false; @@ -1286,7 +1293,7 @@ std::pair, LPCDIDATAFORMAT> dinput_a } // set the cooperative level - result = device->SetCooperativeLevel(window_handle, di_cooperative_level); + result = device->SetCooperativeLevel(GetDesktopWindow(), di_cooperative_level); if (result != DI_OK) { osd_printf_error("DirectInput: Unable to set cooperative level.\n"); diff --git a/src/osd/sdl/osdsdl.cpp b/src/osd/sdl/osdsdl.cpp index ce1f5c74bf7..e02232ece1f 100644 --- a/src/osd/sdl/osdsdl.cpp +++ b/src/osd/sdl/osdsdl.cpp @@ -654,6 +654,8 @@ void sdl_osd_interface::process_window_event(SDL_Event const &event) break; case SDL_WINDOWEVENT_FOCUS_LOST: + if (window == m_focus_window) + m_focus_window = nullptr; machine().ui_input().push_window_defocus_event(window->target()); break;