Browse Source

receive_windows_message

David Rose 16 years ago
parent
commit
8061092d8e

+ 8 - 7
panda/src/display/windowHandle.cxx

@@ -27,18 +27,18 @@ WindowHandle::
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: WindowHandle::send_keyboard_event
+//     Function: WindowHandle::send_windows_message
 //       Access: Published
 //       Access: Published
 //  Description: Call this method on a parent WindowHandle to deliver
 //  Description: Call this method on a parent WindowHandle to deliver
-//               a button event to the current child window, if any.
+//               a Windows message to the current child window, if any.
 //               This is used in the web plugin system to deliver
 //               This is used in the web plugin system to deliver
 //               button events detected directly by the browser system
 //               button events detected directly by the browser system
-//               into Panda.
+//               into Panda, which is particularly necessary on Vista.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void WindowHandle::
 void WindowHandle::
-send_keyboard_event(const ButtonEvent &event) {
+send_windows_message(unsigned int msg, int wparam, int lparam) {
   if (_keyboard_window != NULL) {
   if (_keyboard_window != NULL) {
-    _keyboard_window->receive_keyboard_event(event);
+    _keyboard_window->receive_windows_message(msg, wparam, lparam);
   }
   }
 }
 }
 
 
@@ -106,13 +106,14 @@ request_keyboard_focus(WindowHandle *child) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: WindowHandle::receive_keyboard_event
+//     Function: WindowHandle::receive_windows_message
 //       Access: Public, Virtual
 //       Access: Public, Virtual
 //  Description: Called on a child handle to deliver a keyboard button
 //  Description: Called on a child handle to deliver a keyboard button
 //               event generated in the parent window.
 //               event generated in the parent window.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void WindowHandle::
 void WindowHandle::
-receive_keyboard_event(const ButtonEvent &event) {
+receive_windows_message(unsigned int msg, int wparam, int lparam) {
+  nout << "receive_windows_message(" << msg << ", " << wparam << ", " << lparam << ")\n";
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 4
panda/src/display/windowHandle.h

@@ -20,8 +20,6 @@
 #include "typedReferenceCount.h"
 #include "typedReferenceCount.h"
 #include "pointerTo.h"
 #include "pointerTo.h"
 
 
-class ButtonEvent;
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : WindowHandle
 //       Class : WindowHandle
 // Description : This object represents a window on the desktop, not
 // Description : This object represents a window on the desktop, not
@@ -50,7 +48,7 @@ PUBLISHED:
   INLINE OSHandle *get_os_handle() const;
   INLINE OSHandle *get_os_handle() const;
   INLINE void set_os_handle(OSHandle *os_handle);
   INLINE void set_os_handle(OSHandle *os_handle);
 
 
-  void send_keyboard_event(const ButtonEvent &event);
+  void send_windows_message(unsigned int msg, int wparam, int lparam);
 
 
   size_t get_int_handle() const;
   size_t get_int_handle() const;
 
 
@@ -62,7 +60,7 @@ public:
   virtual void detach_child(WindowHandle *child);
   virtual void detach_child(WindowHandle *child);
 
 
   virtual void request_keyboard_focus(WindowHandle *child);
   virtual void request_keyboard_focus(WindowHandle *child);
-  virtual void receive_keyboard_event(const ButtonEvent &event);
+  virtual void receive_windows_message(unsigned int msg, int wparam, int lparam);
 
 
 PUBLISHED:
 PUBLISHED:
   // This internal pointer within WindowHandle stores the actual
   // This internal pointer within WindowHandle stores the actual

+ 113 - 11
panda/src/windisplay/winGraphicsWindow.cxx

@@ -33,6 +33,7 @@
 
 
 
 
 TypeHandle WinGraphicsWindow::_type_handle;
 TypeHandle WinGraphicsWindow::_type_handle;
+TypeHandle WinGraphicsWindow::WinWindowHandle::_type_handle;
 
 
 WinGraphicsWindow::WindowHandles WinGraphicsWindow::_window_handles;
 WinGraphicsWindow::WindowHandles WinGraphicsWindow::_window_handles;
 WinGraphicsWindow *WinGraphicsWindow::_creating_window = NULL;
 WinGraphicsWindow *WinGraphicsWindow::_creating_window = NULL;
@@ -117,6 +118,9 @@ WinGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 WinGraphicsWindow::
 WinGraphicsWindow::
 ~WinGraphicsWindow() {
 ~WinGraphicsWindow() {
+  if (_window_handle != (WindowHandle *)NULL) {
+    DCAST(WinWindowHandle, _window_handle)->clear_window();
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -437,6 +441,20 @@ open_window() {
     Rid.hwndTarget = _hWnd;
     Rid.hwndTarget = _hWnd;
     pRegisterRawInputDevices(&Rid, 1, sizeof (Rid));
     pRegisterRawInputDevices(&Rid, 1, sizeof (Rid));
   }
   }
+
+  // Create a WindowHandle for ourselves
+  _window_handle = NativeWindowHandle::make_win(_hWnd);
+
+  // Actually, we want a WinWindowHandle.
+  _window_handle = new WinWindowHandle(this, *_window_handle);
+
+  // And tell our parent window that we're now its child.
+  if (_parent_window_handle != (WindowHandle *)NULL) {
+    _parent_window_handle->attach_child(_window_handle);
+  }
+
+  // set us as the focus window for keyboard input
+  set_focus();
   
   
   return true;
   return true;
 }
 }
@@ -741,6 +759,9 @@ open_fullscreen_window()
     _properties.set_size(640, 480);
     _properties.set_size(640, 480);
   }
   }
 
 
+  // No parent window for a fullscreen window.
+  _parent_window_handle = NULL;
+
   HWND hDesktopWindow = GetDesktopWindow();
   HWND hDesktopWindow = GetDesktopWindow();
   HDC scrnDC = GetDC(hDesktopWindow);
   HDC scrnDC = GetDC(hDesktopWindow);
   DWORD cur_bitdepth = GetDeviceCaps(scrnDC, BITSPIXEL);
   DWORD cur_bitdepth = GetDeviceCaps(scrnDC, BITSPIXEL);
@@ -888,6 +909,7 @@ open_regular_window() {
       }
       }
     }
     }
   }
   }
+  _parent_window_handle = window_handle;
 
 
   if (!_hparent) {
   if (!_hparent) {
     _hWnd = CreateWindow(wclass._name.c_str(), title.c_str(), window_style, 
     _hWnd = CreateWindow(wclass._name.c_str(), title.c_str(), window_style, 
@@ -905,13 +927,11 @@ open_regular_window() {
       y_origin = _properties.get_y_origin();
       y_origin = _properties.get_y_origin();
     }
     }
 
 
-    nout << "Creating embedded window\n";
     _hWnd = CreateWindow(wclass._name.c_str(), title.c_str(), 
     _hWnd = CreateWindow(wclass._name.c_str(), title.c_str(), 
                          WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS ,
                          WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS ,
                          x_origin,y_origin,
                          x_origin,y_origin,
                          x_size, y_size,
                          x_size, y_size,
                          _hparent, NULL, hinstance, 0);
                          _hparent, NULL, hinstance, 0);
-    nout << "Done creating embedded window, _hwnd = " << _hWnd << "\n";
     
     
     if (_hWnd) {
     if (_hWnd) {
       // join our keyboard state with the parents
       // join our keyboard state with the parents
@@ -920,9 +940,6 @@ open_regular_window() {
       // It causes problems with the browser plugin--it deadlocks when
       // It causes problems with the browser plugin--it deadlocks when
       // the parent process is waiting on the child process.
       // the parent process is waiting on the child process.
       //AttachThreadInput(GetWindowThreadProcessId(_hparent,NULL), GetCurrentThreadId(),TRUE);
       //AttachThreadInput(GetWindowThreadProcessId(_hparent,NULL), GetCurrentThreadId(),TRUE);
-
-      // set us as the focus window for keyboard input
-      SetFocus(_hWnd);
       
       
       WindowProperties properties;
       WindowProperties properties;
       properties.set_foreground(true);
       properties.set_foreground(true);
@@ -1038,8 +1055,52 @@ track_mouse_leaving(HWND hwnd) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: WinGraphicsWindow::window_proc
+//     Function: WinGraphicsWindow::set_focus
 //       Access: Private
 //       Access: Private
+//  Description: Attempts to set this window as the "focus" window, so
+//               that keyboard events come here.
+////////////////////////////////////////////////////////////////////
+void WinGraphicsWindow::
+set_focus() {
+  if (SetFocus(_hWnd) == NULL && GetLastError() != 0) {
+    // If the SetFocus() request failed, maybe we're running in the
+    // plugin environment on Vista, with UAC enabled.  In this case,
+    // we're not allowed to assign focus to the Panda window for some
+    // stupid reason.  So instead, we have to ask the parent window
+    // (in the browser process) to proxy our keyboard events for us.
+    if (_parent_window_handle != NULL && _window_handle != NULL) {
+      _parent_window_handle->request_keyboard_focus(_window_handle);
+    } else {
+      // Otherwise, something is wrong.
+      windisplay_cat.error()
+        << "SetFocus failed: " << GetLastError() << "\n";
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WinGraphicsWindow::receive_windows_message
+//       Access: Public
+//  Description: This is called to receive a keyboard event generated
+//               by proxy by another window in a parent process.  This
+//               hacky system is used in the web plugin system to
+//               allow the Panda window to receive keyboard events on
+//               Vista, which doesn't allow the Panda window to set
+//               keyboard focus to itself.
+////////////////////////////////////////////////////////////////////
+void WinGraphicsWindow::
+receive_windows_message(unsigned int msg, int wparam, int lparam) {
+  // Well, we'll just deliver this directly to window_proc(),
+  // supplying our own window handle.  For the most part, we don't
+  // care about the window handle anyway, but this might become an
+  // issue for the IME.  TODO: investigate IME issues.
+
+  window_proc(_hWnd, msg, wparam, lparam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WinGraphicsWindow::window_proc
+//       Access: Public, Virtual
 //  Description: This is the nonstatic window_proc function.  It is
 //  Description: This is the nonstatic window_proc function.  It is
 //               called to handle window events for this particular
 //               called to handle window events for this particular
 //               window.
 //               window.
@@ -1226,7 +1287,9 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
     SetCapture(hwnd);
     SetCapture(hwnd);
     _input_devices[0].set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
     _input_devices[0].set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
     _input_devices[0].button_down(MouseButton::button(0), get_message_time());
     _input_devices[0].button_down(MouseButton::button(0), get_message_time());
-    SetFocus(hwnd); // [gjeon] to get the keyboard event
+
+    // A button-click in the window means to grab the keyboard focus.
+    set_focus();
     break;
     break;
         
         
   case WM_MBUTTONDOWN:
   case WM_MBUTTONDOWN:
@@ -1236,7 +1299,8 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
     SetCapture(hwnd);
     SetCapture(hwnd);
     _input_devices[0].set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
     _input_devices[0].set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
     _input_devices[0].button_down(MouseButton::button(1), get_message_time());
     _input_devices[0].button_down(MouseButton::button(1), get_message_time());
-    SetFocus(hwnd); // [gjeon] to get the keyboard event
+    // A button-click in the window means to grab the keyboard focus.
+    set_focus();
     break;
     break;
 
 
   case WM_RBUTTONDOWN:
   case WM_RBUTTONDOWN:
@@ -1246,7 +1310,8 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
     SetCapture(hwnd);
     SetCapture(hwnd);
     _input_devices[0].set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
     _input_devices[0].set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
     _input_devices[0].button_down(MouseButton::button(2), get_message_time());
     _input_devices[0].button_down(MouseButton::button(2), get_message_time());
-    SetFocus(hwnd); // [gjeon] to get the keyboard event
+    // A button-click in the window means to grab the keyboard focus.
+    set_focus();
     break;
     break;
 
 
   case WM_XBUTTONDOWN:
   case WM_XBUTTONDOWN:
@@ -2469,6 +2534,45 @@ register_window_class(const WindowProperties &props) {
   return wclass;
   return wclass;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: WinGraphicsWindow::WinWindowHandle::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+WinGraphicsWindow::WinWindowHandle::
+WinWindowHandle(WinGraphicsWindow *window, const WindowHandle &copy) :
+  WindowHandle(copy),
+  _window(window)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WinGraphicsWindow::WinWindowHandle::clear_window
+//       Access: Public
+//  Description: Should be called by the WinGraphicsWindow's
+//               destructor, so that we don't end up with a floating
+//               pointer should this object persist beyond the
+//               lifespan of its window.
+////////////////////////////////////////////////////////////////////
+void WinGraphicsWindow::WinWindowHandle::
+clear_window() {
+  _window = NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WinGraphicsWindow::WinWindowHandle::receive_windows_message
+//       Access: Public, Virtual
+//  Description: Called on a child handle to deliver a keyboard button
+//               event generated in the parent window.
+////////////////////////////////////////////////////////////////////
+void WinGraphicsWindow::WinWindowHandle::
+receive_windows_message(unsigned int msg, int wparam, int lparam) {
+  if (_window != NULL) {
+    _window->receive_windows_message(msg, wparam, lparam);
+  }
+}
+
+
 // pops up MsgBox w/system error msg
 // pops up MsgBox w/system error msg
 void PrintErrorMessage(DWORD msgID) {
 void PrintErrorMessage(DWORD msgID) {
   LPTSTR pMessageBuffer;
   LPTSTR pMessageBuffer;
@@ -2535,5 +2639,3 @@ void get_client_rect_screen(HWND hwnd, RECT *view_rect) {
   view_rect->right = lr.x;
   view_rect->right = lr.x;
   view_rect->bottom = lr.y;
   view_rect->bottom = lr.y;
 }
 }
-
-

+ 39 - 0
panda/src/windisplay/winGraphicsWindow.h

@@ -62,6 +62,7 @@ public:
 
 
   virtual void process_events();
   virtual void process_events();
   virtual void set_properties_now(WindowProperties &properties);
   virtual void set_properties_now(WindowProperties &properties);
+  void receive_windows_message(unsigned int msg, int wparam, int lparam);
   virtual LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
   virtual LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
   static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
   static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
   virtual bool handle_mouse_motion(int x, int y);
   virtual bool handle_mouse_motion(int x, int y);
@@ -97,6 +98,8 @@ private:
   void handle_raw_input(HRAWINPUT hraw);
   void handle_raw_input(HRAWINPUT hraw);
   void track_mouse_leaving(HWND hwnd);
   void track_mouse_leaving(HWND hwnd);
 
 
+  void set_focus();
+
   static void process_1_event();
   static void process_1_event();
 
 
   INLINE void handle_keypress(ButtonHandle key, int x, int y, double time);
   INLINE void handle_keypress(ButtonHandle key, int x, int y, double time);
@@ -213,6 +216,41 @@ private:
   static int _window_class_index;
   static int _window_class_index;
 
 
   static const WindowClass &register_window_class(const WindowProperties &props);
   static const WindowClass &register_window_class(const WindowProperties &props);
+private:
+  // This subclass of WindowHandle is stored in _window_handle to
+  // represent this particular window.  We use it to add hooks for
+  // communicating with the parent window, in particular to receive
+  // keyboard events from the parent window when necessary.
+  class WinWindowHandle : public WindowHandle {
+  public:
+    WinWindowHandle(WinGraphicsWindow *window,
+                    const WindowHandle &copy);
+    void clear_window();
+
+  protected:
+    virtual void receive_windows_message(unsigned int msg, int wparam, int lparam);
+
+  private:
+    // Not reference-counted, to avoid a circular reference count.
+    WinGraphicsWindow *_window;
+
+  public:
+    static TypeHandle get_class_type() {
+      return _type_handle;
+    }
+    static void init_type() {
+      WindowHandle::init_type();
+      register_type(_type_handle, "WinWindowHandle",
+                    WindowHandle::get_class_type());
+    }
+    virtual TypeHandle get_type() const {
+      return get_class_type();
+    }
+    virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+    
+  private:
+    static TypeHandle _type_handle;
+  };
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
@@ -222,6 +260,7 @@ public:
     GraphicsWindow::init_type();
     GraphicsWindow::init_type();
     register_type(_type_handle, "WinGraphicsWindow",
     register_type(_type_handle, "WinGraphicsWindow",
                   GraphicsWindow::get_class_type());
                   GraphicsWindow::get_class_type());
+    WinWindowHandle::init_type();
   }
   }
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();