mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
firefox fixes
This commit is contained in:
parent
4ee298e942
commit
4dd7ebec82
@ -37,8 +37,6 @@ typedef P3DSplashWindow SplashWindowType;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int P3DInstance::_next_instance_id = 0;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: P3DInstance::Constructor
|
// Function: P3DInstance::Constructor
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -55,8 +53,8 @@ P3DInstance(P3D_request_ready_func *func, void *user_data) :
|
|||||||
_got_fparams = false;
|
_got_fparams = false;
|
||||||
_got_wparams = false;
|
_got_wparams = false;
|
||||||
|
|
||||||
_instance_id = _next_instance_id;
|
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||||
++_next_instance_id;
|
_instance_id = inst_mgr->get_unique_id();
|
||||||
|
|
||||||
INIT_LOCK(_request_lock);
|
INIT_LOCK(_request_lock);
|
||||||
|
|
||||||
@ -123,7 +121,7 @@ set_fparams(const P3DFileParams &fparams) {
|
|||||||
// For the moment, all sessions will be unique.
|
// For the moment, all sessions will be unique.
|
||||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||||
ostringstream strm;
|
ostringstream strm;
|
||||||
strm << inst_mgr->get_unique_session_index();
|
strm << inst_mgr->get_unique_id();
|
||||||
_session_key = strm.str();
|
_session_key = strm.str();
|
||||||
|
|
||||||
// TODO.
|
// TODO.
|
||||||
@ -457,8 +455,8 @@ void P3DInstance::
|
|||||||
start_download(P3DDownload *download) {
|
start_download(P3DDownload *download) {
|
||||||
assert(download->get_download_id() == 0);
|
assert(download->get_download_id() == 0);
|
||||||
|
|
||||||
int download_id = _next_instance_id;
|
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||||
++_next_instance_id;
|
int download_id = inst_mgr->get_unique_id();
|
||||||
download->set_download_id(download_id);
|
download->set_download_id(download_id);
|
||||||
|
|
||||||
bool inserted = _downloads.insert(Downloads::value_type(download_id, download)).second;
|
bool inserted = _downloads.insert(Downloads::value_type(download_id, download)).second;
|
||||||
|
@ -139,8 +139,6 @@ private:
|
|||||||
typedef deque<P3D_request *> BakedRequests;
|
typedef deque<P3D_request *> BakedRequests;
|
||||||
BakedRequests _baked_requests;
|
BakedRequests _baked_requests;
|
||||||
|
|
||||||
static int _next_instance_id;
|
|
||||||
|
|
||||||
friend class P3DSession;
|
friend class P3DSession;
|
||||||
friend class SplashDownload;
|
friend class SplashDownload;
|
||||||
};
|
};
|
||||||
|
@ -40,7 +40,7 @@ P3DInstanceManager *P3DInstanceManager::_global_ptr;
|
|||||||
P3DInstanceManager::
|
P3DInstanceManager::
|
||||||
P3DInstanceManager() {
|
P3DInstanceManager() {
|
||||||
_is_initialized = false;
|
_is_initialized = false;
|
||||||
_unique_session_index = 0;
|
_unique_id = 0;
|
||||||
|
|
||||||
_notify_thread_continue = false;
|
_notify_thread_continue = false;
|
||||||
_started_notify_thread = false;
|
_started_notify_thread = false;
|
||||||
@ -280,16 +280,17 @@ get_package(const string &package_name, const string &package_version,
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: P3DInstanceManager::get_unique_session_index
|
// Function: P3DInstanceManager::get_unique_id
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description: Returns a number used to uniquify the session_key for
|
// Description: Returns a number used to uniquify different
|
||||||
// different instances. This number is guaranteed to be
|
// instances. This number is guaranteed to be different
|
||||||
// different at each call.
|
// at each call, at least until the int space rolls
|
||||||
|
// over.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
int P3DInstanceManager::
|
int P3DInstanceManager::
|
||||||
get_unique_session_index() {
|
get_unique_id() {
|
||||||
++_unique_session_index;
|
++_unique_id;
|
||||||
return _unique_session_index;
|
return _unique_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -61,7 +61,7 @@ public:
|
|||||||
|
|
||||||
inline int get_num_instances() const;
|
inline int get_num_instances() const;
|
||||||
|
|
||||||
int get_unique_session_index();
|
int get_unique_id();
|
||||||
void signal_request_ready(P3DInstance *inst);
|
void signal_request_ready(P3DInstance *inst);
|
||||||
|
|
||||||
P3D_class_definition *make_class_definition() const;
|
P3D_class_definition *make_class_definition() const;
|
||||||
@ -100,7 +100,7 @@ private:
|
|||||||
typedef map<string, P3DPackage *> Packages;
|
typedef map<string, P3DPackage *> Packages;
|
||||||
Packages _packages;
|
Packages _packages;
|
||||||
|
|
||||||
int _unique_session_index;
|
int _unique_id;
|
||||||
|
|
||||||
// This condition var is waited on the main thread and signaled in a
|
// This condition var is waited on the main thread and signaled in a
|
||||||
// sub-thread when new request notices arrive.
|
// sub-thread when new request notices arrive.
|
||||||
|
@ -32,6 +32,7 @@ P3DPythonRun(int argc, char *argv[]) {
|
|||||||
INIT_LOCK(_commands_lock);
|
INIT_LOCK(_commands_lock);
|
||||||
INIT_THREAD(_read_thread);
|
INIT_THREAD(_read_thread);
|
||||||
|
|
||||||
|
_session_id = 0;
|
||||||
_next_sent_id = 0;
|
_next_sent_id = 0;
|
||||||
|
|
||||||
_program_name = argv[0];
|
_program_name = argv[0];
|
||||||
@ -223,7 +224,20 @@ handle_command(TiXmlDocument *doc) {
|
|||||||
|
|
||||||
const char *cmd = xcommand->Attribute("cmd");
|
const char *cmd = xcommand->Attribute("cmd");
|
||||||
if (cmd != NULL) {
|
if (cmd != NULL) {
|
||||||
if (strcmp(cmd, "start_instance") == 0) {
|
if (strcmp(cmd, "init") == 0) {
|
||||||
|
assert(!needs_response);
|
||||||
|
|
||||||
|
// The only purpose of the "init" command is to send us a
|
||||||
|
// unique session ID, which in fact we don't do much with.
|
||||||
|
xcommand->Attribute("session_id", &_session_id);
|
||||||
|
|
||||||
|
// We do use it to initiate our object id sequence with a
|
||||||
|
// number at least a little bit distinct from other sessions,
|
||||||
|
// though. No technical requirement that we do this, but it
|
||||||
|
// does make debugging the logs a bit easier.
|
||||||
|
_next_sent_id = _session_id * 1000;
|
||||||
|
|
||||||
|
} else if (strcmp(cmd, "start_instance") == 0) {
|
||||||
assert(!needs_response);
|
assert(!needs_response);
|
||||||
TiXmlElement *xinstance = xcommand->FirstChildElement("instance");
|
TiXmlElement *xinstance = xcommand->FirstChildElement("instance");
|
||||||
if (xinstance != (TiXmlElement *)NULL) {
|
if (xinstance != (TiXmlElement *)NULL) {
|
||||||
@ -405,6 +419,7 @@ handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
|
|||||||
if (PyArg_ParseTuple(params, "s", &property_name)) {
|
if (PyArg_ParseTuple(params, "s", &property_name)) {
|
||||||
if (PyObject_HasAttrString(obj, property_name)) {
|
if (PyObject_HasAttrString(obj, property_name)) {
|
||||||
result = PyObject_GetAttrString(obj, property_name);
|
result = PyObject_GetAttrString(obj, property_name);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = NULL;
|
result = NULL;
|
||||||
}
|
}
|
||||||
|
@ -105,6 +105,8 @@ private:
|
|||||||
typedef pmap<int, P3DCInstance *> Instances;
|
typedef pmap<int, P3DCInstance *> Instances;
|
||||||
Instances _instances;
|
Instances _instances;
|
||||||
|
|
||||||
|
int _session_id;
|
||||||
|
|
||||||
string _program_name;
|
string _program_name;
|
||||||
int _py_argc;
|
int _py_argc;
|
||||||
char **_py_argv;
|
char **_py_argv;
|
||||||
|
@ -38,13 +38,12 @@
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
P3DSession::
|
P3DSession::
|
||||||
P3DSession(P3DInstance *inst) {
|
P3DSession(P3DInstance *inst) {
|
||||||
|
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||||
|
_session_id = inst_mgr->get_unique_id();
|
||||||
_session_key = inst->get_session_key();
|
_session_key = inst->get_session_key();
|
||||||
_python_version = inst->get_python_version();
|
_python_version = inst->get_python_version();
|
||||||
|
|
||||||
_next_sent_id = 0;
|
|
||||||
|
|
||||||
_p3dpython_running = false;
|
_p3dpython_running = false;
|
||||||
_next_response_id = 0;
|
|
||||||
_response = NULL;
|
_response = NULL;
|
||||||
_got_response_id = -1;
|
_got_response_id = -1;
|
||||||
|
|
||||||
@ -58,8 +57,6 @@ P3DSession(P3DInstance *inst) {
|
|||||||
INIT_LOCK(_instances_lock);
|
INIT_LOCK(_instances_lock);
|
||||||
INIT_THREAD(_read_thread);
|
INIT_THREAD(_read_thread);
|
||||||
|
|
||||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
|
||||||
|
|
||||||
_panda3d = inst_mgr->get_package("panda3d", "dev", "Panda3D");
|
_panda3d = inst_mgr->get_package("panda3d", "dev", "Panda3D");
|
||||||
_python_root_dir = _panda3d->get_package_dir();
|
_python_root_dir = _panda3d->get_package_dir();
|
||||||
inst->add_package(_panda3d);
|
inst->add_package(_panda3d);
|
||||||
@ -261,8 +258,8 @@ command_and_response(TiXmlDocument *command) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int response_id = _next_response_id;
|
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||||
++_next_response_id;
|
int response_id = inst_mgr->get_unique_id();
|
||||||
|
|
||||||
// Add the "want_response_id" attribute to the toplevel command, so
|
// Add the "want_response_id" attribute to the toplevel command, so
|
||||||
// the sub-process knows we'll be waiting for its response.
|
// the sub-process knows we'll be waiting for its response.
|
||||||
@ -474,15 +471,14 @@ p3dobj_to_xml(P3D_object *obj) {
|
|||||||
// should pass a reference down to this particular object, so
|
// should pass a reference down to this particular object, so
|
||||||
// the Python process knows to call back up to here to query it.
|
// the Python process knows to call back up to here to query it.
|
||||||
|
|
||||||
int object_id = _next_sent_id;
|
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||||
++_next_sent_id;
|
int object_id = inst_mgr->get_unique_id();
|
||||||
bool inserted = _sent_objects.insert(SentObjects::value_type(object_id, obj)).second;
|
bool inserted = _sent_objects.insert(SentObjects::value_type(object_id, obj)).second;
|
||||||
while (!inserted) {
|
while (!inserted) {
|
||||||
// Hmm, we must have cycled around the entire int space? Either
|
// Hmm, we must have cycled around the entire int space? Either
|
||||||
// that, or there's a logic bug somewhere. Assume the former,
|
// that, or there's a logic bug somewhere. Assume the former,
|
||||||
// and keep looking for an empty slot.
|
// and keep looking for an empty slot.
|
||||||
object_id = _next_sent_id;
|
object_id = inst_mgr->get_unique_id();
|
||||||
++_next_sent_id;
|
|
||||||
inserted = _sent_objects.insert(SentObjects::value_type(object_id, obj)).second;
|
inserted = _sent_objects.insert(SentObjects::value_type(object_id, obj)).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -656,16 +652,28 @@ start_p3dpython() {
|
|||||||
|
|
||||||
spawn_read_thread();
|
spawn_read_thread();
|
||||||
|
|
||||||
// Now that the process has been started, feed it any commands we
|
// The very first command we send to the process is its session_id.
|
||||||
// may have queued up.
|
TiXmlDocument doc;
|
||||||
|
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
|
||||||
|
TiXmlElement *xcommand = new TiXmlElement("command");
|
||||||
|
xcommand->SetAttribute("cmd", "init");
|
||||||
|
xcommand->SetAttribute("session_id", _session_id);
|
||||||
|
doc.LinkEndChild(decl);
|
||||||
|
doc.LinkEndChild(xcommand);
|
||||||
|
nout << "sent: " << doc << "\n" << flush;
|
||||||
|
_pipe_write << doc;
|
||||||
|
|
||||||
|
// Also feed it any commands we may have queued up from before the
|
||||||
|
// process was started.
|
||||||
Commands::iterator ci;
|
Commands::iterator ci;
|
||||||
for (ci = _commands.begin(); ci != _commands.end(); ++ci) {
|
for (ci = _commands.begin(); ci != _commands.end(); ++ci) {
|
||||||
nout << "sent: " << *(*ci) << "\n" << flush;
|
nout << "sent: " << *(*ci) << "\n" << flush;
|
||||||
_pipe_write << *(*ci);
|
_pipe_write << *(*ci);
|
||||||
delete (*ci);
|
delete (*ci);
|
||||||
}
|
}
|
||||||
_pipe_write << flush;
|
|
||||||
_commands.clear();
|
_commands.clear();
|
||||||
|
|
||||||
|
_pipe_write << flush;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -98,6 +98,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int _session_id;
|
||||||
string _session_key;
|
string _session_key;
|
||||||
string _python_version;
|
string _python_version;
|
||||||
string _output_filename;
|
string _output_filename;
|
||||||
@ -119,7 +120,6 @@ private:
|
|||||||
// child process tells us it's safe to delete them.
|
// child process tells us it's safe to delete them.
|
||||||
typedef map<int, P3D_object *> SentObjects;
|
typedef map<int, P3D_object *> SentObjects;
|
||||||
SentObjects _sent_objects;
|
SentObjects _sent_objects;
|
||||||
int _next_sent_id;
|
|
||||||
|
|
||||||
P3DPackage *_panda3d;
|
P3DPackage *_panda3d;
|
||||||
PackageCallback *_panda3d_callback;
|
PackageCallback *_panda3d_callback;
|
||||||
@ -132,8 +132,6 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
bool _p3dpython_running;
|
bool _p3dpython_running;
|
||||||
|
|
||||||
int _next_response_id;
|
|
||||||
|
|
||||||
// The _response_ready mutex protects this pointer.
|
// The _response_ready mutex protects this pointer.
|
||||||
TiXmlDocument *_response;
|
TiXmlDocument *_response;
|
||||||
int _got_response_id;
|
int _got_response_id;
|
||||||
|
@ -221,7 +221,13 @@ has_property(NPIdentifier name) {
|
|||||||
// will never be called. So we always say we *do* have any
|
// will never be called. So we always say we *do* have any
|
||||||
// particular property, whether we currently have it right now or
|
// particular property, whether we currently have it right now or
|
||||||
// not (since we *could* have it if you call set_property()).
|
// not (since we *could* have it if you call set_property()).
|
||||||
return true;
|
|
||||||
|
// On the other hand, Firefox gets confused about methods that are
|
||||||
|
// also properties. So you have to say there's *no* property if
|
||||||
|
// there is in fact a callable method by that name, or Firefox will
|
||||||
|
// never call the method.
|
||||||
|
bool result = P3D_OBJECT_HAS_METHOD(_p3d_object, property_name.c_str());
|
||||||
|
return !result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -518,7 +518,12 @@ class BrowserObject:
|
|||||||
value = self.__runner.scriptRequest('get_property', self,
|
value = self.__runner.scriptRequest('get_property', self,
|
||||||
propertyName = name)
|
propertyName = name)
|
||||||
except EnvironmentError:
|
except EnvironmentError:
|
||||||
# Failed to retrieve the attribute.
|
# Failed to retrieve the attribute. But maybe there's a
|
||||||
|
# method instead?
|
||||||
|
if self.__runner.scriptRequest('has_method', self, propertyName = name):
|
||||||
|
# Yes, so create a method wrapper for it.
|
||||||
|
return MethodWrapper(self.__runner, self, name)
|
||||||
|
|
||||||
raise AttributeError(name)
|
raise AttributeError(name)
|
||||||
|
|
||||||
if isinstance(value, BrowserObject):
|
if isinstance(value, BrowserObject):
|
||||||
@ -591,6 +596,64 @@ class BrowserObject:
|
|||||||
else:
|
else:
|
||||||
raise IndexError(key)
|
raise IndexError(key)
|
||||||
|
|
||||||
|
class MethodWrapper:
|
||||||
|
""" This is a Python wrapper around a property of a BrowserObject
|
||||||
|
that doesn't appear to be a first-class object in the Python
|
||||||
|
sense, but is nonetheless a callable method. """
|
||||||
|
|
||||||
|
def __init__(self, runner, parentObj, objectId):
|
||||||
|
self.__dict__['_MethodWrapper__runner'] = runner
|
||||||
|
self.__dict__['_MethodWraper__boundMethod'] = (parentObj, objectId)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
parentObj, attribName = self.__boundMethod
|
||||||
|
return "%s.%s" % (parentObj, attribName)
|
||||||
|
|
||||||
|
def __nonzero__(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __call__(self, *args):
|
||||||
|
try:
|
||||||
|
parentObj, attribName = self.__boundMethod
|
||||||
|
# Call it as a method.
|
||||||
|
needsResponse = True
|
||||||
|
if parentObj is self.__runner.dom and attribName == 'alert':
|
||||||
|
# As a special hack, we don't wait for the return
|
||||||
|
# value from the alert() call, since this is a
|
||||||
|
# blocking call, and waiting for this could cause
|
||||||
|
# problems.
|
||||||
|
needsResponse = False
|
||||||
|
|
||||||
|
if parentObj is self.__runner.dom and attribName == 'eval' and len(args) == 1 and isinstance(args[0], types.StringTypes):
|
||||||
|
# As another special hack, we make dom.eval() a
|
||||||
|
# special case, and map it directly into an eval()
|
||||||
|
# call. If the string begins with 'void ', we further
|
||||||
|
# assume we're not waiting for a response.
|
||||||
|
if args[0].startswith('void '):
|
||||||
|
needsResponse = False
|
||||||
|
result = self.__runner.scriptRequest('eval', parentObj, value = args[0], needsResponse = needsResponse)
|
||||||
|
else:
|
||||||
|
# This is a normal method call.
|
||||||
|
try:
|
||||||
|
result = self.__runner.scriptRequest('call', parentObj, propertyName = attribName, value = args, needsResponse = needsResponse)
|
||||||
|
except EnvironmentError:
|
||||||
|
# Problem on the call. Maybe no such method?
|
||||||
|
raise AttributeError
|
||||||
|
|
||||||
|
except EnvironmentError:
|
||||||
|
# Some odd problem on the call.
|
||||||
|
raise TypeError
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def __setattr__(self, name, value):
|
||||||
|
""" setattr will generally fail on method objects. """
|
||||||
|
raise AttributeError(name)
|
||||||
|
|
||||||
|
def __delattr__(self, name):
|
||||||
|
""" delattr will generally fail on method objects. """
|
||||||
|
raise AttributeError(name)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
runner = AppRunner()
|
runner = AppRunner()
|
||||||
runner.gotWindow = True
|
runner.gotWindow = True
|
||||||
|
Loading…
x
Reference in New Issue
Block a user