From 10d038e43f5f339bae967db5c6c88f4a05153feb Mon Sep 17 00:00:00 2001 From: Megamouse Date: Fri, 24 Jan 2025 19:01:16 +0100 Subject: [PATCH] Qt: Fix device notification registration segfault The main window does not exist if we boot with no-gui --- rpcs3/rpcs3qt/gui_application.cpp | 69 ++++++++++++++++++++++++------- rpcs3/rpcs3qt/gui_application.h | 4 ++ 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/rpcs3/rpcs3qt/gui_application.cpp b/rpcs3/rpcs3qt/gui_application.cpp index e25c0627f4..7c01333540 100644 --- a/rpcs3/rpcs3qt/gui_application.cpp +++ b/rpcs3/rpcs3qt/gui_application.cpp @@ -76,10 +76,7 @@ gui_application::~gui_application() discord::shutdown(); #endif #ifdef _WIN32 - if (m_device_notification_handle && !UnregisterDeviceNotification(m_device_notification_handle)) - { - gui_log.error("UnregisterDeviceNotification() failed: %s", fmt::win_error{GetLastError(), nullptr}); - } + unregister_device_notification(); #endif } @@ -205,17 +202,9 @@ bool gui_application::Init() #ifdef _WIN32 // Currently only needed for raw mouse input on windows installNativeEventFilter(&m_native_event_filter); - // Enable usb device hotplug events - // Currently only needed for hotplug on windows, as libusb handles other platforms - DEV_BROADCAST_DEVICEINTERFACE notification_filter {}; - notification_filter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); - notification_filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; - notification_filter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE; - - m_device_notification_handle = RegisterDeviceNotification(reinterpret_cast(m_main_window->winId()), ¬ification_filter, DEVICE_NOTIFY_WINDOW_HANDLE); - if (!m_device_notification_handle ) + if (m_main_window) { - gui_log.error("RegisterDeviceNotification() failed: %s", fmt::win_error{GetLastError(), nullptr}); + register_device_notification(m_main_window->winId()); } #endif @@ -491,11 +480,26 @@ std::unique_ptr gui_application::get_gs_frame() } m_game_window = frame; + ensure(m_game_window); + +#ifdef _WIN32 + if (!m_show_gui) + { + register_device_notification(m_game_window->winId()); + } +#endif connect(m_game_window, &gs_frame::destroyed, this, [this]() { gui_log.notice("gui_application: Deleting old game window"); m_game_window = nullptr; + +#ifdef _WIN32 + if (!m_show_gui) + { + unregister_device_notification(); + } +#endif }); return std::unique_ptr(frame); @@ -1234,3 +1238,40 @@ bool gui_application::native_event_filter::nativeEventFilter([[maybe_unused]] co return false; } + +#ifdef _WIN32 +void gui_application::register_device_notification(WId window_id) +{ + if (m_device_notification_handle) return; + + gui_log.notice("Registering device notifications..."); + + // Enable usb device hotplug events + // Currently only needed for hotplug on windows, as libusb handles other platforms + DEV_BROADCAST_DEVICEINTERFACE notification_filter {}; + notification_filter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); + notification_filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + notification_filter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE; + + m_device_notification_handle = RegisterDeviceNotification(reinterpret_cast(window_id), ¬ification_filter, DEVICE_NOTIFY_WINDOW_HANDLE); + if (!m_device_notification_handle ) + { + gui_log.error("RegisterDeviceNotification() failed: %s", fmt::win_error{GetLastError(), nullptr}); + } +} + +void gui_application::unregister_device_notification() +{ + if (m_device_notification_handle) + { + gui_log.notice("Unregistering device notifications..."); + + if (!UnregisterDeviceNotification(m_device_notification_handle)) + { + gui_log.error("UnregisterDeviceNotification() failed: %s", fmt::win_error{GetLastError(), nullptr}); + } + + m_device_notification_handle = {}; + } +} +#endif diff --git a/rpcs3/rpcs3qt/gui_application.h b/rpcs3/rpcs3qt/gui_application.h index f766c3b9c2..a09e7bb895 100644 --- a/rpcs3/rpcs3qt/gui_application.h +++ b/rpcs3/rpcs3qt/gui_application.h @@ -121,9 +121,13 @@ private: u64 m_pause_delayed_tag = 0; typename Emulator::stop_counter_t m_emu_focus_out_emulation_id{}; bool m_is_pause_on_focus_loss_active = false; + #ifdef _WIN32 + void register_device_notification(WId window_id); + void unregister_device_notification(); HDEVNOTIFY m_device_notification_handle {}; #endif + private Q_SLOTS: void OnChangeStyleSheetRequest(); void OnShortcutChange();