better handling of some startup failures; don't make a osx gui app unless necessary

This commit is contained in:
David Rose 2009-10-22 07:05:51 +00:00
parent 3f5dd0d039
commit 2dbd154536
8 changed files with 78 additions and 37 deletions

View File

@ -33,7 +33,7 @@ else:
from direct.showbase import VFSImporter from direct.showbase import VFSImporter
from direct.showbase.DirectObject import DirectObject from direct.showbase.DirectObject import DirectObject
from pandac.PandaModules import VirtualFileSystem, Filename, Multifile, loadPrcFileData, unloadPrcFile, getModelPath, Thread, WindowProperties, ExecutionEnvironment, PandaSystem, Notify, StreamWriter, ConfigVariableString from pandac.PandaModules import VirtualFileSystem, Filename, Multifile, loadPrcFileData, unloadPrcFile, getModelPath, Thread, WindowProperties, ExecutionEnvironment, PandaSystem, Notify, StreamWriter, ConfigVariableString, initAppForGui
from pandac import PandaModules from pandac import PandaModules
from direct.stdpy import file from direct.stdpy import file
from direct.task.TaskManagerGlobal import taskMgr from direct.task.TaskManagerGlobal import taskMgr
@ -80,6 +80,7 @@ class AppRunner(DirectObject):
# These will be set from the application flags when # These will be set from the application flags when
# setP3DFilename() is called. # setP3DFilename() is called.
self.allowPythonDev = False self.allowPythonDev = False
self.guiApp = False
self.interactiveConsole = False self.interactiveConsole = False
self.initialAppImport = False self.initialAppImport = False
@ -518,29 +519,41 @@ class AppRunner(DirectObject):
self.superMirrorUrl = superMirrorUrl self.superMirrorUrl = superMirrorUrl
def addPackageInfo(self, name, platform, version, hostUrl): def addPackageInfo(self, name, platform, version, hostUrl):
""" Called by the browser to list all of the "required" """ Called by the browser for each one of the "required"
packages that were preloaded before starting the packages that were preloaded before starting the application.
application. If for some reason the package isn't already If for some reason the package isn't already downloaded, this
downloaded, this will download it on the spot. """ will download it on the spot. Raises OSError on failure. """
host = self.getHost(hostUrl) host = self.getHost(hostUrl)
if not host.readContentsFile(): if not host.readContentsFile():
if not host.downloadContentsFile(self.http): if not host.downloadContentsFile(self.http):
print "Host %s cannot be downloaded, cannot preload %s." % (hostUrl, name) message = "Host %s cannot be downloaded, cannot preload %s." % (hostUrl, name)
return raise OSError, message
if not platform: if not platform:
platform = None platform = None
package = host.getPackage(name, version, platform = platform) package = host.getPackage(name, version, platform = platform)
if not package: if not package:
print "Couldn't find %s %s on %s" % (name, version, hostUrl) message = "Couldn't find %s %s on %s" % (name, version, hostUrl)
return raise OSError, message
package.checkStatus() package.checkStatus()
package.downloadDescFile(self.http) if not package.downloadDescFile(self.http):
package.downloadPackage(self.http) message = "Couldn't get desc file for %s" % (name)
package.installPackage(self) raise OSError, message
if not package.downloadPackage(self.http):
message = "Couldn't download %s" % (name)
raise OSError, message
if not package.installPackage(self):
message = "Couldn't install %s" % (name)
raise OSError, message
if package.guiApp:
self.guiApp = True
initAppForGui()
def setP3DFilename(self, p3dFilename, tokens, argv, instanceId, def setP3DFilename(self, p3dFilename, tokens, argv, instanceId,
interactiveConsole): interactiveConsole):
@ -608,6 +621,9 @@ class AppRunner(DirectObject):
allowPythonDev = self.p3dConfig.Attribute('allow_python_dev') allowPythonDev = self.p3dConfig.Attribute('allow_python_dev')
if allowPythonDev: if allowPythonDev:
self.allowPythonDev = int(allowPythonDev) self.allowPythonDev = int(allowPythonDev)
guiApp = self.p3dConfig.Attribute('gui_app')
if guiApp:
self.guiApp = int(guiApp)
xhost = self.p3dConfig.FirstChildElement('host') xhost = self.p3dConfig.FirstChildElement('host')
while xhost: while xhost:
@ -625,6 +641,9 @@ class AppRunner(DirectObject):
# allow_python_dev is enabled. # allow_python_dev is enabled.
ConfigVariableString('frame-rate-meter-text-pattern').setValue('allow_python_dev %0.1f fps') ConfigVariableString('frame-rate-meter-text-pattern').setValue('allow_python_dev %0.1f fps')
if self.guiApp:
initAppForGui()
self.initPackedAppEnvironment() self.initPackedAppEnvironment()
# Mount the Multifile under /mf, by convention. # Mount the Multifile under /mf, by convention.

View File

@ -77,6 +77,7 @@ class PackageInfo:
self.hasDescFile = False self.hasDescFile = False
self.patchVersion = None self.patchVersion = None
self.displayName = None self.displayName = None
self.guiApp = False
self.uncompressedArchive = None self.uncompressedArchive = None
self.compressedArchive = None self.compressedArchive = None
self.extracts = [] self.extracts = []
@ -243,6 +244,11 @@ class PackageInfo:
# The name for display to an English-speaking user. # The name for display to an English-speaking user.
self.displayName = xconfig.Attribute('display_name') self.displayName = xconfig.Attribute('display_name')
# True if any apps that use this package must be GUI apps.
guiApp = xconfig.Attribute('gui_app')
if guiApp:
self.guiApp = int(guiApp)
# The uncompressed archive, which will be mounted directly, # The uncompressed archive, which will be mounted directly,
# and also used for patching. # and also used for patching.
xuncompressedArchive = xpackage.FirstChildElement('uncompressed_archive') xuncompressedArchive = xpackage.FirstChildElement('uncompressed_archive')
@ -800,7 +806,7 @@ class PackageInfo:
def installPackage(self, appRunner): def installPackage(self, appRunner):
""" Mounts the package and sets up system paths so it becomes """ Mounts the package and sets up system paths so it becomes
available for use. """ available for use. Returns true on success, false on failure. """
assert self.hasPackage assert self.hasPackage
if self.installed: if self.installed:

View File

@ -214,6 +214,7 @@ class ode(package):
class wx(package): class wx(package):
config(display_name = "wxPython GUI Toolkit") config(display_name = "wxPython GUI Toolkit")
config(gui_app = True)
require('panda3d') require('panda3d')
module('direct.showbase.WxGlobal', 'wx', 'wx.*') module('direct.showbase.WxGlobal', 'wx', 'wx.*')
@ -221,6 +222,7 @@ class wx(package):
class tk(package): class tk(package):
config(display_name = "Tk GUI Toolkit") config(display_name = "Tk GUI Toolkit")
config(gui_app = True)
require('panda3d') require('panda3d')
module('Tkinter', module('Tkinter',

View File

@ -21,11 +21,6 @@
#include <string.h> // strrchr #include <string.h> // strrchr
using namespace std; using namespace std;
#ifdef __APPLE__
#include <Carbon/Carbon.h>
extern "C" { void CPSEnableForegroundOperation(ProcessSerialNumber* psn); }
#endif
#if defined(_WIN32) && defined(NON_CONSOLE) #if defined(_WIN32) && defined(NON_CONSOLE)
// On Windows, we may need to build p3dpythonw.exe, a non-console // On Windows, we may need to build p3dpythonw.exe, a non-console
// version of this program. // version of this program.
@ -155,16 +150,6 @@ main(int argc, char *argv[]) {
} }
} }
#ifdef __APPLE__
// In case the application is going to run a wx app, allow it to
// have access to the desktop.
ProcessSerialNumber psn;
GetCurrentProcess(&psn);
CPSEnableForegroundOperation(&psn);
SetFrontProcess(&psn);
#endif
if (!run_p3dpython(program_name, archive_file, input_handle, output_handle, if (!run_p3dpython(program_name, archive_file, input_handle, output_handle,
NULL, interactive_console)) { NULL, interactive_console)) {
cerr << "Failure on startup.\n"; cerr << "Failure on startup.\n";

View File

@ -1180,9 +1180,10 @@ set_instance_info(P3DCInstance *inst, TiXmlElement *xinstance) {
if (result == NULL) { if (result == NULL) {
PyErr_Print(); PyErr_Print();
if (!_interactive_console) { if (_interactive_console) {
exit(1); run_interactive_console();
} }
exit(1);
} }
Py_XDECREF(result); Py_XDECREF(result);
} }
@ -1214,10 +1215,12 @@ add_package_info(P3DCInstance *inst, TiXmlElement *xpackage) {
if (result == NULL) { if (result == NULL) {
PyErr_Print(); PyErr_Print();
if (!_interactive_console) { if (_interactive_console) {
run_interactive_console();
}
exit(1); exit(1);
} }
}
Py_XDECREF(result); Py_XDECREF(result);
} }
@ -1281,9 +1284,10 @@ set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams) {
if (result == NULL) { if (result == NULL) {
PyErr_Print(); PyErr_Print();
if (!_interactive_console) { if (_interactive_console) {
exit(1); run_interactive_console();
} }
exit(1);
} }
Py_XDECREF(result); Py_XDECREF(result);
} }
@ -1380,9 +1384,10 @@ setup_window(P3DCInstance *inst, TiXmlElement *xwparams) {
if (result == NULL) { if (result == NULL) {
PyErr_Print(); PyErr_Print();
if (!_interactive_console) { if (_interactive_console) {
exit(1); run_interactive_console();
} }
exit(1);
} }
Py_XDECREF(result); Py_XDECREF(result);
} }

View File

@ -2429,6 +2429,7 @@ class ShowBase(DirectObject.DirectObject):
def startWx(self, fWantWx = 1): def startWx(self, fWantWx = 1):
self.wantWx = fWantWx self.wantWx = fWantWx
if self.wantWx: if self.wantWx:
initAppForGui()
from direct.showbase import WxGlobal from direct.showbase import WxGlobal
taskMgr.remove('wxLoop') taskMgr.remove('wxLoop')
WxGlobal.spawnWxLoop() WxGlobal.spawnWxLoop()
@ -2436,6 +2437,7 @@ class ShowBase(DirectObject.DirectObject):
def startTk(self, fWantTk = 1): def startTk(self, fWantTk = 1):
self.wantTk = fWantTk self.wantTk = fWantTk
if self.wantTk: if self.wantTk:
initAppForGui()
from direct.showbase import TkGlobal from direct.showbase import TkGlobal
taskMgr.remove('tkLoop') taskMgr.remove('tkLoop')
TkGlobal.spawnTkLoop() TkGlobal.spawnTkLoop()

View File

@ -20,6 +20,11 @@
#include "camera.h" #include "camera.h"
#include "graphicsPipeSelection.h" #include "graphicsPipeSelection.h"
#ifdef __APPLE__
#include <Carbon/Carbon.h>
extern "C" { void CPSEnableForegroundOperation(ProcessSerialNumber* psn); }
#endif
#ifdef WIN32 #ifdef WIN32
#include <windows.h> // For SystemParametersInfo() #include <windows.h> // For SystemParametersInfo()
STICKYKEYS g_StartupStickyKeys = {sizeof(STICKYKEYS), 0}; STICKYKEYS g_StartupStickyKeys = {sizeof(STICKYKEYS), 0};
@ -55,6 +60,23 @@ get_config_showbase() {
return config_showbase; return config_showbase;
} }
// Initialize the application for making a Gui-based app, such as wx.
// At the moment, this is a no-op except on Mac.
void
init_app_for_gui() {
static bool initted_for_gui = false;
if (!initted_for_gui) {
initted_for_gui = true;
#ifdef IS_OSX
ProcessSerialNumber psn;
GetCurrentProcess(&psn);
CPSEnableForegroundOperation(&psn);
SetFrontProcess(&psn);
#endif // IS_OSX
}
}
// klunky interface since we cant pass array from python->C++ to use verify_window_sizes directly // klunky interface since we cant pass array from python->C++ to use verify_window_sizes directly
static int num_fullscreen_testsizes = 0; static int num_fullscreen_testsizes = 0;
#define MAX_FULLSCREEN_TESTS 10 #define MAX_FULLSCREEN_TESTS 10

View File

@ -40,7 +40,7 @@ EXPCL_DIRECT ConfigVariableSearchPath &get_particle_path();
EXPCL_DIRECT void throw_new_frame(); EXPCL_DIRECT void throw_new_frame();
EXPCL_DIRECT DConfig &get_config_showbase(); EXPCL_DIRECT DConfig &get_config_showbase();
EXPCL_DIRECT void init_app_for_gui();
// klunky interface since we cant pass array from python->C++ // klunky interface since we cant pass array from python->C++
EXPCL_DIRECT void add_fullscreen_testsize(int xsize, int ysize); EXPCL_DIRECT void add_fullscreen_testsize(int xsize, int ysize);