mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
request_keyboard_focus
This commit is contained in:
parent
f89a811cf6
commit
5e12be142a
@ -20,6 +20,7 @@
|
||||
#include "p3d_plugin.h"
|
||||
#include "pvector.h"
|
||||
#include "get_tinyxml.h"
|
||||
#include "windowHandle.h"
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
@ -28,7 +29,7 @@ class P3DSession;
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : P3DCInstance
|
||||
// Description : This is an instance of a Panda3D window, as seen in
|
||||
// the parent-level process.
|
||||
// the child-level process.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class P3DCInstance : public P3D_instance {
|
||||
public:
|
||||
@ -37,6 +38,9 @@ public:
|
||||
|
||||
inline int get_instance_id() const;
|
||||
|
||||
public:
|
||||
PT(WindowHandle) _parent_window_handle;
|
||||
|
||||
private:
|
||||
P3D_request_ready_func *_func;
|
||||
|
||||
|
@ -1495,6 +1495,9 @@ handle_notify_request(const string &message) {
|
||||
} else if (message == "authfinished") {
|
||||
// Similarly for the "auth finished" message.
|
||||
auth_finished_main_thread();
|
||||
|
||||
} else if (message == "keyboardfocus") {
|
||||
request_keyboard_focus();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1594,6 +1597,19 @@ 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
|
||||
|
@ -162,6 +162,8 @@ 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);
|
||||
void set_button_image(ImageType image_type);
|
||||
|
@ -29,6 +29,8 @@ IMPORT_THIS struct Dtool_PyTypedObject Dtool_WindowHandle;
|
||||
// instances of this thing.
|
||||
P3DPythonRun *P3DPythonRun::_global_ptr = NULL;
|
||||
|
||||
TypeHandle P3DPythonRun::P3DWindowHandle::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DPythonRun::Constructor
|
||||
// Access: Public
|
||||
@ -38,6 +40,8 @@ P3DPythonRun::
|
||||
P3DPythonRun(const char *program_name, const char *archive_file,
|
||||
FHandle input_handle, FHandle output_handle,
|
||||
const char *log_pathname, bool interactive_console) {
|
||||
P3DWindowHandle::init_type();
|
||||
|
||||
_read_thread_continue = false;
|
||||
_program_continue = true;
|
||||
_session_terminated = false;
|
||||
@ -112,6 +116,8 @@ P3DPythonRun(const char *program_name, const char *archive_file,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DPythonRun::
|
||||
~P3DPythonRun() {
|
||||
nassertv(_instances.empty());
|
||||
|
||||
// Close the write pipe, so the parent process will terminate us.
|
||||
_pipe_write.close();
|
||||
|
||||
@ -380,6 +386,35 @@ run_python() {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DPythonRun::request_keyboard_focus
|
||||
// Access: Public
|
||||
// Description: Called from low-level Panda (via the P3DWindowHandle
|
||||
// object) when its main window requires keyboard focus,
|
||||
// but is unable to assign it directly. This is
|
||||
// particularly necessary under Windows Vista, where a
|
||||
// child window of the browser is specifically
|
||||
// disallowed from being given keyboard focus.
|
||||
//
|
||||
// This sends a notify request up to the parent process,
|
||||
// to ask the parent to manage keyboard events by proxy,
|
||||
// and send them back down to Panda, again via the
|
||||
// P3DWindowHandle.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
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());
|
||||
xrequest->SetAttribute("rtype", "notify");
|
||||
xrequest->SetAttribute("message", "keyboardfocus");
|
||||
doc.LinkEndChild(xrequest);
|
||||
|
||||
write_xml(_pipe_write, &doc, nout);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DPythonRun::run_interactive_console
|
||||
// Access: Private
|
||||
@ -1299,6 +1334,15 @@ setup_window(P3DCInstance *inst, TiXmlElement *xwparams) {
|
||||
|
||||
PyObject *py_handle = Py_None;
|
||||
if (parent_window_handle != NULL) {
|
||||
|
||||
// We have a valid parent WindowHandle, but replace it with a
|
||||
// P3DWindowHandle so we can get the callbacks.
|
||||
parent_window_handle = new P3DWindowHandle(this, inst, *parent_window_handle);
|
||||
inst->_parent_window_handle = parent_window_handle;
|
||||
|
||||
// Also pass this P3DWindowHandle object down into Panda, via the
|
||||
// setupWindow() call. For this, we need to create a Python
|
||||
// wrapper objcet.
|
||||
parent_window_handle->ref();
|
||||
py_handle = DTool_CreatePyInstanceTyped(parent_window_handle, Dtool_WindowHandle, true, false, parent_window_handle->get_type_index());
|
||||
}
|
||||
@ -1666,3 +1710,29 @@ rt_thread_run() {
|
||||
RELEASE_LOCK(_commands_lock);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DPythonRun::P3DWindowHandle::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DPythonRun::P3DWindowHandle::
|
||||
P3DWindowHandle(P3DPythonRun *p3dpython, P3DCInstance *inst,
|
||||
const WindowHandle ©) :
|
||||
WindowHandle(copy.get_os_handle()),
|
||||
_p3dpython(p3dpython),
|
||||
_inst(inst)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DPythonRun::P3DWindowHandle::request_keyboard_focus
|
||||
// Access: Public, Virtual
|
||||
// Description: Called on a parent handle to indicate a child
|
||||
// window's wish to receive keyboard button events.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DPythonRun::P3DWindowHandle::
|
||||
request_keyboard_focus(WindowHandle *child) {
|
||||
WindowHandle::request_keyboard_focus(child);
|
||||
_p3dpython->request_keyboard_focus(_inst);
|
||||
}
|
||||
|
@ -74,6 +74,8 @@ public:
|
||||
|
||||
bool run_python();
|
||||
|
||||
void request_keyboard_focus(P3DCInstance *inst);
|
||||
|
||||
private:
|
||||
void run_interactive_console();
|
||||
void handle_command(TiXmlDocument *doc);
|
||||
@ -105,6 +107,42 @@ private:
|
||||
TiXmlElement *pyobj_to_xml(PyObject *value);
|
||||
PyObject *xml_to_pyobj(TiXmlElement *xvalue);
|
||||
|
||||
private:
|
||||
// This subclass of P3DWindowHandle 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
|
||||
// necessary.
|
||||
class P3DWindowHandle : public WindowHandle {
|
||||
public:
|
||||
P3DWindowHandle(P3DPythonRun *p3dpython, P3DCInstance *inst,
|
||||
const WindowHandle ©);
|
||||
|
||||
private:
|
||||
P3DPythonRun *_p3dpython;
|
||||
P3DCInstance *_inst;
|
||||
|
||||
protected:
|
||||
virtual void request_keyboard_focus(WindowHandle *child);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
WindowHandle::init_type();
|
||||
register_type(_type_handle, "P3DWindowHandle",
|
||||
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;
|
||||
};
|
||||
|
||||
private:
|
||||
// This method runs only within the read thread.
|
||||
THREAD_CALLBACK_DECLARATION(P3DPythonRun, rt_thread_run);
|
||||
|
@ -749,6 +749,15 @@ void GraphicsWindow::
|
||||
close_window() {
|
||||
display_cat.info()
|
||||
<< "Closing " << get_type() << "\n";
|
||||
|
||||
// Tell our parent window (if any) that we're no longer its child.
|
||||
if (_window_handle != (WindowHandle *)NULL &&
|
||||
_parent_window_handle != (WindowHandle *)NULL) {
|
||||
_parent_window_handle->detach_child(_window_handle);
|
||||
}
|
||||
|
||||
_window_handle = NULL;
|
||||
_parent_window_handle = NULL;
|
||||
_is_valid = false;
|
||||
}
|
||||
|
||||
|
@ -132,6 +132,7 @@ protected:
|
||||
protected:
|
||||
WindowProperties _properties;
|
||||
PT(WindowHandle) _window_handle;
|
||||
PT(WindowHandle) _parent_window_handle;
|
||||
|
||||
private:
|
||||
LightReMutex _properties_lock;
|
||||
|
@ -26,6 +26,22 @@ WindowHandle::
|
||||
~WindowHandle() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowHandle::send_keyboard_event
|
||||
// Access: Published
|
||||
// Description: Call this method on a parent WindowHandle to deliver
|
||||
// a button event 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.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void WindowHandle::
|
||||
send_keyboard_event(const ButtonEvent &event) {
|
||||
if (_keyboard_window != NULL) {
|
||||
_keyboard_window->receive_keyboard_event(event);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowHandle::get_int_handle
|
||||
// Access: Published
|
||||
@ -57,7 +73,7 @@ output(ostream &out) const {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowHandle::attach_child
|
||||
// Access: Protected, Virtual
|
||||
// Access: Public, Virtual
|
||||
// Description: Called on a parent handle to indicate a child
|
||||
// window's intention to attach itself.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -67,25 +83,37 @@ attach_child(WindowHandle *child) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowHandle::detach_child
|
||||
// Access: Protected, Virtual
|
||||
// Access: Public, Virtual
|
||||
// Description: Called on a parent handle to indicate a child
|
||||
// window's intention to detach itself.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void WindowHandle::
|
||||
detach_child(WindowHandle *child) {
|
||||
if (_keyboard_window == child) {
|
||||
_keyboard_window = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowHandle::set_keyboard_focus
|
||||
// Access: Protected, Virtual
|
||||
// Function: WindowHandle::request_keyboard_focus
|
||||
// Access: Public, Virtual
|
||||
// Description: Called on a parent handle to indicate a child
|
||||
// window's intention to set itself as the recipient of
|
||||
// keyboard events.
|
||||
// window's wish to receive keyboard button events.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void WindowHandle::
|
||||
set_keyboard_focus(WindowHandle *child) {
|
||||
request_keyboard_focus(WindowHandle *child) {
|
||||
_keyboard_window = child;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowHandle::receive_keyboard_event
|
||||
// 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) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowHandle::OSHandle::Destructor
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include "typedReferenceCount.h"
|
||||
#include "pointerTo.h"
|
||||
|
||||
class ButtonEvent;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : WindowHandle
|
||||
// Description : This object represents a window on the desktop, not
|
||||
@ -48,10 +50,21 @@ PUBLISHED:
|
||||
INLINE OSHandle *get_os_handle() const;
|
||||
INLINE void set_os_handle(OSHandle *os_handle);
|
||||
|
||||
void send_keyboard_event(const ButtonEvent &event);
|
||||
|
||||
size_t get_int_handle() const;
|
||||
|
||||
void output(ostream &out) const;
|
||||
|
||||
public:
|
||||
// Callbacks for communication with the parent window.
|
||||
virtual void attach_child(WindowHandle *child);
|
||||
virtual void detach_child(WindowHandle *child);
|
||||
|
||||
virtual void request_keyboard_focus(WindowHandle *child);
|
||||
virtual void receive_keyboard_event(const ButtonEvent &event);
|
||||
|
||||
PUBLISHED:
|
||||
// This internal pointer within WindowHandle stores the actual
|
||||
// OS-specific window handle type, whatever type that is. It is
|
||||
// subclassed for each OS.
|
||||
@ -82,16 +95,11 @@ PUBLISHED:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
protected:
|
||||
// Callbacks for communication with the parent window.
|
||||
virtual void attach_child(WindowHandle *child);
|
||||
virtual void detach_child(WindowHandle *child);
|
||||
|
||||
virtual void set_keyboard_focus(WindowHandle *child);
|
||||
|
||||
protected:
|
||||
PT(OSHandle) _os_handle;
|
||||
|
||||
PT(WindowHandle) _keyboard_window;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
@ -685,6 +685,7 @@ open_window() {
|
||||
}
|
||||
}
|
||||
}
|
||||
_parent_window_handle = window_handle;
|
||||
|
||||
setup_colormap(visual_info);
|
||||
|
||||
@ -774,6 +775,14 @@ open_window() {
|
||||
}
|
||||
}
|
||||
|
||||
// Create a WindowHandle for ourselves
|
||||
_window_handle = NativeWindowHandle::make_x11(_xwindow);
|
||||
|
||||
// And tell our parent window that we're now its child.
|
||||
if (_parent_window_handle != (WindowHandle *)NULL) {
|
||||
_parent_window_handle->attach_child(_window_handle);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -216,6 +216,7 @@ open_window() {
|
||||
}
|
||||
}
|
||||
}
|
||||
_parent_window_handle = window_handle;
|
||||
|
||||
#ifdef HAVE_GLXFBCONFIG
|
||||
if (glxgsg->_fbconfig != None) {
|
||||
@ -302,7 +303,15 @@ open_window() {
|
||||
<< "Raw mice not requested.\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Create a WindowHandle for ourselves
|
||||
_window_handle = NativeWindowHandle::make_x11(_xwindow);
|
||||
|
||||
// And tell our parent window that we're now its child.
|
||||
if (_parent_window_handle != (WindowHandle *)NULL) {
|
||||
_parent_window_handle->attach_child(_window_handle);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -531,6 +531,7 @@ open_window() {
|
||||
}
|
||||
}
|
||||
}
|
||||
_parent_window_handle = window_handle;
|
||||
|
||||
setup_colormap(visual_info);
|
||||
|
||||
@ -616,6 +617,14 @@ open_window() {
|
||||
<< "Raw mice not requested.\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Create a WindowHandle for ourselves
|
||||
_window_handle = NativeWindowHandle::make_x11(_xwindow);
|
||||
|
||||
// And tell our parent window that we're now its child.
|
||||
if (_parent_window_handle != (WindowHandle *)NULL) {
|
||||
_parent_window_handle->attach_child(_window_handle);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -634,6 +634,7 @@ close_window() {
|
||||
// application, so the server hears the close request.
|
||||
XFlush(_display);
|
||||
}
|
||||
|
||||
GraphicsWindow::close_window();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user