layer5/main.cpp (1,309 lines of code) (raw):
/*
A* -------------------------------------------------------------------
B* This file contains source code for the PyMOL computer program
C* Copyright (c) Schrodinger, LLC.
D* -------------------------------------------------------------------
E* It is unlawful to modify or remove this copyright notice.
F* -------------------------------------------------------------------
G* Please see the accompanying LICENSE file for further information.
H* -------------------------------------------------------------------
I* Additional authors of this source file include:
-*
-*
-*
Z* -------------------------------------------------------------------
*/
#include"os_python.h"
#include "os_predef.h"
/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
#ifdef WIN32
#include <signal.h>
#include <tchar.h>
#endif
/* END PROPRIETARY CODE SEGMENT */
#include "os_std.h"
#include "os_gl.h"
#ifdef _DRI_WORKAROUND
#include <dlfcn.h>
#endif
#include "PyMOLGlobals.h"
#include "PyMOL.h"
#include "PyMOLOptions.h"
#include "MemoryDebug.h"
#include "Base.h"
#include "main.h"
#include "P.h"
#include "PConv.h"
#include "Ortho.h"
#include "Scene.h"
#include "Seq.h"
#include "Util.h"
#include "Control.h"
#include "Movie.h"
#include "Executive.h"
int _gScaleFactor = 1;
#ifdef _PYMOL_NO_MAIN
int MainSavingUnderWhileIdle(void)
{
return 0;
}
#ifdef _MACPYMOL_XCODE
void MainBlock(void)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
PBlock(G);
}
void MainUnblock(void)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
PUnblock(G);
}
int MainLockAPIAsGlut(int a)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
return PLockAPIAsGlut(G, a);
}
void MainUnlockAPIAsGlut()
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
PUnlockAPIAsGlut(G);
}
int MainFeedbackOut(char *st)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
return OrthoFeedbackOut(G, *G->Ortho);
}
void MainRunCommand(const char *str1)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
if(PLockAPIAsGlut(G, true)) {
if(str1[0] != '_') { /* suppress internal call-backs */
if(strncmp(str1, "cmd._", 5)) {
OrthoAddOutput(G, "PyMOL>");
OrthoAddOutput(G, str1);
OrthoNewLine(G, NULL, true);
if(WordMatch(G, str1, "quit", true) == 0) /* don't log quit */
PLog(G, str1, cPLog_pml);
}
PParse(G, str1);
} else if(str1[1] == ' ') { /* "_ command" suppresses echoing of command, but it is still logged */
if(WordMatch(G, str1 + 2, "quit", true) >= 0) /* don't log quit */
PLog(G, str1 + 2, cPLog_pml);
PParse(G, str1 + 2);
} else {
PParse(G, str1);
}
PUnlockAPIAsGlut(G);
}
}
PyObject *MainGetStringResult(const char *str)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
PyObject *result;
result = PyRun_String(str, Py_eval_input, G->P_inst->dict, G->P_inst->dict);
return (result);
}
void MainRunString(const char *str)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
PBlock(G);
PLockStatus(G);
PRunStringModule(G, str);
PUnlockStatus(G);
PUnblock(G);
}
void MainMovieCopyPrepare(int *width, int *height, int *length)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
if(PLockAPIAsGlut(G, true)) {
MovieCopyPrepare(G, width, height, length);
MovieSetRealtime(G, false);
PUnlockAPIAsGlut(G);
}
}
int MainMovieCopyFrame(int frame, int width, int height, int rowbytes, void *ptr)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
int result = false;
if(PLockAPIAsGlut(G, true)) {
result = MovieCopyFrame(G, frame, width, height, rowbytes, ptr);
PUnlockAPIAsGlut(G);
}
return result;
}
int MainMoviePurgeFrame(int frame)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
int result = false;
if(PLockAPIAsGlut(G, true)) {
result = MoviePurgeFrame(G, frame);
PUnlockAPIAsGlut(G);
}
return result;
}
void MainMovieCopyFinish(void)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
if(PLockAPIAsGlut(G, true)) {
MovieCopyFinish(G);
MovieSetRealtime(G, true);
PUnlockAPIAsGlut(G);
}
}
void MainFlushAsync(void)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
if(PLockAPIAsGlut(G, true)) {
PFlush(G);
PUnlockAPIAsGlut(G);
}
}
int MainCheckRedundantOpen(char *file)
{
int result = false;
#ifndef _PYMOL_NOPY
PyMOLGlobals *G = SingletonPyMOLGlobals;
PBlock(G);
result = PTruthCallStr(G->P_inst->cmd, "check_redundant_open", file);
PUnblock(G);
#endif
return result;
}
void MainSceneGetSize(int *width, int *height)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
if(PLockAPIAsGlut(G, true)) {
SceneGetImageSize(G, width, height);
PUnlockAPIAsGlut(G);
}
}
int MainSceneCopy(int width, int height, int rowbytes, void *ptr)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
int result = false;
if(PLockAPIAsGlut(G, true)) {
result = SceneCopyExternal(G, width, height, rowbytes, (unsigned char *) ptr, 0x1);
PUnlockAPIAsGlut(G);
}
return result;
}
PyObject *MainComplete(const char *str)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
PyObject *result = NULL;
result = PYOBJECT_CALLFUNCTION(G->P_inst->complete, "s", str);
return (result);
}
#endif
#else
void MainFree(void);
void MainReshape(int width, int height);
static void MainDrawLocked(void);
static void MainDrag(int x, int y);
static CPyMOL *PyMOLInstance = NULL; /* eliminate */
struct _CMain {
int IdleMode;
double IdleTime;
int IdleCount;
int Modifiers;
int FinalInitCounter, FinalInitTrigger, FinalInitDone;
int TheWindow;
int WindowIsVisible;
double ReshapeTime;
double DrawAfter, DrawDelay;
int DrawGovernorActive, DrawDeferred, DrawSignalled;
int DrawnFlag, DeferReshapeDeferral;
int MaximizeCheck;
CPyMOLOptions *OwnedOptions;
/* if Main owns a reference to a copy of the startup options that
needs to be freed upon shutdown to fully scrub the heap */
};
/* global options */
void MainOnExit(void);
static void MainPushValidContext(PyMOLGlobals * G)
{
PLockStatus(G);
PyMOL_PushValidContext(G->PyMOL);
PUnlockStatus(G);
}
static void MainPopValidContext(PyMOLGlobals * G)
{
PLockStatus(G);
PyMOL_PopValidContext(G->PyMOL);
PUnlockStatus(G);
}
static void DrawBlueLine(PyMOLGlobals * G)
{
if(G->Option->blue_line) {
GLint i;
unsigned long buffer;
GLint window_width, window_height;
window_width = G->Option->winX;
window_height = G->Option->winY;
glPushAttrib(GL_ALL_ATTRIB_BITS);
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
for(i = 0; i < 6; i++)
glDisable(GL_CLIP_PLANE0 + i);
glDisable(GL_COLOR_LOGIC_OP);
glDisable(GL_COLOR_MATERIAL);
glDisable(GL_DEPTH_TEST);
glDisable(GL_DITHER);
glDisable(GL_FOG);
glDisable(GL_LIGHTING);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_LINE_STIPPLE);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_STENCIL_TEST);
/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
#ifdef _PYMOL_OSX
/*glDisable(GL_SHARED_TEXTURE_PALETTE_EXT); */
glDisable(GL_TEXTURE_1D);
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_3D);
glDisable(GL_TEXTURE_CUBE_MAP);
glDisable(GL_TEXTURE_RECTANGLE_EXT);
glDisable(GL_VERTEX_PROGRAM_ARB);
#endif
/* END PROPRIETARY CODE SEGMENT */
for(buffer = GL_BACK_LEFT; buffer <= GL_BACK_RIGHT; buffer++) {
GLint matrixMode;
GLint vp[4];
OrthoDrawBuffer(G, buffer);
glGetIntegerv(GL_VIEWPORT, vp);
glViewport(0, 0, window_width, window_height);
glGetIntegerv(GL_MATRIX_MODE, &matrixMode);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glScalef(2.0f / window_width, -2.0f / window_height, 1.0f);
glTranslatef(-window_width / 2.0f, -window_height / 2.0f, 0.0f);
/* draw sync lines */
glColor3d(0.0f, 0.0f, 0.0f);
glBegin(GL_LINES); /* Draw a background line */
glVertex3f(0.0F, window_height - 0.5F, 0.0F);
glVertex3f((float) window_width, window_height - 0.5F, 0.0F);
glEnd();
glColor3d(0.0f, 0.0f, 1.0f);
glBegin(GL_LINES); /* Draw a line of the correct length (the cross
over is about 40% across the screen from the left */
glVertex3f(0.0f, window_height - 0.5f, 0.0f);
if(buffer == GL_BACK_LEFT)
glVertex3f(window_width * 0.30f, window_height - 0.5f, 0.0f);
else
glVertex3f(window_width * 0.80f, window_height - 0.5f, 0.0f);
glEnd();
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(matrixMode);
glViewport(vp[0], vp[1], vp[2], vp[3]);
}
glPopAttrib();
}
}
/*========================================================================*/
void MainOnExit(void)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
/*
here we enter not knowing anything about the current state...
so, no graceful exit is possible -- in fact under Window's we'll
crash unless we take the drastic way out
*/
if(G && !G->Terminating) {
G->Terminating = true;
printf(" PyMOL: abrupt program termination.\n");
/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
#ifdef WIN32
TerminateProcess(GetCurrentProcess(), 0); /* only way to avoid a crash */
#endif
/* END PROPRIETARY CODE SEGMENT */
exit(EXIT_SUCCESS);
}
}
/*========================================================================*/
int MainSavingUnderWhileIdle(void)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
CMain *I = G->Main;
return (I && (I->IdleMode > 3));
}
/*========================================================================*/
void MainSetWindowVisibility(int mode)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
G->Option->window_visible = mode;
}
/*========================================================================*/
static void MainDrag(int x, int y)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
CMain *I = G->Main;
if(PLockAPIAsGlut(G, false)) {
y = G->Option->winY - y;
PyMOL_Drag(PyMOLInstance, x, y, I->Modifiers);
if(PyMOL_GetRedisplay(PyMOLInstance, true)) {
if(G->HaveGUI) {
p_glutPostRedisplay();
}
}
I->IdleMode = 0;
PUnlockAPIAsGlut(G);
}
}
/*========================================================================*/
static void MainButton(int button, int state, int x, int y)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
int glMod;
CMain *I = G->Main;
#ifdef WIN32
// fix wheel x/y on Windows (PYMOL-2173)
switch(button) {
case P_GLUT_BUTTON_SCROLL_FORWARD:
case P_GLUT_BUTTON_SCROLL_BACKWARD:
x -= p_glutGet(P_GLUT_WINDOW_X);
y -= p_glutGet(P_GLUT_WINDOW_Y);
}
#endif
glMod = p_glutGetModifiers();
if(PLockAPIAsGlut(G, false)) {
I->IdleMode = 0; /* restore responsiveness */
if(PyMOL_GetPassive(PyMOLInstance, (button < 3) ? true : false)) {
MainDrag(x, y);
} else {
/* stay blocked here because Clicks->SexFrame->PParse */
y = G->Option->winY - y;
I->Modifiers = ((glMod & P_GLUT_ACTIVE_SHIFT) ? cOrthoSHIFT : 0) |
((glMod & P_GLUT_ACTIVE_CTRL) ? cOrthoCTRL : 0) |
((glMod & P_GLUT_ACTIVE_ALT) ? cOrthoALT : 0);
PyMOL_Button(PyMOLInstance, button, state, x, y, I->Modifiers);
}
PUnlockAPIAsGlut(G);
}
}
/*========================================================================*/
static void MainPassive(int x, int y)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
CMain *I = G->Main;
#define PASSIVE_EDGE 20
if(PyMOL_GetPassive(G->PyMOL, false)) { /* a harmless race condition -- we don't want
to slow Python down buy locking on passive
mouse motion */
if(PLockAPIAsGlut(G, false)) {
if((y < -PASSIVE_EDGE) || (x < -PASSIVE_EDGE) ||
(x > (G->Option->winX + PASSIVE_EDGE)) ||
(y > (G->Option->winY + PASSIVE_EDGE))) {
/* release passive drag if mouse leaves window...
[IF we continue to receive mouse events...] */
y = G->Option->winY - y;
PyMOL_Button(PyMOLInstance, P_GLUT_LEFT_BUTTON, P_GLUT_UP, x, y, I->Modifiers);
PyMOL_GetPassive(G->PyMOL, true); /* reset the flag */
} else {
y = G->Option->winY - y;
PyMOL_Drag(PyMOLInstance, x, y, I->Modifiers);
}
if(PyMOL_GetRedisplay(PyMOLInstance, true)) {
if(G->HaveGUI) {
p_glutPostRedisplay();
}
I->IdleMode = 0;
}
PUnlockAPIAsGlut(G);
}
}
}
/*========================================================================*/
static void MainDrawLocked(void)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
CMain *I = G->Main;
if(I->FinalInitTrigger) {
I->FinalInitTrigger = false;
#ifndef _PYMOL_NOPY
/* okay, on the way in, the API is locked but the interpreter is
running async, so we need to block it */
PBlock(G);
if(PyErr_Occurred())
PyErr_Print();
/* next, we need to let PyMOL know we have a valid context,
because some initializations, involve GL calls (such as going
into full-screen or stereo mode) */
if(G->HaveGUI)
MainPushValidContext(G);
/* restore working directory if asked to */
PRunStringModule(G,
"if 'PYMOL_WD' in os.environ: os.chdir(os.environ['PYMOL_WD'])");
if(PyErr_Occurred())
PyErr_Print();
/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
#ifdef _PYMOL_OSX
PRunStringModule(G,
"if os.getcwd()[-23:]=='.app/Contents/Resources': os.chdir('../../..')");
#endif
/* END PROPRIETARY CODE SEGMENT */
if(PyErr_Occurred())
PyErr_Print();
PXDecRef(PYOBJECT_CALLMETHOD(G->P_inst->obj, "launch_gui", "O", G->P_inst->obj));
if(PyErr_Occurred())
PyErr_Print();
PXDecRef(PYOBJECT_CALLMETHOD
(G->P_inst->obj, "adapt_to_hardware", "O", G->P_inst->obj));
if(PyErr_Occurred())
PyErr_Print();
if(G->Option->incentive_product) { /* perform incentive product initialization (if any) */
PyRun_SimpleString("try:\n import ipymol\nexcept:\n pass\n");
if(PyErr_Occurred())
PyErr_Print();
}
PXDecRef(PYOBJECT_CALLMETHOD(G->P_inst->obj, "exec_deferred", "O", G->P_inst->obj));
if(PyErr_Occurred())
PyErr_Print();
#ifdef _PYMOL_SHARP3D
/*PParse("load $TUT/1hpv.pdb;hide;show sticks;show surface;set surface_color,white;set transparency,0.5;stereo on"); */
/*PParse("stereo on");
PParse("wizard demo,cartoon"); */
#endif
if(G->HaveGUI)
MainPopValidContext(G);
PUnblock(G);
#endif
I->FinalInitDone = true;
}
PyMOL_Draw(PyMOLInstance);
if(G->HaveGUI) {
if(Feedback(G, FB_OpenGL, FB_Debugging)) {
PyMOLCheckOpenGLErr("During Rendering");
}
}
if(PyMOL_GetSwap(G->PyMOL, true)) {
if(!SettingGetGlobal_b(G, cSetting_suspend_updates))
if(G->HaveGUI) {
DrawBlueLine(G);
p_glutSwapBuffers();
}
}
}
static void MainDrawProgress(PyMOLGlobals * G)
{
int progress[PYMOL_PROGRESS_SIZE];
int update = false;
PBlock(G);
PLockStatus(G);
update = PyMOL_GetProgress(G->PyMOL, progress, true);
PUnlockStatus(G);
PUnblock(G);
/*
printf("show progress %d %d %d %d %d %d\n",
progress[0],progress[1],progress[2],
progress[3],progress[4],progress[5]); */
if(update &&
(progress[PYMOL_PROGRESS_SLOW] ||
progress[PYMOL_PROGRESS_MED] || progress[PYMOL_PROGRESS_FAST])) {
int offset;
int x = 0, y;
float black[3] = { 0, 0, 0 };
float white[3] = { 1, 1, 1 };
GLint ViewPort[4];
#define cBusyWidth 240
#define cBusyHeight 60
#define cBusyMargin 10
#define cBusyBar 10
#define cBusySpacing 15
glGetIntegerv(GL_VIEWPORT, ViewPort);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, ViewPort[2], 0, ViewPort[3], -100, 100);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glTranslatef(0.33F, 0.33F, 0.0F); /* this generates better
rasterization on macs */
glDisable(GL_ALPHA_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_FOG);
glDisable(GL_NORMALIZE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_COLOR_MATERIAL);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_DITHER);
glDisable(GL_BLEND);
{
int pass = 0;
int draw_both = SceneMustDrawBoth(G);
glClear(GL_DEPTH_BUFFER_BIT);
while(1) {
if(draw_both) {
if(!pass)
OrthoDrawBuffer(G, GL_FRONT_LEFT);
else
OrthoDrawBuffer(G, GL_FRONT_RIGHT);
} else {
OrthoDrawBuffer(G, GL_FRONT); /* draw into the front buffer */
}
glColor3fv(black);
glBegin(GL_POLYGON);
glVertex2i(0, ViewPort[3]);
glVertex2i(cBusyWidth, ViewPort[3]);
glVertex2i(cBusyWidth, ViewPort[3] - cBusyHeight);
glVertex2i(0, ViewPort[3] - cBusyHeight);
glVertex2i(0, ViewPort[3]); /* needed on old buggy Mesa */
glEnd();
y = ViewPort[3] - cBusyMargin;
glColor3fv(white);
/*
c=I->BusyMessage;
if(*c) {
TextSetColor(G,white);
TextSetPos2i(G,cBusyMargin,y-(cBusySpacing/2));
TextDrawStr(G,c);
y-=cBusySpacing;
}
*/
for(offset = 0; offset < PYMOL_PROGRESS_SIZE; offset += 2) {
if(progress[offset + 1]) {
glBegin(GL_LINE_LOOP);
glVertex2i(cBusyMargin, y);
glVertex2i(cBusyWidth - cBusyMargin, y);
glVertex2i(cBusyWidth - cBusyMargin, y - cBusyBar);
glVertex2i(cBusyMargin, y - cBusyBar);
glVertex2i(cBusyMargin, y); /* needed on old buggy Mesa */
glEnd();
glColor3fv(white);
x =
(progress[offset] * (cBusyWidth - 2 * cBusyMargin) / progress[offset + 1]) +
cBusyMargin;
glBegin(GL_POLYGON);
glVertex2i(cBusyMargin, y);
glVertex2i(x, y);
glVertex2i(x, y - cBusyBar);
glVertex2i(cBusyMargin, y - cBusyBar);
glVertex2i(cBusyMargin, y); /* needed on old buggy Mesa */
glEnd();
y -= cBusySpacing;
}
}
if(!draw_both)
break;
if(pass > 1)
break;
pass++;
}
glFlush();
glFinish();
if(draw_both)
OrthoDrawBuffer(G, GL_BACK_LEFT);
else
OrthoDrawBuffer(G, GL_BACK);
}
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
}
/*========================================================================*/
static void MainDraw(void)
{
int usec_sleep_after_draw = 0;
PyMOLGlobals *G = SingletonPyMOLGlobals;
PRINTFD(G, FB_Main)
" MainDraw: called.\n" ENDFD;
if(PLockAPIAsGlut(G, false)) {
CMain *I = G->Main;
if(I->DrawGovernorActive &&
(!I->DrawSignalled) && (UtilGetSeconds(G) < I->DrawAfter) && I->FinalInitDone) {
I->DrawDeferred = true;
} else {
int skip = false;
if(I->MaximizeCheck) {
{
/* is the window manager screwing us over??? */
int height = p_glutGet(P_GLUT_SCREEN_HEIGHT);
int width = p_glutGet(P_GLUT_SCREEN_WIDTH);
int actual_x = p_glutGet(P_GLUT_WINDOW_X);
int actual_y = p_glutGet(P_GLUT_WINDOW_Y);
I->MaximizeCheck = false;
if(actual_x != 0) {
width -= 2 * actual_x;
height -= actual_x;
}
if(actual_y != 0) {
height -= actual_y;
}
p_glutPositionWindow(0, 0);
p_glutReshapeWindow(width, height);
skip = true;
}
}
if((!skip) && (!I->DrawnFlag) && I->FinalInitDone) {
if(I->DeferReshapeDeferral > 0)
I->DeferReshapeDeferral--;
else {
double time_since_reshape = UtilGetSeconds(G) - I->ReshapeTime;
if(time_since_reshape < 0.05) {
/* defer screen updates while it's being actively resized */
skip = true;
}
}
}
if(!skip) {
MainDrawLocked();
I->DrawnFlag = true;
if(PyMOL_GetModalDraw(PyMOLInstance)) {
usec_sleep_after_draw = 10000; /* give other threads a chance to run */
}
} else {
PyMOL_NeedRedisplay(PyMOLInstance);
}
I->DrawAfter = UtilGetSeconds(G) + I->DrawDelay;
I->DrawSignalled = false;
I->DrawDeferred = false;
}
PUnlockAPIAsGlut(G);
} else { /* we're busy -- so try to display a progress indicator */
MainDrawProgress(G);
}
PRINTFD(G, FB_Main)
" MainDraw: completed.\n" ENDFD;
if(usec_sleep_after_draw && G) {
PSleepUnlocked(G, usec_sleep_after_draw);
}
}
/*========================================================================*/
static void MainKey(unsigned char k, int x, int y)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
CMain *I = G->Main;
int glMod;
glMod = p_glutGetModifiers();
#if defined(_PYMOL_OSX) && !defined(_PYMOL_LIB)
// MacOS GLUT.framework: swap delete and backspace
switch (k) {
case 0x08: k = 0x7f; break;
case 0x7f: k = 0x08; break;
}
#endif
PRINTFB(G, FB_Main, FB_Blather)
" MainKey: code:%d modifiers:0x%02x x:%d y:%d\n", k, glMod, x, y ENDFB(G);
if(PLockAPIAsGlut(G, false)) {
I->IdleMode = 0; /* restore responsiveness */
I->Modifiers = ((glMod & P_GLUT_ACTIVE_SHIFT) ? cOrthoSHIFT : 0) |
((glMod & P_GLUT_ACTIVE_CTRL) ? cOrthoCTRL : 0) |
((glMod & P_GLUT_ACTIVE_ALT) ? cOrthoALT : 0);
PyMOL_Key(PyMOLInstance, k, x, y, I->Modifiers);
PUnlockAPIAsGlut(G);
} else {
if((k == 8) || (k == 127)) { /* interrupt busy state (if possibele) */
PBlock(G);
PLockStatus(G);
PyMOL_SetInterrupt(G->PyMOL, true);
PUnlockStatus(G);
PUnblock(G);
}
}
}
/*========================================================================*/
static void MainSpecial(int k, int x, int y)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
CMain *I = G->Main;
int glMod;
PRINTFB(G, FB_Main, FB_Blather)
" MainSpecial: %d %d %d\n", k, x, y ENDFB(G);
glMod = p_glutGetModifiers();
if(PLockAPIAsGlut(G, false)) {
I->Modifiers = ((glMod & P_GLUT_ACTIVE_SHIFT) ? cOrthoSHIFT : 0) |
((glMod & P_GLUT_ACTIVE_CTRL) ? cOrthoCTRL : 0) |
((glMod & P_GLUT_ACTIVE_ALT) ? cOrthoALT : 0);
PyMOL_Special(PyMOLInstance, k, x, y, I->Modifiers);
PUnlockAPIAsGlut(G);
}
}
/* new window size or exposure */
/*========================================================================*/
void MainReshape(int width, int height)
{ /* called by Glut */
PyMOLGlobals *G = SingletonPyMOLGlobals;
if(G) {
CMain *I = G->Main;
I->ReshapeTime = (double) UtilGetSeconds(G);
I->DrawnFlag = false;
if (width==0 || height==0)
return;
if(PLockAPIAsGlut(G, true)) {
if(G->HaveGUI) {
glViewport(0, 0, (GLint) width, (GLint) height);
if((!PyMOLInstance) ||
(width != OrthoGetWidth(G)) || (height != OrthoGetHeight(G))) {
/* wipe the screen ASAP to prevent display of garbage... */
int draw_both = G->StereoCapable &&
((SceneGetStereo(G) == 1) ||
SettingGetGlobal_b(G, cSetting_stereo_double_pump_mono));
SceneGLClearColor(0.0, 0.0, 0.0, 1.0);
if(draw_both) {
OrthoDrawBuffer(G, GL_FRONT_LEFT);
glClear(GL_COLOR_BUFFER_BIT);
OrthoDrawBuffer(G, GL_FRONT_RIGHT);
glClear(GL_COLOR_BUFFER_BIT);
OrthoDrawBuffer(G, GL_BACK_LEFT);
glClear(GL_COLOR_BUFFER_BIT);
OrthoDrawBuffer(G, GL_BACK_RIGHT);
glClear(GL_COLOR_BUFFER_BIT);
} else {
OrthoDrawBuffer(G, GL_FRONT);
glClear(GL_COLOR_BUFFER_BIT);
OrthoDrawBuffer(G, GL_BACK);
glClear(GL_COLOR_BUFFER_BIT);
}
}
PyMOL_SwapBuffers(PyMOLInstance);
}
}
if(PyMOLInstance)
PyMOL_Reshape(PyMOLInstance, width, height, false);
PUnlockAPIAsGlut(G);
}
}
/*========================================================================*/
void MainDoReshape(int width, int height)
{ /* called internally */
int internal_feedback;
int force = false;
PyMOLGlobals *G = SingletonPyMOLGlobals;
if(G) {
/* if width and height are negative and we are in full screen, don't reshape window */
bool keep_fullscreen = (width < 0 && height < 0 && ExecutiveIsFullScreen(G));
/* if width is negative, force a reshape based on the current width */
if(width < 0) {
width = SceneGetBlock(G)->getWidth();
if(SettingGetGlobal_b(G, cSetting_internal_gui))
width += SettingGetGlobal_i(G, cSetting_internal_gui_width);
force = true;
}
/* if height is negative, force a reshape based on the current height */
if(height < 0) {
height = SceneGetBlock(G)->getHeight();
internal_feedback = SettingGetGlobal_i(G, cSetting_internal_feedback);
if(internal_feedback)
height += (internal_feedback - 1) * cOrthoLineHeight + cOrthoBottomSceneMargin;
if(SettingGetGlobal_b(G, cSetting_seq_view)
&& !SettingGetGlobal_b(G, cSetting_seq_view_overlay))
height += SeqGetHeight(G);
height += MovieGetPanelHeight(G);
force = true;
}
/* if we have a GUI, for a reshape event */
if(G->HaveGUI && G->ValidContext && width > 0 && height > 0) {
p_glutReshapeWindow(width, height);
glViewport(0, 0, (GLint) width, (GLint) height);
}
if((!width)||(!height)) {
int actual_width = width ? width : G->Option->winX;
int actual_height = height ? height : G->Option->winY;
PyMOL_Reshape(G->PyMOL, actual_width, actual_height, true);
} else {
PyMOL_Reshape(G->PyMOL, width, height, force);
if(G->Main) {
G->Main->DeferReshapeDeferral = 1;
}
/* do we need to become full-screen? */
if(keep_fullscreen) {
p_glutFullScreen();
}
}
}
}
/*========================================================================*/
static void MainInit(PyMOLGlobals * G)
{
CMain *I = (G->Main = Calloc(CMain, 1));
/* Data structure is zeroed on start...no need for explicit zero inits */
I->DeferReshapeDeferral = 1;
PyMOL_Start(PyMOLInstance);
// moved to PyMOL_DrawWithoutLock
// PyMOL_ConfigureShadersGL(PyMOLInstance);
PyMOL_SetSwapBuffersFn(PyMOLInstance, (PyMOLSwapBuffersFn *) p_glutSwapBuffers);
I->ReshapeTime = (I->IdleTime = UtilGetSeconds(G));
I->DrawGovernorActive = false;
I->DrawSignalled = true;
I->DrawDelay = 0.01; /* 100 FPS max */
I->DrawAfter = 0.0;
I->DrawDeferred = false;
}
/*========================================================================*/
void MainFree(void)
{
PyMOLGlobals *G = PyMOL_GetGlobals(PyMOLInstance); /* temporary -- will change */
CPyMOLOptions *owned_options = G->Main->OwnedOptions;
int show_message = G->Option->show_splash && !G->Option->quiet;
/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
#ifdef WIN32
int haveGUI = G->HaveGUI;
int theWindow = G->Main->TheWindow;
#endif
#ifdef _PYMOL_OSX
int game_mode = G->Option->game_mode;
int haveGUI = G->HaveGUI;
int theWindow = G->Main->TheWindow;
#endif
/* END PROPRIETARY CODE SEGMENT */
FreeP(G->Main);
if(owned_options)
PyMOLOptions_Free(owned_options); /* clean up launch options if we're supposed to */
if(show_message) {
printf(" PyMOL: normal program termination.\n");
}
/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
#ifdef WIN32
if(haveGUI)
p_glutDestroyWindow(theWindow);
TerminateProcess(GetCurrentProcess(), 0); /* only way to avoid a crash */
#endif
#ifdef _PYMOL_OSX
if(haveGUI) {
if(game_mode) {
p_glutLeaveGameMode();
/* force a full-screen refresh to eliminate garbage on screen
* NOTE that we currently have to patch Apple's GLUT to make this work */
p_glutInitWindowPosition(0, 0);
p_glutInitWindowSize(640, 480);
p_glutInitDisplayMode(P_GLUT_RGBA | P_GLUT_DEPTH | P_GLUT_DOUBLE);
if(p_glutGet(P_GLUT_DISPLAY_MODE_POSSIBLE)) {
theWindow = p_glutCreateWindow("PyMOL Viewer");
p_glutFullScreen();
p_glutDestroyWindow(theWindow);
}
} else
p_glutDestroyWindow(theWindow);
}
#endif
/* END PROPRIETARY CODE SEGMENT */
}
/*========================================================================*/
void MainRefreshNow(void)
{ /* should only be called by the master thread, with a locked API */
PyMOLGlobals *G = SingletonPyMOLGlobals;
CMain *I = G->Main;
if(PyMOL_GetSwap(G->PyMOL, true)) {
if(G->HaveGUI) {
DrawBlueLine(G);
p_glutSwapBuffers();
}
}
if(PyMOL_GetRedisplay(PyMOLInstance, true)) {
if(G->HaveGUI)
p_glutPostRedisplay();
else
MainDrawLocked();
I->IdleMode = 0;
}
}
/*========================================================================*/
#ifdef _PYMOL_SHARP3D
static int Sharp3DLastWindowX = -1000;
#endif
static void MainBusyIdle(void)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
/* This is one of the few places in the program where we can be sure
* that we have the "glut" thread...glut doesn't seem to be completely
* thread safe or rather thread consistent
*/
CMain *I = G->Main;
PRINTFD(G, FB_Main)
" MainBusyIdle: called.\n" ENDFD;
/* flush command and output queues */
/* PRINTFD(G,FB_Main)
" MainBusyIdle: entered, IdleMode %d\n",
I->IdleMode
ENDFD; */
if(PLockAPIAsGlut(G, false)) {
PRINTFD(G, FB_Main)
" MainBusyIdle: got lock.\n" ENDFD;
/* change window visibility & refresh, if necessary */
if(G->HaveGUI) {
if(I->WindowIsVisible != G->Option->window_visible) {
I->WindowIsVisible = G->Option->window_visible;
if(I->WindowIsVisible) {
p_glutShowWindow();
OrthoDirty(G);
} else {
p_glutHideWindow();
}
}
}
PRINTFD(G, FB_Main)
" MainBusyIdle: calling idle function.\n" ENDFD;
if(PyMOL_Idle(PyMOLInstance)) {
/* we did some work, so keep PyMOL responsive */
I->IdleMode = 1;
} else if(!I->IdleMode) {
I->IdleMode = 1;
} else if(I->IdleMode == 1) {
I->IdleMode = 2;
I->IdleTime = UtilGetSeconds(G);
}
PRINTFD(G, FB_Main)
" MainBusyIdle: swap check.\n" ENDFD;
if(PyMOL_GetSwap(G->PyMOL, true)) {
if(G->HaveGUI) {
DrawBlueLine(G);
p_glutSwapBuffers();
}
}
/* if the screen has become dirty, post a redisplay event, or if
we're running without a GUI, then call the draw routine (if we */
PRINTFD(G, FB_Main)
" MainBusyIdle: redisplay.\n" ENDFD;
if(PyMOL_GetRedisplay(PyMOLInstance, true)) {
if(G->HaveGUI)
p_glutPostRedisplay();
else
MainDrawLocked();
if(I->IdleMode > 1) {
I->IdleMode = 1;
}
}
PRINTFD(G, FB_Main)
" MainBusyIdle: redisplay.\n" ENDFD;
/* the following code enables PyMOL to avoid busy-idling
* even though we're using GLUT! */
#ifndef _PYMOL_WX_GLUT
/* however, don't spend any extra time sleeping in PYMOL if we're
running under wxPython though... */
switch (I->IdleMode) {
case 2: /* avoid racing the CPU */
if((UtilGetSeconds(G) - I->IdleTime) > (SettingGetGlobal_f(G, cSetting_idle_delay) / 5.0)) {
I->IdleMode = 3;
I->IdleTime = UtilGetSeconds(G);
}
break;
case 3:
if((UtilGetSeconds(G) - I->IdleTime) > (SettingGetGlobal_f(G, cSetting_idle_delay))) {
I->IdleMode = 4;
if(G->HaveGUI)
if(SettingGetGlobal_b(G, cSetting_cache_display)) {
p_glutPostRedisplay(); /* trigger caching of the current scene */
}
break;
}
}
#endif
PRINTFD(G, FB_Main)
" MainBusyIdle: unlocking.\n" ENDFD;
{
int control_idling = false;
if(I->IdleMode == 1) {
control_idling = ControlIdling(G);
}
PUnlockAPIAsGlut(G);
switch (I->IdleMode) {
case 4:
PSleepUnlocked(G, SettingGetGlobal_i(G, cSetting_slow_idle)); /* slow idle - save CPU cycles */
break;
case 3:
PSleepUnlocked(G, SettingGetGlobal_i(G, cSetting_fast_idle)); /* fast idle - more responsive */
break;
case 2:
PSleepUnlocked(G, SettingGetGlobal_i(G, cSetting_no_idle)); /* give Tcl/Tk a chance to run */
break;
case 1:
if(control_idling) {
PSleepUnlocked(G, SettingGetGlobal_i(G, cSetting_no_idle)); /* give Tcl/Tk a chance to run */
}
break;
default:
break;
}
}
/* run final initilization code for Python-based PyMOL implementations. */
#define FINAL_INIT_AT 10
if(I->FinalInitCounter < FINAL_INIT_AT) {
I->FinalInitCounter = I->FinalInitCounter + 1;
if(I->FinalInitCounter == FINAL_INIT_AT) {
I->FinalInitTrigger = true;
PyMOL_NeedRedisplay(PyMOLInstance);
}
}
/* when running in command-line mode, if we're not reading from
* standard input and if we're not keeping the thread alive, then
* we can have no further input. Therefore die. */
if(!G->HaveGUI) {
if(!(OrthoCommandWaiting(G) ||
PyMOL_GetModalDraw(G->PyMOL) ||
OrthoDeferredWaiting(G) || SettingGetGlobal_b(G, cSetting_keep_alive))) {
if((!G->Option->keep_thread_alive) &&
(!G->Option->read_stdin) && (I->FinalInitCounter >= FINAL_INIT_AT)) {
I->IdleCount++;
if(I->IdleCount == 10) {
if(PLockAPIAsGlut(G, true)) {
PParse(G, "_quit");
PFlush(G);
PUnlockAPIAsGlut(G);
}
}
}
} else {
I->IdleCount = 0;
}
}
{
int max_ups = SettingGetGlobal_i(G, cSetting_max_ups);
if(max_ups < 1) {
I->DrawGovernorActive = false;
if(I->DrawDeferred) {
p_glutPostRedisplay();
}
} else {
I->DrawDelay = 1.0 / max_ups;
I->DrawGovernorActive = true;
if(I->DrawDeferred) {
if(UtilGetSeconds(G) > I->DrawAfter) {
I->DrawSignalled = true;
}
if(I->DrawSignalled) {
I->DrawDeferred = false;
p_glutPostRedisplay();
}
}
}
}
} else {
PRINTFD(G, FB_Main)
" MainBusyIdle: lock not obtained...\n" ENDFD;
PSleepWhileBusy(G, 100000); /* 10 per second */
if(G->HaveGUI) {
PBlock(G);
PLockStatus(G);
if(PyMOL_GetProgressChanged(G->PyMOL, false))
p_glutPostRedisplay();
PUnlockStatus(G);
PUnblock(G);
}
}
PRINTFD(G, FB_Main)
" MainBusyIdle: leaving... IdleMode %d\n", I->IdleMode ENDFD;
}
void MainSetWindowPosition(PyMOLGlobals * G, int x, int y)
{
#ifdef _PYMOL_FINK
y -= 22; /* something is wrong with FinkGlut's window positioning... */
#endif
p_glutPositionWindow(x, y);
}
void MainSetWindowSize(PyMOLGlobals * G, int w, int h)
{
G->Main->DeferReshapeDeferral = 1;
p_glutReshapeWindow(w, h);
}
void MainMaximizeWindow(PyMOLGlobals * G)
{
int height = p_glutGet(P_GLUT_SCREEN_HEIGHT);
int width = p_glutGet(P_GLUT_SCREEN_WIDTH);
G->Main->DeferReshapeDeferral = 1;
G->Main->MaximizeCheck = true;
p_glutPositionWindow(0, 0);
p_glutReshapeWindow(width, height);
}
void MainCheckWindowFit(PyMOLGlobals * G)
{
CMain *I = G->Main;
if(G && G->Main) {
int height = p_glutGet(P_GLUT_SCREEN_HEIGHT);
int width = p_glutGet(P_GLUT_SCREEN_WIDTH);
int actual_x = p_glutGet(P_GLUT_WINDOW_X);
int actual_y = p_glutGet(P_GLUT_WINDOW_Y);
int actual_width = p_glutGet(P_GLUT_WINDOW_WIDTH);
int actual_height = p_glutGet(P_GLUT_WINDOW_HEIGHT);
int new_width = -1;
int new_height = -1;
I->DeferReshapeDeferral = 1;
if((actual_x + actual_width) > width)
new_width = (width - actual_x) - 5; /* allow room for decoration */
if((actual_y + actual_height) > height)
new_height = (height - actual_y) - 5; /* allow room for decoration */
if((new_width > 0) || (new_height > 0)) {
if(new_width < 0)
new_width = actual_width;
if(new_height < 0)
new_height = actual_height;
MainSetWindowSize(G, new_width, new_height);
}
}
}
/*========================================================================*/
/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
#ifdef WIN32
BOOL WINAPI HandlerRoutine(DWORD dwCtrlType /* control signal type */
)
{
switch (dwCtrlType) {
case CTRL_CLOSE_EVENT:
case CTRL_BREAK_EVENT:
case CTRL_C_EVENT:
TerminateProcess(GetCurrentProcess(), 0); /* only way to avoid a crash */
break;
}
return 1;
}
#endif
#ifdef _PYMOL_SHARP3D
void sharp3d_prepare_context(void);
#endif
static void launch(CPyMOLOptions * options, int own_the_options)
{
int multisample_mask = 0;
int theWindow = 0;
PyMOLGlobals *G = NULL;
PyMOLInstance = PyMOL_NewWithOptions(options);
G = PyMOL_GetGlobals(PyMOLInstance);
/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
#ifdef _MACPYMOL_XCODE
MacPyMOLOption = G->Option;
MacPyMOLReady = &G->Ready;
#endif
/* END PROPRIETARY CODE SEGMENT */
if(G->Option->multisample)
multisample_mask = P_GLUT_MULTISAMPLE;
/* if were running GLUT, then we have the ability to increase the
* size of the window in order to accomodate the context */
if(G->Option->internal_gui && (!G->Option->game_mode))
G->Option->winX += cOrthoRightSceneMargin;
if(G->Option->internal_feedback && (!G->Option->game_mode))
G->Option->winY +=
(G->Option->internal_feedback - 1) * cOrthoLineHeight + cOrthoBottomSceneMargin;
if(G->HaveGUI) {
#ifndef _PYMOL_OSX
atexit(MainOnExit); /* register callback to help prevent crashes
when GLUT spontaneously kills us */
#endif
/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
#ifdef WIN32
SetConsoleCtrlHandler(HandlerRoutine, // address of handler function
true // handler to add or remove
);
SetConsoleTitle(_T("PyMOL"));
#endif
#ifdef _PYMOL_SHARP3D
sharp3d_prepare_context();
#endif
int myArgc = 0;
char *myArgv[8] = {"pymol"};
p_glutInit(&myArgc, myArgv);
{
int display_mode_possible = false;
if(G->Option->stereo_mode > 1)
G->Option->force_stereo = 0;
switch (G->Option->force_stereo) {
case -1: /* force mono */
G->StereoCapable = 0;
break;
case 1: /* force quad buffer stereo (if possible) */
G->Option->stereo_mode = cStereo_quadbuffer;
case 0: /* default/autodetect */
#ifdef _PYMOL_SHARP3D
G->Option->stereo_mode = cStereo_stencil_custom;
#endif
switch (G->Option->stereo_mode) {
case cStereo_default:
case cStereo_quadbuffer:
p_glutInitDisplayMode(P_GLUT_RGBA | P_GLUT_DEPTH | multisample_mask |
P_GLUT_DOUBLE | P_GLUT_STEREO);
display_mode_possible = p_glutGet(P_GLUT_DISPLAY_MODE_POSSIBLE);
if(multisample_mask && (!display_mode_possible)) {
G->LaunchStatus |= cPyMOLGlobals_LaunchStatus_MultisampleFailed;
p_glutInitDisplayMode(P_GLUT_RGBA | P_GLUT_DEPTH | P_GLUT_DOUBLE |
P_GLUT_STEREO);
display_mode_possible = p_glutGet(P_GLUT_DISPLAY_MODE_POSSIBLE);
}
if(display_mode_possible) {
G->StereoCapable = 1;
} else if(G->Option->stereo_mode == cStereo_quadbuffer) {
G->LaunchStatus |= cPyMOLGlobals_LaunchStatus_StereoFailed;
}
break;
case cStereo_clone_dynamic:
p_glutInitDisplayMode(P_GLUT_RGBA | P_GLUT_DEPTH | P_GLUT_DOUBLE | P_GLUT_ACCUM
| P_GLUT_STEREO);
display_mode_possible = p_glutGet(P_GLUT_DISPLAY_MODE_POSSIBLE);
if(!display_mode_possible) {
G->LaunchStatus |= cPyMOLGlobals_LaunchStatus_StereoFailed;
G->Option->stereo_mode = 0;
} else {
G->StereoCapable = 1;
}
break;
case cStereo_dynamic:
p_glutInitDisplayMode(P_GLUT_RGBA | P_GLUT_DEPTH | P_GLUT_DOUBLE |
P_GLUT_ACCUM);
display_mode_possible = p_glutGet(P_GLUT_DISPLAY_MODE_POSSIBLE);
if(!display_mode_possible) {
G->LaunchStatus |= cPyMOLGlobals_LaunchStatus_StereoFailed;
G->Option->stereo_mode = 0;
}
break;
case cStereo_stencil_by_row:
case cStereo_stencil_by_column:
case cStereo_stencil_checkerboard:
case cStereo_stencil_custom:
p_glutInitDisplayMode(P_GLUT_RGBA | P_GLUT_DEPTH | P_GLUT_DOUBLE |
P_GLUT_STENCIL);
display_mode_possible = p_glutGet(P_GLUT_DISPLAY_MODE_POSSIBLE);
if(!display_mode_possible) {
G->LaunchStatus |= cPyMOLGlobals_LaunchStatus_StereoFailed;
G->Option->stereo_mode = 0;
}
break;
case cStereo_anaglyph: /* nothing special required for anaglyph */
G->StereoCapable = 1;
break;
default: /* fall through */
break;
}
break;
}
/* fallback behavior */
if(!display_mode_possible) {
G->LaunchStatus &= ~cPyMOLGlobals_LaunchStatus_MultisampleFailed;
p_glutInitDisplayMode(P_GLUT_RGBA | P_GLUT_DEPTH | multisample_mask |
P_GLUT_DOUBLE);
display_mode_possible = p_glutGet(P_GLUT_DISPLAY_MODE_POSSIBLE);
G->StereoCapable = 0;
}
if(multisample_mask && (!display_mode_possible)) {
G->LaunchStatus |= cPyMOLGlobals_LaunchStatus_MultisampleFailed;
p_glutInitDisplayMode(P_GLUT_RGBA | P_GLUT_DEPTH | P_GLUT_DOUBLE);
display_mode_possible = p_glutGet(P_GLUT_DISPLAY_MODE_POSSIBLE);
G->StereoCapable = 0;
}
}
if(!G->Option->game_mode) {
if((G->Option->winPX > -10000) && (G->Option->winPY > -10000)) {
#ifndef _PYMOL_FINK
p_glutInitWindowPosition(G->Option->winPX, G->Option->winPY);
#else
p_glutInitWindowPosition(G->Option->winPX, G->Option->winPY - 22); /* somethings wrong with FinkGlut's window positioning... */
#endif
}
p_glutInitWindowSize(G->Option->winX, G->Option->winY);
theWindow = p_glutCreateWindow("PyMOL Viewer");
if(G->Option->full_screen) {
p_glutFullScreen();
}
if(G->Option->window_visible) {
p_glutShowWindow();
} else {
p_glutHideWindow();
}
} else {
char str[255];
sprintf(str, "%dx%d:32@120", G->Option->winX, G->Option->winY);
p_glutGameModeString(str);
p_glutEnterGameMode();
}
}
#ifdef _PYMOL_SHARP3D
/* Setup OpenGL */
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
#endif
MainInit(G);
if(own_the_options)
G->Main->OwnedOptions = options;
/* make sure we can clean up these options later if we've been asked to do so */
{
CMain *I = G->Main;
I->TheWindow = theWindow;
PInit(G, true);
#ifdef _PYMOL_SHARP3D
SettingSetGlobal_f(G, cSetting_stereo_shift, 2.5); /* increase strength */
#endif
if(G->HaveGUI) {
p_glutDisplayFunc(MainDraw);
p_glutReshapeFunc(MainReshape);
p_glutKeyboardFunc(MainKey);
p_glutMouseFunc(MainButton);
p_glutMotionFunc(MainDrag);
p_glutPassiveMotionFunc(MainPassive);
p_glutSpecialFunc(MainSpecial);
p_glutIdleFunc(MainBusyIdle);
}
PUnblock(G);
if(G->HaveGUI) {
if(!I->WindowIsVisible)
MainReshape(G->Option->winX, G->Option->winY);
I->IdleMode = 3;
p_glutMainLoop(); /* never returns with traditional GLUT implementation */
PBlock(G); /* if we've gotten here, then we're heading back to Python... */
} else {
SceneSetCardInfo(G, "none", "ray trace only", "none");
if(G->Option->show_splash && !G->Option->quiet)
printf(" Command mode. No graphics front end.\n");
MainReshape(G->Option->winX, G->Option->winY);
MainDraw(); /* for command line processing */
while(1) {
MainBusyIdle();
MainDraw();
}
}
}
}
/*========================================================================*/
static int main_common(void);
static int decoy_input_hook(void) { return 0; }
int main_exec(int argc, char **argv)
{
PyMOLGlobals *G = SingletonPyMOLGlobals;
fflush(stdout);
PSetupEmbedded(G, argc, argv);
return PyRun_SimpleString(
"import pymol\n"
"pymol.launch()\n");
}
int main_shared(int block_input_hook)
{
if(block_input_hook)
PyOS_InputHook = decoy_input_hook;
#ifdef _DRI_WORKAROUND
dlopen("libGL.so.1", RTLD_LAZY | RTLD_GLOBAL);
#endif
return main_common();
}
static int main_common(void)
{
{ /* no matter how PyMOL was built, we always come through here... */
CPyMOLOptions *options = PyMOLOptions_New();
if(options) {
PGetOptions(options);
launch(options, true);
/* this only returns when PyMOL is not running under GLUT */
}
}
return 0;
}
#endif
/*========================================================================*/
PyObject *MainAsPyList(PyMOLGlobals *G)
{
#ifdef _PYMOL_NOPY
return NULL;
#else
PyObject *result = NULL;
int width, height;
result = PyList_New(2);
width = SceneGetBlock(G)->getWidth();
height = SceneGetBlock(G)->getHeight();
if(SettingGetGlobal_b(G, cSetting_seq_view)
&& !SettingGetGlobal_b(G, cSetting_seq_view_overlay))
height += SeqGetHeight(G);
PyList_SetItem(result, 0, PyInt_FromLong(width));
PyList_SetItem(result, 1, PyInt_FromLong(height));
return (PConvAutoNone(result));
#endif
}
int MainFromPyList(PyMOLGlobals *G, PyObject * list)
{
#ifdef _PYMOL_NOPY
return 0;
#else
int ok = true;
int win_x, win_y;
int ll = 0;
OrthoLineType buffer;
if(ok)
ok = (list != NULL);
if(ok)
ok = PyList_Check(list);
if(ok)
ll = PyList_Size(list);
if(ok && (ll >= 2)) {
if(!G->Option->presentation &&
!G->Option->full_screen &&
!ExecutiveIsFullScreen(G)) {
if(ok)
ok = PConvPyIntToInt(PyList_GetItem(list, 0), &win_x);
if(ok)
ok = PConvPyIntToInt(PyList_GetItem(list, 1), &win_y);
/* BlockGetSize(SceneGetBlock(G),&win_x,&win_y); * so how did this get into 0.98beta29? */
if(ok) {
sprintf(buffer, "viewport %d, %d", win_x, win_y);
PParse(G, buffer);
}
}
}
return (ok);
#endif
}