From e0c5309bc3b048f94b978342f8eb16486a635760 Mon Sep 17 00:00:00 2001
From: Vojtech Bubnik <bubnikv@gmail.com>
Date: Wed, 14 Oct 2020 12:55:00 +0200
Subject: [PATCH] wxEVT_CREATE and wxEVT_ACTIVATE is not being called on the
 main frame on application start-up, at least not on Windows. wxEVT_CREATE was
 called for some control deep in the Plater, however the event was delivered
 to the main frame and only for slicer, not for G-code viewer. Thus the
 callbacks for 3D Mouse were not registered for and the 3D mouse did not work
 on Windows.

Fixed by calling the callback registration from the first execution
of the Idle function.
---
 src/PrusaSlicer.cpp          |   4 +-
 src/libslic3r/PrintBase.hpp  |   2 +-
 src/slic3r/GUI/GUI_App.cpp   |   7 ++-
 src/slic3r/GUI/GUI_App.hpp   |   4 +-
 src/slic3r/GUI/MainFrame.cpp | 117 +++++++++++++++++------------------
 src/slic3r/GUI/MainFrame.hpp |   3 +
 6 files changed, 71 insertions(+), 66 deletions(-)

diff --git a/src/PrusaSlicer.cpp b/src/PrusaSlicer.cpp
index b41894ebb..ccae13815 100644
--- a/src/PrusaSlicer.cpp
+++ b/src/PrusaSlicer.cpp
@@ -588,9 +588,9 @@ int CLI::run(int argc, char **argv)
 //		gui->autosave = m_config.opt_string("autosave");
         GUI::GUI_App::SetInstance(gui);
 #if ENABLE_GCODE_VIEWER
-        gui->m_after_init_loads.set_params(load_configs, m_extra_config, m_input_files, start_as_gcodeviewer);
+        gui->after_init_loads.set_params(load_configs, m_extra_config, m_input_files, start_as_gcodeviewer);
 #else
-        gui->m_after_init_loads.set_params(load_configs, m_extra_config, m_input_files);
+        gui->after_init_loads.set_params(load_configs, m_extra_config, m_input_files);
 #endif // ENABLE_GCODE_VIEWER
 /*
 #if ENABLE_GCODE_VIEWER
diff --git a/src/libslic3r/PrintBase.hpp b/src/libslic3r/PrintBase.hpp
index 647c24c1c..66851f16e 100644
--- a/src/libslic3r/PrintBase.hpp
+++ b/src/libslic3r/PrintBase.hpp
@@ -406,7 +406,7 @@ public:
         // set to an ObjectID of a Print or a PrintObject based on flags
         // (whether UPDATE_PRINT_STEP_WARNINGS or UPDATE_PRINT_OBJECT_STEP_WARNINGS is set).
         ObjectID        warning_object_id;
-        // For which Print or PrintObject step a new warning is beeing issued?
+        // For which Print or PrintObject step a new warning is being issued?
         int             warning_step { -1 };
     };
     typedef std::function<void(const SlicingStatus&)>  status_callback_type;
diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp
index d11ca1f38..f5624bb6a 100644
--- a/src/slic3r/GUI/GUI_App.cpp
+++ b/src/slic3r/GUI/GUI_App.cpp
@@ -533,7 +533,7 @@ static void generic_exception_handle()
     }
 }
 
-void GUI_App::AFTER_INIT_LOADS::on_loads(GUI_App* gui)
+void GUI_App::AfterInitLoads::on_loads(GUI_App* gui)
 {
     if (!gui->initialized())
         return;
@@ -847,7 +847,10 @@ bool GUI_App::on_init_inner()
         static bool update_gui_after_init = true;
         if (update_gui_after_init) {
             update_gui_after_init = false;
-            m_after_init_loads.on_loads(this);
+#ifdef WIN32
+            this->mainframe->register_win32_callbacks();
+#endif
+            this->after_init_loads.on_loads(this);
         }
 
 		// Preset updating & Configwizard are done after the above initializations,
diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp
index dd2d54c0d..fa2872a53 100644
--- a/src/slic3r/GUI/GUI_App.hpp
+++ b/src/slic3r/GUI/GUI_App.hpp
@@ -143,7 +143,7 @@ private:
 	size_t m_instance_hash_int;
 
     // parameters needed for the after OnInit() loads
-    struct AFTER_INIT_LOADS
+    struct AfterInitLoads 
     {
         std::vector<std::string>    m_load_configs;
         DynamicPrintConfig          m_extra_config;
@@ -272,7 +272,7 @@ public:
     PresetUpdater*  preset_updater{ nullptr };
     MainFrame*      mainframe{ nullptr };
     Plater*         plater_{ nullptr };
-    AFTER_INIT_LOADS m_after_init_loads;
+    AfterInitLoads  after_init_loads;
 
 	PresetUpdater* get_preset_updater() { return preset_updater; }
 
diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp
index 8db0bba5b..67ccd385e 100644
--- a/src/slic3r/GUI/MainFrame.cpp
+++ b/src/slic3r/GUI/MainFrame.cpp
@@ -217,65 +217,6 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
     update_title();
 
     // declare events
-    Bind(wxEVT_CREATE, [this](wxWindowCreateEvent& event) {
-
-#ifdef _WIN32
-		//static GUID GUID_DEVINTERFACE_USB_DEVICE	= { 0xA5DCBF10, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED };
-		//static GUID GUID_DEVINTERFACE_DISK 		= { 0x53f56307, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b };
-		//static GUID GUID_DEVINTERFACE_VOLUME 	    = { 0x71a27cdd, 0x812a, 0x11d0, 0xbe, 0xc7, 0x08, 0x00, 0x2b, 0xe2, 0x09, 0x2f };
-		static GUID GUID_DEVINTERFACE_HID			= { 0x4D1E55B2, 0xF16F, 0x11CF, 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 };
-
-    	// Register USB HID (Human Interface Devices) notifications to trigger the 3DConnexion enumeration.
-		DEV_BROADCAST_DEVICEINTERFACE NotificationFilter = { 0 };
-		NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
-		NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
-		NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_HID;
-		m_hDeviceNotify = ::RegisterDeviceNotification(this->GetHWND(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
-
-// or register for file handle change?
-//		DEV_BROADCAST_HANDLE NotificationFilter = { 0 };
-//		NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
-//		NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
-
-		// Using Win32 Shell API to register for media insert / removal events.
-		LPITEMIDLIST ppidl;
-		if (SHGetSpecialFolderLocation(this->GetHWND(), CSIDL_DESKTOP, &ppidl) == NOERROR) {
-			SHChangeNotifyEntry shCNE;
-			shCNE.pidl       = ppidl;
-			shCNE.fRecursive = TRUE;
-			// Returns a positive integer registration identifier (ID).
-			// Returns zero if out of memory or in response to invalid parameters.
-			m_ulSHChangeNotifyRegister = SHChangeNotifyRegister(this->GetHWND(),		// Hwnd to receive notification
-				SHCNE_DISKEVENTS,														// Event types of interest (sources)
-				SHCNE_MEDIAINSERTED | SHCNE_MEDIAREMOVED,
-				//SHCNE_UPDATEITEM,														// Events of interest - use SHCNE_ALLEVENTS for all events
-				WM_USER_MEDIACHANGED,													// Notification message to be sent upon the event
-				1,																		// Number of entries in the pfsne array
-				&shCNE);																// Array of SHChangeNotifyEntry structures that 
-																						// contain the notifications. This array should 
-																						// always be set to one when calling SHChnageNotifyRegister
-																						// or SHChangeNotifyDeregister will not work properly.
-			assert(m_ulSHChangeNotifyRegister != 0);    // Shell notification failed
-		} else {
-			// Failed to get desktop location
-			assert(false); 
-		}
-
-		{
-			static constexpr int device_count = 1;
-			RAWINPUTDEVICE devices[device_count] = { 0 };
-			// multi-axis mouse (SpaceNavigator, etc.)
-			devices[0].usUsagePage = 0x01;
-			devices[0].usUsage = 0x08;
-			if (! RegisterRawInputDevices(devices, device_count, sizeof(RAWINPUTDEVICE)))
-				BOOST_LOG_TRIVIAL(error) << "RegisterRawInputDevices failed";
-		}
-#endif // _WIN32
-
-        // propagate event
-        event.Skip();
-    });
-
     Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& event) {
         if (event.CanVeto() && !wxGetApp().check_unsaved_changes()) {
             event.Veto();
@@ -286,6 +227,8 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
         event.Skip();
     });
 
+    //FIXME it seems this method is not called on application start-up, at least not on Windows. Why?
+    // The same applies to wxEVT_CREATE, it is not being called on startup on Windows.
     Bind(wxEVT_ACTIVATE, [this](wxActivateEvent& event) {
         if (m_plater != nullptr && event.GetActive())
             m_plater->on_activate();
@@ -656,6 +599,62 @@ void MainFrame::init_tabpanel()
     }
 }
 
+#ifdef WIN32
+void MainFrame::register_win32_callbacks()
+{
+    //static GUID GUID_DEVINTERFACE_USB_DEVICE  = { 0xA5DCBF10, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED };
+    //static GUID GUID_DEVINTERFACE_DISK        = { 0x53f56307, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b };
+    //static GUID GUID_DEVINTERFACE_VOLUME      = { 0x71a27cdd, 0x812a, 0x11d0, 0xbe, 0xc7, 0x08, 0x00, 0x2b, 0xe2, 0x09, 0x2f };
+    static GUID GUID_DEVINTERFACE_HID           = { 0x4D1E55B2, 0xF16F, 0x11CF, 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 };
+
+    // Register USB HID (Human Interface Devices) notifications to trigger the 3DConnexion enumeration.
+    DEV_BROADCAST_DEVICEINTERFACE NotificationFilter = { 0 };
+    NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
+    NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
+    NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_HID;
+    m_hDeviceNotify = ::RegisterDeviceNotification(this->GetHWND(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
+
+// or register for file handle change?
+//      DEV_BROADCAST_HANDLE NotificationFilter = { 0 };
+//      NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
+//      NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
+
+    // Using Win32 Shell API to register for media insert / removal events.
+    LPITEMIDLIST ppidl;
+    if (SHGetSpecialFolderLocation(this->GetHWND(), CSIDL_DESKTOP, &ppidl) == NOERROR) {
+        SHChangeNotifyEntry shCNE;
+        shCNE.pidl       = ppidl;
+        shCNE.fRecursive = TRUE;
+        // Returns a positive integer registration identifier (ID).
+        // Returns zero if out of memory or in response to invalid parameters.
+        m_ulSHChangeNotifyRegister = SHChangeNotifyRegister(this->GetHWND(),        // Hwnd to receive notification
+            SHCNE_DISKEVENTS,                                                       // Event types of interest (sources)
+            SHCNE_MEDIAINSERTED | SHCNE_MEDIAREMOVED,
+            //SHCNE_UPDATEITEM,                                                     // Events of interest - use SHCNE_ALLEVENTS for all events
+            WM_USER_MEDIACHANGED,                                                   // Notification message to be sent upon the event
+            1,                                                                      // Number of entries in the pfsne array
+            &shCNE);                                                                // Array of SHChangeNotifyEntry structures that 
+                                                                                    // contain the notifications. This array should 
+                                                                                    // always be set to one when calling SHChnageNotifyRegister
+                                                                                    // or SHChangeNotifyDeregister will not work properly.
+        assert(m_ulSHChangeNotifyRegister != 0);    // Shell notification failed
+    } else {
+        // Failed to get desktop location
+        assert(false); 
+    }
+
+    {
+        static constexpr int device_count = 1;
+        RAWINPUTDEVICE devices[device_count] = { 0 };
+        // multi-axis mouse (SpaceNavigator, etc.)
+        devices[0].usUsagePage = 0x01;
+        devices[0].usUsage = 0x08;
+        if (! RegisterRawInputDevices(devices, device_count, sizeof(RAWINPUTDEVICE)))
+            BOOST_LOG_TRIVIAL(error) << "RegisterRawInputDevices failed";
+    }
+}
+#endif // _WIN32
+
 void MainFrame::create_preset_tabs()
 {
     wxGetApp().update_label_colours_from_appconfig();
diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp
index 9be9bbad9..3a8443cb8 100644
--- a/src/slic3r/GUI/MainFrame.hpp
+++ b/src/slic3r/GUI/MainFrame.hpp
@@ -156,6 +156,9 @@ public:
     void        create_preset_tabs();
     void        add_created_tab(Tab* panel);
     bool        is_active_and_shown_tab(Tab* tab);
+    // Register Win32 RawInput callbacks (3DConnexion) and removable media insert / remove callbacks.
+    // Called from wxEVT_ACTIVATE, as wxEVT_CREATE was not reliable (bug in wxWidgets?).
+    void        register_win32_callbacks();
 #if ENABLE_GCODE_VIEWER
     void        init_menubar_as_editor();
     void        init_menubar_as_gcodeviewer();