Browse Source

finish workaround for Vista keyboard issue

David Rose 16 years ago
parent
commit
13877e26b1

+ 20 - 2
direct/src/plugin/binaryXml.cxx

@@ -13,11 +13,14 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "binaryXml.h"
+#include "p3d_lock.h"
 #include <sstream>
 
-
 static const bool debug_xml_output = false;
 
+static LOCK xml_lock;
+static bool xml_lock_initialized = false;
+
 #define DO_BINARY_XML 1
 
 enum NodeType {
@@ -251,6 +254,11 @@ read_xml_node(istream &in, char *&buffer, size_t &buffer_length,
 ////////////////////////////////////////////////////////////////////
 void
 write_xml(ostream &out, TiXmlDocument *doc, ostream &logfile) {
+  if (!xml_lock_initialized) {
+    INIT_LOCK(xml_lock);
+  }
+  ACQUIRE_LOCK(xml_lock);
+
 #ifdef DO_BINARY_XML
   // Binary write.
   write_xml_node(out, doc);
@@ -274,6 +282,8 @@ write_xml(ostream &out, TiXmlDocument *doc, ostream &logfile) {
     logout << "sent: " << *doc << "\n";
     logfile << logout.str() << flush;
   }
+
+  RELEASE_LOCK(xml_lock);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -291,6 +301,11 @@ write_xml(ostream &out, TiXmlDocument *doc, ostream &logfile) {
 ////////////////////////////////////////////////////////////////////
 TiXmlDocument *
 read_xml(istream &in, ostream &logfile) {
+  if (!xml_lock_initialized) {
+    INIT_LOCK(xml_lock);
+  }
+  ACQUIRE_LOCK(xml_lock);
+
 #if DO_BINARY_XML
   // binary read.
   size_t buffer_length = 128;
@@ -298,6 +313,7 @@ read_xml(istream &in, ostream &logfile) {
   TiXmlNode *xnode = read_xml_node(in, buffer, buffer_length, logfile);
   delete[] buffer;
   if (xnode == NULL) {
+    RELEASE_LOCK(xml_lock);
     return NULL;
   }
 
@@ -310,6 +326,7 @@ read_xml(istream &in, ostream &logfile) {
   in >> *doc;
   if (in.fail() || in.eof()) {
     delete doc;
+    RELEASE_LOCK(xml_lock);
     return NULL;
   }
 #endif
@@ -321,6 +338,7 @@ read_xml(istream &in, ostream &logfile) {
     logout << "received: " << *doc << "\n";
     logfile << logout.str() << flush;
   }
-    
+
+  RELEASE_LOCK(xml_lock);
   return doc;
 }

+ 26 - 29
direct/src/plugin/p3dInstance.cxx

@@ -1426,7 +1426,6 @@ void P3DInstance::
 handle_notify_request(const string &message) {
   // We look for certain notify events that have particular meaning
   // to this instance.
-  nout << "Got notify: " << message << "\n";
   if (message == "onpythonload") {
     // Once Python is up and running, we can get the actual main
     // object from the Python side, and merge it with our own.
@@ -1459,13 +1458,13 @@ handle_notify_request(const string &message) {
 
   } else if (message == "onwindowopen") {
     // The process told us that it just succesfully opened its
-    // window.  Tear down the splash window.
+    // window.  Hide the splash window.
     _instance_window_opened = true;
     if (_splash_window != NULL) {
-      delete _splash_window;
-      _splash_window = NULL;
+      _splash_window->set_visible(false);
     }
 
+    // Guess we won't be using these images any more.
     for (int i = 0; i < (int)IT_num_image_types; ++i) {
       _image_files[i].cleanup();
     }
@@ -1497,7 +1496,9 @@ handle_notify_request(const string &message) {
     auth_finished_main_thread();
 
   } else if (message == "keyboardfocus") {
-    request_keyboard_focus();
+    if (_splash_window != NULL) {
+      _splash_window->request_keyboard_focus();
+    }
   }
 }
 
@@ -1597,19 +1598,6 @@ handle_script_request(const string &operation, P3D_object *object,
   }
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: P3DInstance::request_keyboard_focus
-//       Access: Private
-//  Description: The Panda window is asking us to manage keyboard
-//               focus in proxy for it.  This is used on Vista, where
-//               the Panda window may be disallowed from directly
-//               assigning itself keyboard focus.
-////////////////////////////////////////////////////////////////////
-void P3DInstance::
-request_keyboard_focus() {
-  nout << "request_keyboard_focus\n";
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DInstance::make_splash_window
 //       Access: Private
@@ -1618,8 +1606,24 @@ request_keyboard_focus() {
 ////////////////////////////////////////////////////////////////////
 void P3DInstance::
 make_splash_window() {
-  if (_splash_window != NULL || _instance_window_opened) {
-    // Already got one, or we're already showing the real instance.
+  // Should we make the splash window visible?
+  bool make_visible = true;
+  if (_instance_window_opened) {
+    // Not once we've opened the main window.
+    make_visible = false;
+  }
+
+  if (_wparams.get_window_type() != P3D_WT_embedded && 
+      !_stuff_to_download && _auto_start && _p3d_trusted) {
+    // If it's a toplevel or fullscreen window, then we don't want a
+    // splash window unless we have stuff to download, or a button to
+    // display.
+    make_visible = false;
+  }
+
+  if (_splash_window != NULL) {
+    // Already got one.
+    _splash_window->set_visible(make_visible);
     return;
   }
   if (!_got_wparams) {
@@ -1630,18 +1634,11 @@ make_splash_window() {
     // We're hidden, and so is the splash window.
     return;
   }
-  if (_wparams.get_window_type() != P3D_WT_embedded && 
-      !_stuff_to_download && _auto_start && _p3d_trusted) {
-    // If it's a toplevel or fullscreen window, then we don't want a
-    // splash window unless we have stuff to download, or a button to
-    // display.
-    return;
-  }
 
-  _splash_window = new SplashWindowType(this);
+  _splash_window = new SplashWindowType(this, make_visible);
   _splash_window->set_wparams(_wparams);
   _splash_window->set_install_label(_install_label);
-
+    
   P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
 
   // Go get the required images.

+ 0 - 1
direct/src/plugin/p3dInstance.h

@@ -162,7 +162,6 @@ private:
   void handle_script_request(const string &operation, P3D_object *object, 
                              const string &property_name, P3D_object *value,
                              bool needs_response, int unique_id);
-  void request_keyboard_focus();
 
   void make_splash_window();
   void set_background_image(ImageType image_type);

+ 7 - 4
direct/src/plugin/p3dOsxSplashWindow.cxx

@@ -29,8 +29,8 @@
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 P3DOsxSplashWindow::
-P3DOsxSplashWindow(P3DInstance *inst) : 
-  P3DSplashWindow(inst)
+P3DOsxSplashWindow(P3DInstance *inst, bool make_visible) : 
+  P3DSplashWindow(inst, make_visible)
 {
   _install_progress = 0;
   _got_wparams = false;
@@ -226,10 +226,13 @@ handle_event(P3D_event_data event) {
 ////////////////////////////////////////////////////////////////////
 void P3DOsxSplashWindow::
 refresh() {
+  if (!_visible) {
+    return;
+  }
   if (_toplevel_window != NULL) {
     Rect r = { 0, 0, _win_height, _win_width }; 
     InvalWindowRect(_toplevel_window, &r);
-
+    
   } else {
     _inst->request_refresh();
   }
@@ -242,7 +245,7 @@ refresh() {
 ////////////////////////////////////////////////////////////////////
 void P3DOsxSplashWindow::
 paint_window() {
-  if (!_got_wparams) {
+  if (!_visible) {
     return;
   }
 

+ 1 - 1
direct/src/plugin/p3dOsxSplashWindow.h

@@ -30,7 +30,7 @@
 ////////////////////////////////////////////////////////////////////
 class P3DOsxSplashWindow : public P3DSplashWindow {
 public:
-  P3DOsxSplashWindow(P3DInstance *inst);
+  P3DOsxSplashWindow(P3DInstance *inst, bool make_visible);
   virtual ~P3DOsxSplashWindow();
 
   virtual void set_wparams(const P3DWindowParams &wparams);

+ 32 - 3
direct/src/plugin/p3dPythonRun.cxx

@@ -403,8 +403,6 @@ run_python() {
 ////////////////////////////////////////////////////////////////////
 void P3DPythonRun::
 request_keyboard_focus(P3DCInstance *inst) {
-  cerr << "requesting keyboard focus\n";
-
   TiXmlDocument doc;
   TiXmlElement *xrequest = new TiXmlElement("request");
   xrequest->SetAttribute("instance_id", inst->get_instance_id());
@@ -509,6 +507,18 @@ handle_command(TiXmlDocument *doc) {
           setup_window(instance_id, xwparams);
         }
 
+      } else if (strcmp(cmd, "windows_message") == 0) {
+        assert(!needs_response);
+        // This is a special message that we use to proxy keyboard
+        // events from the parent process down into Panda, a necessary
+        // hack on Vista.
+        int instance_id = 0, msg = 0, wparam = 0, lparam = 0;
+        xcommand->Attribute("instance_id", &instance_id);
+        xcommand->Attribute("msg", &msg);
+        xcommand->Attribute("wparam", &wparam);
+        xcommand->Attribute("lparam", &lparam);
+        send_windows_message(instance_id, msg, wparam, lparam);
+
       } else if (strcmp(cmd, "exit") == 0) {
         assert(!needs_response);
         terminate_session();
@@ -1362,6 +1372,25 @@ setup_window(P3DCInstance *inst, TiXmlElement *xwparams) {
   Py_XDECREF(result);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DPythonRun::send_windows_message
+//       Access: Public
+//  Description: This is used to deliver a windows keyboard message to
+//               the Panda process from the parent process, a
+//               necessary hack on Vista.
+////////////////////////////////////////////////////////////////////
+void P3DPythonRun::
+send_windows_message(int id, unsigned int msg, int wparam, int lparam) {
+  Instances::iterator ii = _instances.find(id);
+  if (ii == _instances.end()) {
+    return;
+  }
+
+  P3DCInstance *inst = (*ii).second;
+  if (inst->_parent_window_handle != (WindowHandle *)NULL) {
+    inst->_parent_window_handle->send_windows_message(msg, wparam, lparam);
+  }
+}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DPythonRun::terminate_session
@@ -1719,7 +1748,7 @@ rt_thread_run() {
 P3DPythonRun::P3DWindowHandle::
 P3DWindowHandle(P3DPythonRun *p3dpython, P3DCInstance *inst,
                 const WindowHandle &copy) :
-  WindowHandle(copy.get_os_handle()),
+  WindowHandle(copy),
   _p3dpython(p3dpython),
   _inst(inst)
 {

+ 6 - 4
direct/src/plugin/p3dPythonRun.h

@@ -100,6 +100,8 @@ private:
   void set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams);
   void setup_window(int id, TiXmlElement *xwparams);
   void setup_window(P3DCInstance *inst, TiXmlElement *xwparams);
+
+  void send_windows_message(int id, unsigned int msg, int wparam, int lparam);
   
   void terminate_session();
 
@@ -108,7 +110,7 @@ private:
   PyObject *xml_to_pyobj(TiXmlElement *xvalue);
 
 private:
-  // This subclass of P3DWindowHandle is associated with the parent
+  // This subclass of WindowHandle is associated with the parent
   // window we are given by the parent process.  We use it to add
   // hooks for communicating with the parent window, for instance to
   // ask for the parent window to manage keyboard focus when
@@ -118,13 +120,13 @@ private:
     P3DWindowHandle(P3DPythonRun *p3dpython, P3DCInstance *inst,
                     const WindowHandle &copy);
 
+  protected:
+    virtual void request_keyboard_focus(WindowHandle *child);
+
   private:
     P3DPythonRun *_p3dpython;
     P3DCInstance *_inst;
 
-  protected:
-    virtual void request_keyboard_focus(WindowHandle *child);
-
   public:
     static TypeHandle get_class_type() {
       return _type_handle;

+ 23 - 0
direct/src/plugin/p3dSession.cxx

@@ -583,6 +583,29 @@ p3dobj_to_xml(P3D_object *obj) {
   return xvalue;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSession::send_windows_message
+//       Access: Public
+//  Description: This is called by the splash window to deliver a
+//               windows keyboard message to the Panda process.  It
+//               will be called in a sub-thread, but that's OK, since
+//               write_xml() supports locking.
+////////////////////////////////////////////////////////////////////
+void P3DSession::
+send_windows_message(P3DInstance *inst, unsigned int msg, int wparam, int lparam) {
+  if (_p3dpython_started) {
+    TiXmlDocument doc;
+    TiXmlElement *xcommand = new TiXmlElement("command");
+    xcommand->SetAttribute("cmd", "windows_message");
+    xcommand->SetAttribute("instance_id", inst->get_instance_id());
+    xcommand->SetAttribute("msg", msg);
+    xcommand->SetAttribute("wparam", wparam);
+    xcommand->SetAttribute("lparam", lparam);
+    doc.LinkEndChild(xcommand);
+    write_xml(_pipe_write, &doc, nout);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DSession::signal_request_ready
 //       Access: Public

+ 2 - 0
direct/src/plugin/p3dSession.h

@@ -54,6 +54,8 @@ public:
   TiXmlDocument *command_and_response(TiXmlDocument *command);
   P3D_object *xml_to_p3dobj(const TiXmlElement *xvalue);
   TiXmlElement *p3dobj_to_xml(P3D_object *obj);
+  void send_windows_message(P3DInstance *inst, unsigned int msg, 
+                            int wparam, int lparam);
 
   void signal_request_ready(P3DInstance *inst);
 

+ 28 - 1
direct/src/plugin/p3dSplashWindow.cxx

@@ -49,11 +49,12 @@ METHODDEF(void) my_error_exit (j_common_ptr cinfo) {
 //               them both into this class for reference.
 ////////////////////////////////////////////////////////////////////
 P3DSplashWindow::
-P3DSplashWindow(P3DInstance *inst) : 
+P3DSplashWindow(P3DInstance *inst, bool make_visible) : 
   _inst(inst),
   _fparams(inst->get_fparams()),
   _wparams(inst->get_wparams())
 {
+  _visible = make_visible;
   _button_width = 0;
   _button_height = 0;
   _button_x = 0;
@@ -87,6 +88,20 @@ set_wparams(const P3DWindowParams &wparams) {
   _wparams = wparams;
   _win_width = _wparams.get_win_width();
   _win_height = _wparams.get_win_height();
+  _visible = true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSplashWindow::set_visible
+//       Access: Public, Virtual
+//  Description: Makes the splash window visible or invisible, so as
+//               not to compete with the embedded Panda window in the
+//               same space.
+////////////////////////////////////////////////////////////////////
+void P3DSplashWindow::
+set_visible(bool visible) {
+  nout << "P3DSplashWindow::set_visible(" << visible << ")\n";
+  _visible = visible;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -152,6 +167,18 @@ set_button_active(bool flag) {
   set_mouse_data(_mouse_x, _mouse_y, _mouse_down);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSplashWindow::request_keyboard_focus
+//       Access: Private
+//  Description: The Panda window is asking us to manage keyboard
+//               focus in proxy for it.  This is used on Vista, where
+//               the Panda window may be disallowed from directly
+//               assigning itself keyboard focus.
+////////////////////////////////////////////////////////////////////
+void P3DSplashWindow::
+request_keyboard_focus() {
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DSplashWindow::read_image_data
 //       Access: Protected

+ 5 - 1
direct/src/plugin/p3dSplashWindow.h

@@ -33,7 +33,7 @@ class P3DInstance;
 ////////////////////////////////////////////////////////////////////
 class P3DSplashWindow {
 public:
-  P3DSplashWindow(P3DInstance *inst);
+  P3DSplashWindow(P3DInstance *inst, bool make_visible);
   virtual ~P3DSplashWindow();
 
   inline const P3DFileParams &get_fparams() const;
@@ -41,6 +41,8 @@ public:
   virtual void set_wparams(const P3DWindowParams &wparams);
   inline const P3DWindowParams &get_wparams() const;
 
+  virtual void set_visible(bool visible);
+
   enum ImagePlacement {
     IP_background,
     IP_button_ready,
@@ -57,6 +59,7 @@ public:
   virtual bool handle_event(P3D_event_data event);
 
   virtual void set_button_active(bool flag);
+  virtual void request_keyboard_focus();
 
 protected:
   // This ImageData base class provides minimal functionality for
@@ -96,6 +99,7 @@ protected:
   P3DFileParams _fparams;
   P3DWindowParams _wparams;
   int _win_width, _win_height;
+  bool _visible;
 
   // The region of the window for accepting button clicks.
   int _button_width, _button_height;

+ 102 - 3
direct/src/plugin/p3dWinSplashWindow.cxx

@@ -16,6 +16,10 @@
 
 #ifdef _WIN32
 
+#ifndef WM_MOUSEWHEEL
+#define WM_MOUSEWHEEL 0x20a
+#endif
+
 bool P3DWinSplashWindow::_registered_window_class = false;
 
 ////////////////////////////////////////////////////////////////////
@@ -24,8 +28,8 @@ bool P3DWinSplashWindow::_registered_window_class = false;
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 P3DWinSplashWindow::
-P3DWinSplashWindow(P3DInstance *inst) : 
-  P3DSplashWindow(inst)
+P3DWinSplashWindow(P3DInstance *inst, bool make_visible) : 
+  P3DSplashWindow(inst, make_visible)
 {
   _thread = NULL;
   _thread_id = 0;
@@ -36,6 +40,9 @@ P3DWinSplashWindow(P3DInstance *inst) :
 
   _drawn_bstate = BS_hidden;
   _drawn_progress = 0.0;
+  _focus_seq = 0;
+
+  _request_focus_tick = 0;
 
   INIT_LOCK(_install_lock);
 }
@@ -68,6 +75,24 @@ set_wparams(const P3DWindowParams &wparams) {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DWinSplashWindow::set_visible
+//       Access: Public, Virtual
+//  Description: Makes the splash window visible or invisible, so as
+//               not to compete with the embedded Panda window in the
+//               same space.
+////////////////////////////////////////////////////////////////////
+void P3DWinSplashWindow::
+set_visible(bool visible) {
+  P3DSplashWindow::set_visible(visible);
+
+  if (_visible) {
+    ShowWindow(_hwnd, SW_SHOWNORMAL);
+  } else {
+    ShowWindow(_hwnd, SW_HIDE);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DWinSplashWindow::set_image_filename
 //       Access: Public, Virtual
@@ -166,6 +191,30 @@ set_install_progress(double install_progress) {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DWinSplashWindow::request_keyboard_focus
+//       Access: Private
+//  Description: The Panda window is asking us to manage keyboard
+//               focus in proxy for it.  This is used on Vista, where
+//               the Panda window may be disallowed from directly
+//               assigning itself keyboard focus.
+////////////////////////////////////////////////////////////////////
+void P3DWinSplashWindow::
+request_keyboard_focus() {
+  // Store the time at which we last requested focus.
+  _request_focus_tick = GetTickCount();
+
+  // Increment the _focus_seq to tell the thread to call SetFocus().
+  ACQUIRE_LOCK(_install_lock);
+  ++_focus_seq;
+  RELEASE_LOCK(_install_lock);
+  
+  if (_thread_id != 0) {
+    // Post a silly message to spin the message loop.
+    PostThreadMessage(_thread_id, WM_USER, 0, 0);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DWinSplashWindow::register_window_class
 //       Access: Public, Static
@@ -277,6 +326,7 @@ void P3DWinSplashWindow::
 thread_run() {
   make_window();
 
+  int last_focus_seq = 0;
   MSG msg;
   int retval;
   retval = GetMessage(&msg, NULL, 0, 0);
@@ -312,6 +362,14 @@ thread_run() {
       _drawn_bstate = _bstate;
       InvalidateRect(_hwnd, NULL, TRUE);
     }
+
+    if (_focus_seq != last_focus_seq) {
+      last_focus_seq = _focus_seq;
+      if (SetFocus(_hwnd) == NULL && GetLastError() != 0) {
+        nout << "SetFocus(" << _hwnd << ") failed: " << GetLastError() << "\n";
+      }
+    }
+
     RELEASE_LOCK(_install_lock);
 
     retval = GetMessage(&msg, NULL, 0, 0);
@@ -396,7 +454,13 @@ make_window() {
     }
   }
   SetWindowLongPtr(_hwnd, GWLP_USERDATA, (LONG_PTR)this);
-  ShowWindow(_hwnd, SW_SHOWNORMAL);
+  nout << "Created splash window " << _hwnd << "\n";
+
+  if (_visible) {
+    ShowWindow(_hwnd, SW_SHOWNORMAL);
+  } else {
+    ShowWindow(_hwnd, SW_HIDE);
+  }
 
   _blue_brush = CreateSolidBrush(RGB(108, 165, 224));
 }
@@ -802,6 +866,41 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
     set_mouse_data(_mouse_x, _mouse_y, false);
     ReleaseCapture();
     break;
+
+  case WM_KILLFOCUS:
+    // Someone on the desktop is playing games with us.  It keeps
+    // wanting to grab the keyboard focus back immediately after we
+    // successfully call SetFocus().  Well, we really mean it, darn it
+    // all.  If we got a WM_KILLFOCUS within a few milliseconds of
+    // calling SetFocus(), well, call SetFocus() again, until it
+    // sticks.
+    {
+      int elapsed = GetTickCount() - _request_focus_tick;
+      if (elapsed < 200) {
+        if (SetFocus(_hwnd) == NULL && GetLastError() != 0) {
+          nout << "Secondary SetFocus failed: " << GetLastError() << "\n";
+        }
+      }
+    }
+    break;
+
+    // Keyboard events that are to be proxied to the Panda window.
+  case WM_MOUSEWHEEL:
+  case WM_IME_SETCONTEXT:
+  case WM_IME_NOTIFY:
+  case WM_IME_STARTCOMPOSITION:
+  case WM_IME_ENDCOMPOSITION:
+  case WM_IME_COMPOSITION:
+  case WM_CHAR:
+  case WM_SYSKEYDOWN:
+  case WM_SYSCOMMAND:
+  case WM_KEYDOWN: 
+  case WM_SYSKEYUP:
+  case WM_KEYUP:
+    if (_inst->get_session() != NULL) {
+      _inst->get_session()->send_windows_message(_inst, msg, wparam, lparam);
+    }
+    break;
   };
 
   return DefWindowProc(hwnd, msg, wparam, lparam);

+ 7 - 1
direct/src/plugin/p3dWinSplashWindow.h

@@ -31,14 +31,17 @@
 ////////////////////////////////////////////////////////////////////
 class P3DWinSplashWindow : public P3DSplashWindow {
 public:
-  P3DWinSplashWindow(P3DInstance *inst);
+  P3DWinSplashWindow(P3DInstance *inst, bool make_visible);
   virtual ~P3DWinSplashWindow();
 
   virtual void set_wparams(const P3DWindowParams &wparams);
+  virtual void set_visible(bool visible);
+
   virtual void set_image_filename(const string &image_filename,
                                   ImagePlacement image_placement);
   virtual void set_install_label(const string &install_label);
   virtual void set_install_progress(double install_progress);
+  virtual void request_keyboard_focus();
 
   static void register_window_class();
   static void unregister_window_class();
@@ -92,6 +95,9 @@ private:
   ButtonState _drawn_bstate;
   string _drawn_label;
   double _drawn_progress;
+  int _focus_seq;
+
+  int _request_focus_tick;
 
   bool _thread_continue;
   bool _thread_running;

+ 1 - 1
direct/src/plugin/p3dX11SplashWindow.h

@@ -34,7 +34,7 @@
 ////////////////////////////////////////////////////////////////////
 class P3DX11SplashWindow : public P3DSplashWindow {
 public:
-  P3DX11SplashWindow(P3DInstance *inst);
+  P3DX11SplashWindow(P3DInstance *inst, bool make_visible);
   virtual ~P3DX11SplashWindow();
 
   virtual void set_wparams(const P3DWindowParams &wparams);