Extra error checking, commenting, and some cleanups.

git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@23 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2002-01-10 19:22:58 +00:00
parent 0a10a2d475
commit b463645966
1 changed files with 87 additions and 52 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: mainX11.cxx,v 1.2 2002-01-08 17:11:32 stephena Exp $ // $Id: mainX11.cxx,v 1.3 2002-01-10 19:22:58 stephena Exp $
//============================================================================ //============================================================================
#include <assert.h> #include <assert.h>
@ -67,14 +67,16 @@ Window theWindow;
Colormap thePrivateColormap; Colormap thePrivateColormap;
Cursor normalCursor; Cursor normalCursor;
Cursor blankCursor; Cursor blankCursor;
uInt32 eventMask;
// A graphic context for each of the 2600's colors // A graphic context for each of the 2600's colors
GC theGCTable[256]; GC theGCTable[256];
// function prototypes // function prototypes
void setupDisplay(); bool setupDisplay();
void setupJoystick(); bool setupJoystick();
void createCursors(); bool createCursors();
void cleanup();
void updateDisplay(MediaSource& mediaSource); void updateDisplay(MediaSource& mediaSource);
void handleEvents(); void handleEvents();
@ -230,9 +232,10 @@ uInt32 thePaddleMode = 0;
/** /**
This routine should be called once the console is created to setup This routine should be called once the console is created to setup
the X11 connection and open a window for us to use the X11 connection and open a window for us to use. Return false if any
operation fails, otherwise return true.
*/ */
void setupDisplay() bool setupDisplay()
{ {
// Open a connection to the X server // Open a connection to the X server
if(theDisplayName == "") if(theDisplayName == "")
@ -243,8 +246,8 @@ void setupDisplay()
// Verify that the connection was made // Verify that the connection was made
if(theDisplay == NULL) if(theDisplay == NULL)
{ {
cerr << "ERROR: Cannot open X Windows display...\n"; cerr << "ERROR: Couldn't open X Windows display...\n";
exit(1); return false;
} }
theScreen = DefaultScreen(theDisplay); theScreen = DefaultScreen(theDisplay);
@ -284,10 +287,16 @@ void setupDisplay()
theWindow = XCreateSimpleWindow(theDisplay, rootWindow, 0, 0, theWindow = XCreateSimpleWindow(theDisplay, rootWindow, 0, 0,
width, height, CopyFromParent, CopyFromParent, width, height, CopyFromParent, CopyFromParent,
BlackPixel(theDisplay, theScreen)); BlackPixel(theDisplay, theScreen));
if(!theWindow)
return false;
// Create normal and blank cursors. This must be called AFTER // Create normal and blank cursors. This must be called AFTER
// theDisplay and theWindow are defined // theDisplay and theWindow are defined
createCursors(); if(!createCursors())
{
cerr << "ERROR: Couldn't create cursors.\n";
return false;
}
// If requested create a private colormap for the window // If requested create a private colormap for the window
if(theUsePrivateColormapFlag) if(theUsePrivateColormapFlag)
@ -305,8 +314,7 @@ void setupDisplay()
char name[512]; char name[512];
sprintf(name, "Stella: \"%s\"", sprintf(name, "Stella: \"%s\"",
theConsole->properties().get("Cartridge.Name").c_str()); theConsole->properties().get("Cartridge.Name").c_str());
XmbSetWMProperties(theDisplay, theWindow, name, "stella", 0, 0, &hints, None, None);
XSetStandardProperties(theDisplay, theWindow, name, "xstella", None, 0, 0, &hints);
// Allocate colors in the default colormap // Allocate colors in the default colormap
const uInt32* palette = theConsole->mediaSource().palette(); const uInt32* palette = theConsole->mediaSource().palette();
@ -349,14 +357,15 @@ void setupDisplay()
XNextEvent(theDisplay, &event); XNextEvent(theDisplay, &event);
} while (event.type != Expose); } while (event.type != Expose);
uInt32 mask = ExposureMask | KeyPressMask | KeyReleaseMask | PropertyChangeMask; eventMask = ExposureMask | KeyPressMask | KeyReleaseMask | PropertyChangeMask |
StructureNotifyMask;
// If we're using the mouse for paddle emulation then enable mouse events // If we're using the mouse for paddle emulation then enable mouse events
if(((theConsole->properties().get("Controller.Left") == "Paddles") || if(((theConsole->properties().get("Controller.Left") == "Paddles") ||
(theConsole->properties().get("Controller.Right") == "Paddles")) (theConsole->properties().get("Controller.Right") == "Paddles"))
&& (thePaddleMode != 4)) && (thePaddleMode != 4))
{ {
mask |= (PointerMotionMask | ButtonPressMask | ButtonReleaseMask); eventMask |= (PointerMotionMask | ButtonPressMask | ButtonReleaseMask);
} }
// Keep mouse in game window if grabmouse is selected // Keep mouse in game window if grabmouse is selected
@ -365,7 +374,7 @@ void setupDisplay()
// Show or hide the cursor depending on the 'hidecursor' argument // Show or hide the cursor depending on the 'hidecursor' argument
showCursor(!theHideCursorFlag); showCursor(!theHideCursorFlag);
XSelectInput(theDisplay, theWindow, mask); XSelectInput(theDisplay, theWindow, eventMask);
// If imlib snapshots are enabled, set up some imlib stuff // If imlib snapshots are enabled, set up some imlib stuff
#ifdef IMLIB2_SNAPSHOT #ifdef IMLIB2_SNAPSHOT
@ -378,19 +387,23 @@ void setupDisplay()
else else
imlib_context_set_colormap(DefaultColormap(theDisplay, theScreen)); imlib_context_set_colormap(DefaultColormap(theDisplay, theScreen));
#endif #endif
return true;
} }
/** /**
This routine should be called once setupDisplay is called This routine should be called once setupDisplay is called
to create the joystick stuff to create the joystick stuff
*/ */
void setupJoystick() bool setupJoystick()
{ {
#ifdef LINUX_JOYSTICK #ifdef LINUX_JOYSTICK
// Open the joystick devices // Open the joystick devices
theLeftJoystickFd = open("/dev/js0", O_RDONLY | O_NONBLOCK); theLeftJoystickFd = open("/dev/js0", O_RDONLY | O_NONBLOCK);
theRightJoystickFd = open("/dev/js1", O_RDONLY | O_NONBLOCK); theRightJoystickFd = open("/dev/js1", O_RDONLY | O_NONBLOCK);
#endif #endif
return true;
} }
/** /**
@ -537,9 +550,7 @@ void handleEvents()
{ {
XEvent event; XEvent event;
while(XCheckWindowEvent(theDisplay, theWindow, while(XCheckWindowEvent(theDisplay, theWindow, eventMask, &event))
ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask |
ButtonReleaseMask | PointerMotionMask | PropertyChangeMask, &event))
{ {
char buffer[20]; char buffer[20];
KeySym key; KeySym key;
@ -644,19 +655,17 @@ void handleEvents()
{ {
theRedrawEntireFrameFlag = true; theRedrawEntireFrameFlag = true;
} }
else if(event.type == PropertyNotify) else if(event.type == UnmapNotify)
{
XWindowAttributes attr;
XGetWindowAttributes(theDisplay, theWindow, &attr);
if(attr.map_state == IsUnmapped)
{ {
if(!thePauseIndicator) if(!thePauseIndicator)
{ {
togglePause(); // togglePause();
cerr << "todo: Pause on minimize.\n"; cerr << "todo: Pause on minimize.\n";
} }
} }
else if(event.type == ClientMessage)
{
cerr << "todo: detect and deal with WM_DELETE_WINDOW message\n";
} }
} }
@ -840,7 +849,7 @@ void resizeWindow(int mode)
theRedrawEntireFrameFlag = true; theRedrawEntireFrameFlag = true;
// A resize may mean that the window is no longer centered // A resize probably means that the window is no longer centered
isCentered = false; isCentered = false;
if(theCenterWindowFlag) if(theCenterWindowFlag)
@ -939,12 +948,12 @@ void grabMouse(bool grab)
/** /**
Creates a normal and blank cursor which may be needed if hidecursor or Creates a normal and blank cursor which may be needed if hidecursor or
fullscreen is toggled. fullscreen is toggled. Return false on any errors, otherwise true.
*/ */
void createCursors() bool createCursors()
{ {
if(!theDisplay || !theWindow) if(!theDisplay || !theWindow)
return; return false;
Pixmap cursormask; Pixmap cursormask;
XGCValues xgc; XGCValues xgc;
@ -961,11 +970,18 @@ void createCursors()
dummycolour.flags = 04; dummycolour.flags = 04;
blankCursor = XCreatePixmapCursor(theDisplay, cursormask, cursormask, blankCursor = XCreatePixmapCursor(theDisplay, cursormask, cursormask,
&dummycolour, &dummycolour, 0, 0); &dummycolour, &dummycolour, 0, 0);
if(!blankCursor)
return false;
XFreeGC(theDisplay, gc); XFreeGC(theDisplay, gc);
XFreePixmap(theDisplay, cursormask); XFreePixmap(theDisplay, cursormask);
// Now create the normal cursor // Now create the normal cursor
normalCursor = XCreateFontCursor(theDisplay, XC_left_ptr); normalCursor = XCreateFontCursor(theDisplay, XC_left_ptr);
if(!normalCursor)
return false;
return true;
} }
/** /**
@ -1381,6 +1397,34 @@ void parseRCOptions(istream& in)
} }
} }
/**
Does general cleanup in case any operation failed (or at end of program).
*/
void cleanup()
{
if(theConsole)
delete theConsole;
if(normalCursor)
XFreeCursor(theDisplay, normalCursor);
if(blankCursor)
XFreeCursor(theDisplay, blankCursor);
// If we're using a private colormap then let's free it to be safe
if(theUsePrivateColormapFlag && theDisplay)
{
XFreeColormap(theDisplay, thePrivateColormap);
}
#ifdef LINUX_JOYSTICK
// Close the joystick devices
if(theLeftJoystickFd)
close(theLeftJoystickFd);
if(theRightJoystickFd)
close(theRightJoystickFd);
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
@ -1424,8 +1468,16 @@ int main(int argc, char* argv[])
delete[] image; delete[] image;
// Setup X window and joysticks // Setup X window and joysticks
setupDisplay(); if(!setupDisplay())
setupJoystick(); {
cerr << "ERROR: Couldn't set up display.\n";
cleanup();
}
if(!setupJoystick())
{
cerr << "ERROR: Couldn't set up joysticks.\n";
cleanup();
}
// Get the starting time in case we need to print statistics // Get the starting time in case we need to print statistics
timeval startingTime; timeval startingTime;
@ -1488,22 +1540,5 @@ int main(int argc, char* argv[])
} }
// Cleanup time ... // Cleanup time ...
delete theConsole; cleanup();
XFreeCursor(theDisplay, normalCursor);
XFreeCursor(theDisplay, blankCursor);
// If we're using a private colormap then let's free it to be safe
if(theUsePrivateColormapFlag)
{
XFreeColormap(theDisplay, thePrivateColormap);
}
#ifdef LINUX_JOYSTICK
// Close the joystick devices
if(theLeftJoystickFd)
close(theLeftJoystickFd);
if(theRightJoystickFd)
close(theRightJoystickFd);
#endif
} }