receive_windows_message

This commit is contained in:
David Rose 2009-10-02 20:22:47 +00:00
parent c4f35f6e4c
commit 8061092d8e
4 changed files with 162 additions and 22 deletions

View File

@ -27,18 +27,18 @@ WindowHandle::
}
////////////////////////////////////////////////////////////////////
// Function: WindowHandle::send_keyboard_event
// Function: WindowHandle::send_windows_message
// Access: Published
// 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
// button events detected directly by the browser system
// into Panda.
// into Panda, which is particularly necessary on Vista.
////////////////////////////////////////////////////////////////////
void WindowHandle::
send_keyboard_event(const ButtonEvent &event) {
send_windows_message(unsigned int msg, int wparam, int lparam) {
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
// Description: Called on a child handle to deliver a keyboard button
// event generated in the parent window.
////////////////////////////////////////////////////////////////////
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";
}
////////////////////////////////////////////////////////////////////

View File

@ -20,8 +20,6 @@
#include "typedReferenceCount.h"
#include "pointerTo.h"
class ButtonEvent;
////////////////////////////////////////////////////////////////////
// Class : WindowHandle
// Description : This object represents a window on the desktop, not
@ -50,7 +48,7 @@ PUBLISHED:
INLINE OSHandle *get_os_handle() const;
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;
@ -62,7 +60,7 @@ public:
virtual void detach_child(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:
// This internal pointer within WindowHandle stores the actual

View File

@ -33,6 +33,7 @@
TypeHandle WinGraphicsWindow::_type_handle;
TypeHandle WinGraphicsWindow::WinWindowHandle::_type_handle;
WinGraphicsWindow::WindowHandles WinGraphicsWindow::_window_handles;
WinGraphicsWindow *WinGraphicsWindow::_creating_window = NULL;
@ -117,6 +118,9 @@ WinGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
////////////////////////////////////////////////////////////////////
WinGraphicsWindow::
~WinGraphicsWindow() {
if (_window_handle != (WindowHandle *)NULL) {
DCAST(WinWindowHandle, _window_handle)->clear_window();
}
}
////////////////////////////////////////////////////////////////////
@ -437,6 +441,20 @@ open_window() {
Rid.hwndTarget = _hWnd;
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;
}
@ -741,6 +759,9 @@ open_fullscreen_window()
_properties.set_size(640, 480);
}
// No parent window for a fullscreen window.
_parent_window_handle = NULL;
HWND hDesktopWindow = GetDesktopWindow();
HDC scrnDC = GetDC(hDesktopWindow);
DWORD cur_bitdepth = GetDeviceCaps(scrnDC, BITSPIXEL);
@ -888,6 +909,7 @@ open_regular_window() {
}
}
}
_parent_window_handle = window_handle;
if (!_hparent) {
_hWnd = CreateWindow(wclass._name.c_str(), title.c_str(), window_style,
@ -905,13 +927,11 @@ open_regular_window() {
y_origin = _properties.get_y_origin();
}
nout << "Creating embedded window\n";
_hWnd = CreateWindow(wclass._name.c_str(), title.c_str(),
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS ,
x_origin,y_origin,
x_size, y_size,
_hparent, NULL, hinstance, 0);
nout << "Done creating embedded window, _hwnd = " << _hWnd << "\n";
if (_hWnd) {
// join our keyboard state with the parents
@ -920,9 +940,6 @@ open_regular_window() {
// It causes problems with the browser plugin--it deadlocks when
// the parent process is waiting on the child process.
//AttachThreadInput(GetWindowThreadProcessId(_hparent,NULL), GetCurrentThreadId(),TRUE);
// set us as the focus window for keyboard input
SetFocus(_hWnd);
WindowProperties properties;
properties.set_foreground(true);
@ -1038,8 +1055,52 @@ track_mouse_leaving(HWND hwnd) {
}
////////////////////////////////////////////////////////////////////
// Function: WinGraphicsWindow::window_proc
// Function: WinGraphicsWindow::set_focus
// 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
// called to handle window events for this particular
// window.
@ -1226,7 +1287,9 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
SetCapture(hwnd);
_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());
SetFocus(hwnd); // [gjeon] to get the keyboard event
// A button-click in the window means to grab the keyboard focus.
set_focus();
break;
case WM_MBUTTONDOWN:
@ -1236,7 +1299,8 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
SetCapture(hwnd);
_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());
SetFocus(hwnd); // [gjeon] to get the keyboard event
// A button-click in the window means to grab the keyboard focus.
set_focus();
break;
case WM_RBUTTONDOWN:
@ -1246,7 +1310,8 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
SetCapture(hwnd);
_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());
SetFocus(hwnd); // [gjeon] to get the keyboard event
// A button-click in the window means to grab the keyboard focus.
set_focus();
break;
case WM_XBUTTONDOWN:
@ -2469,6 +2534,45 @@ register_window_class(const WindowProperties &props) {
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
void PrintErrorMessage(DWORD msgID) {
LPTSTR pMessageBuffer;
@ -2535,5 +2639,3 @@ void get_client_rect_screen(HWND hwnd, RECT *view_rect) {
view_rect->right = lr.x;
view_rect->bottom = lr.y;
}

View File

@ -62,6 +62,7 @@ public:
virtual void process_events();
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);
static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
virtual bool handle_mouse_motion(int x, int y);
@ -97,6 +98,8 @@ private:
void handle_raw_input(HRAWINPUT hraw);
void track_mouse_leaving(HWND hwnd);
void set_focus();
static void process_1_event();
INLINE void handle_keypress(ButtonHandle key, int x, int y, double time);
@ -213,6 +216,41 @@ private:
static int _window_class_index;
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:
static TypeHandle get_class_type() {
@ -222,6 +260,7 @@ public:
GraphicsWindow::init_type();
register_type(_type_handle, "WinGraphicsWindow",
GraphicsWindow::get_class_type());
WinWindowHandle::init_type();
}
virtual TypeHandle get_type() const {
return get_class_type();