events.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           mousesdl.cpp  -  description
00003                              -------------------
00004     begin                : Sun Dec 19 1999
00005     copyright            : (C) 1999 by Martin Bickel
00006     email                : bickel@asc-hq.org
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 
00019 
00020 #include <queue>
00021 #include <SDL.h>
00022 #include <SDL_thread.h>
00023 
00024 #include "ctype.h"
00025 
00026 #include "../events.h"
00027 #include "../stack.h"
00028 #include "../basegfx.h"
00029 #include "../global.h"
00030 // #include "keysymbols.h"
00031 #include "../errors.h"
00032 #include "../util/messaginghub.h"
00033 #include "graphicsqueue.h"
00034 
00035 volatile tmousesettings mouseparams;
00036 
00037 SDL_mutex* keyboardmutex = NULL;
00038 SDL_mutex* eventHandlingMutex = NULL;
00039 SDL_mutex* eventQueueMutex = NULL;
00040 SDL_mutex* graphicsQueueMutex = NULL;
00041 
00042 queue<tkey>   keybuffer_sym;
00043 queue<Uint32> keybuffer_prnt;
00044 queue<SDL_Event> eventQueue;
00045 bool _queueEvents = true;
00046 bool _fillLegacyEventStructures = false;
00047 
00048 volatile bool eventThreadRunning = false;
00049 
00050 
00051 std::list<GraphicsQueueOperation*> graphicsQueue;
00052 
00053 int exitprogram = 0;
00054 
00055 
00056 /***************************************************************************
00057  *                                                                         *
00058  *   Mouse handling routines                                               *
00059  *                                                                         *
00060  ***************************************************************************/
00061 
00062 
00063 bool redrawScreen = false;
00064 
00065 const bool trueflag = true;
00066 
00067 const bool* mouseUpdateFlag = &trueflag;
00068 
00069 void setMouseUpdateFlag( const bool* flag )
00070 {
00071    mouseUpdateFlag = flag;
00072 }
00073 
00074 
00075 void mousevisible( int an)
00076 {}
00077 
00078 
00079 int getmousestatus ()
00080 {
00081    return 2;
00082 }
00083 
00084 int mouseTranslate ( int m)
00085 {
00086 
00087    const int mousetranslate[3] = {
00088       0, 2,1
00089    } ;  // in DOS  right button is 1 and center is 2
00090 
00091    if ( m >= 3 )
00092       return m;
00093    else
00094       return mousetranslate[m];
00095 }
00096 
00097 
00098 
00099 void setmouseposition ( int x, int y )
00100 {}
00101 
00102 
00103 
00104 void setnewmousepointer ( void* picture, int hotspotx, int hotspoty )
00105 {}
00106 
00107 
00108 int mouseinrect ( int x1, int y1, int x2, int y2 )
00109 {
00110    if ( mouseparams.x >= x1  && mouseparams.y >= y1  && mouseparams.x <= x2 && mouseparams.y <= y2 )
00111       return 1;
00112    else
00113       return 0;
00114 }
00115 
00116 int mouseinrect ( const tmouserect* rect )
00117 {
00118    if ( mouseparams.x >= rect->x1  && mouseparams.y >= rect->y1  && mouseparams.x <= rect->x2 && mouseparams.y <= rect->y2 )
00119       return 1;
00120    else
00121       return 0;
00122 }
00123 
00124 
00125 
00126 tmouserect tmouserect :: operator+ ( const tmouserect& b ) const
00127 {
00128    tmouserect c;
00129    c.x1 = x1 + b.x1;
00130    c.y1 = y1 + b.y1;
00131    c.x2 = x2 + b.x2;
00132    c.y2 = y2 + b.y2;
00133    return c;
00134 }
00135 
00136 
00137 
00138 /***************************************************************************
00139  *                                                                         *
00140  *   Keyboard handling routines                                            *
00141  *                                                                         *
00142  ***************************************************************************/
00143 
00144 
00145 
00146 int keypress( void )
00147 {
00148    int result = 0;
00149    int r = SDL_mutexP ( keyboardmutex );
00150    if ( !r ) {
00151       result = !keybuffer_sym.empty ( );
00152       r = SDL_mutexV ( keyboardmutex );
00153    }
00154    return result;
00155 }
00156 
00157 void getkeysyms ( tkey* keysym, int* keyprnt )
00158 {
00159    int found = 0;
00160    do {
00161       int r = SDL_mutexP ( keyboardmutex );
00162       if ( !r ) {
00163          if ( !keybuffer_prnt.empty() ) {
00164             *keysym = keybuffer_sym.front();
00165             *keyprnt = keybuffer_prnt.front();
00166             keybuffer_sym.pop();
00167             keybuffer_prnt.pop();
00168             found++;
00169          }
00170          r = SDL_mutexV ( keyboardmutex );
00171       }
00172       if (!found ) {
00173          int t = ticker;
00174          while ( t + 5 > ticker )
00175             releasetimeslice();
00176       }
00177    } while ( !found );
00178 }
00179 
00180 
00181 char  skeypress(tkey keynr)
00182 {
00183    Uint8 *keystate = SDL_GetKeyState ( NULL );
00184    return keystate[ keynr ];
00185 }
00186 
00187 bool isKeyPressed(SDLKey key)
00188 {
00189    Uint8 *keystate = SDL_GetKeyState ( NULL );
00190    return keystate[ key ];
00191 }
00192 
00193 
00194 
00195 void wait(void)
00196 {}
00197 
00198 
00199 
00200 tkey char2key(int c )
00201 {
00202    if ( c < 128 )
00203       return tolower(c);
00204    else
00205       return ct_invvalue;
00206 }
00207 
00208 
00209 int  releasetimeslice( void )
00210 {
00211    SDL_Delay(10);
00212    if ( redrawScreen ) {
00213       redrawScreen = false;
00214       copy2screen();
00215    }
00216    return 0;
00217 }
00218 
00219 
00220 
00221 
00222 
00223 
00224 
00225 
00226 /***************************************************************************
00227  *                                                                         *
00228  *   Timer routines                                                        *
00229  *                                                                         *
00230  ***************************************************************************/
00231 
00232 
00233 
00234 volatile int  ticker = 0; // was static, but I think this needs to be global somewhere
00235 
00236 void ndelay(int time)
00237 {
00238    long l;
00239 
00240    l = ticker;
00241    do {
00242       releasetimeslice();
00243    }  while (ticker - l > time);
00244 }
00245 
00246 
00247 int tticker = 0;
00248 
00249 void starttimer(void)
00250 {
00251    tticker = ticker;
00252 }
00253 
00254 char time_elapsed(int time)
00255 {
00256    if (tticker + time <= ticker) return 1;
00257    else return 0;
00258 }
00259 
00260 
00261 
00262 /***************************************************************************
00263  *                                                                         *
00264  *   Event handling routines                                               *
00265  *                                                                         *
00266  ***************************************************************************/
00267 
00268 #include <iostream>
00269 
00270 volatile int closeEventThread = 0;
00271 
00272 const int keyTranslationNum = 7;
00273 int keyTranslation[keyTranslationNum][2] = { { 228, 132 }, //   "a
00274                                              { 246, 148 }, //   "o
00275                                              { 252, 129 }, //   "u
00276                                              { 196, 142 }, //   "A
00277                                              { 214, 153 }, //   "O
00278                                              { 220, 154 }, //   "U
00279                                              { 223, 225 } }; // sz
00280 
00281                                              
00282 EventHandlingMutex::EventHandlingMutex()
00283 {
00284    SDL_mutexP ( eventHandlingMutex );
00285 }
00286 
00287 EventHandlingMutex::~EventHandlingMutex()
00288 {
00289    SDL_mutexV ( eventHandlingMutex );
00290 }
00291                                              
00292                                              
00293 int processEvents ( )
00294 {
00295    EventHandlingMutex ehm;
00296          
00297    SDL_Event event;
00298    int result;
00299    if ( SDL_PollEvent ( &event ) == 1) {
00300       if ( _fillLegacyEventStructures ) {
00301         switch ( event.type ) {
00302          case SDL_MOUSEBUTTONUP:
00303          case SDL_MOUSEBUTTONDOWN:
00304             {
00305                int taste = mouseTranslate(event.button.button - 1);
00306                int state = event.button.type == SDL_MOUSEBUTTONDOWN;
00307                if ( state )
00308                   mouseparams.taste |= (1 << taste);
00309                else
00310                   mouseparams.taste &= ~(1 << taste);
00311                mouseparams.x = event.button.x;
00312                mouseparams.y = event.button.y;
00313             }
00314             break;
00315 
00316          case SDL_MOUSEMOTION:
00317             {
00318                mouseparams.x = event.motion.x;
00319                mouseparams.y = event.motion.y;
00320                mouseparams.x1 = event.motion.x;
00321                mouseparams.y1 = event.motion.y;
00322                mouseparams.taste = 0;
00323                for ( int i = 0; i < 3; i++ )
00324                   if ( event.motion.state & (1 << i) )
00325                      mouseparams.taste |= 1 << mouseTranslate(i);
00326             }
00327             break;
00328          case SDL_KEYDOWN:
00329             {
00330                int r = SDL_mutexP ( keyboardmutex );
00331                if ( !r ) {
00332                   tkey key = event.key.keysym.sym;
00333                   if ( event.key.keysym.mod & KMOD_ALT )
00334                      key |= ct_altp;
00335                   if ( event.key.keysym.mod & KMOD_CTRL )
00336                      key |= ct_stp;
00337                   if ( event.key.keysym.mod & KMOD_SHIFT )
00338                      key |= ct_shp;
00339                   keybuffer_sym.push ( key );
00340 
00341                   int newsym = event.key.keysym.unicode;
00342                   for ( int i = 0; i < keyTranslationNum; i++ )
00343                      if ( event.key.keysym.unicode == keyTranslation[i][0] )
00344                         newsym = keyTranslation[i][1];
00345                   keybuffer_prnt.push ( newsym );
00346                   r = SDL_mutexV ( keyboardmutex );
00347                }
00348             }
00349             break;
00350          case SDL_KEYUP:
00351          {}
00352             break;
00353 
00354          case SDL_QUIT:
00355             exitprogram = 1;
00356             break;
00357 #ifdef _WIN32_
00358          case SDL_ACTIVEEVENT: 
00359             redrawScreen = true;
00360             break;
00361 #endif
00362         } 
00363       } else {
00364 #ifdef _WIN32_
00365          if ( event.type  == SDL_ACTIVEEVENT ) {
00366             queueOperation( new UpdateRectOp( SDL_GetVideoSurface(), 0,0,0,0), false, true );
00367          }
00368 #endif
00369 
00370       }
00371       result = 1;
00372       if ( _queueEvents ) {
00373          SDL_mutexP( eventQueueMutex );
00374          eventQueue.push ( event );
00375          SDL_mutexV( eventQueueMutex );
00376       }
00377 
00378 
00379    } else
00380       result = 0;
00381 
00382    return result;
00383 }
00384 
00385 #if defined(_WIN32_) || defined(__APPLE__)
00386 #define FirstThreadEvents 1
00387 #endif
00388 
00389 bool syncGraphics = true;
00390 
00391 
00392 SigC::Signal1<void,const SDL_Surface*> postScreenUpdate;
00393 
00394 void queueOperation( GraphicsQueueOperation* gqo, bool wait, bool forceAsync )
00395 {
00396    if ( !eventThreadRunning ) {
00397       gqo->execute();
00398       delete gqo;
00399       return;
00400    }
00401 
00402    SDL_mutexP( graphicsQueueMutex );
00403    graphicsQueue.push_back( gqo );
00404    SDL_mutexV( graphicsQueueMutex );
00405 
00406    if ( forceAsync )
00407       return;
00408 
00409    if ( syncGraphics || wait ) {
00410       bool finished = false;
00411       do {
00412          SDL_Delay(10);
00413          SDL_mutexP( graphicsQueueMutex );
00414          finished = graphicsQueue.empty();
00415          SDL_mutexV( graphicsQueueMutex );
00416       } while (!finished);
00417    }
00418 }
00419 
00420 
00421 void UpdateRectOp::execute()
00422 { 
00423    if ( *mouseUpdateFlag )
00424       SDL_ShowCursor( 0 );
00425 
00426    SDL_UpdateRect( screen, x,y,w,h); 
00427    postScreenUpdate( screen );
00428 
00429    if ( *mouseUpdateFlag )
00430       SDL_ShowCursor( 1 );
00431 };
00432 
00433 
00434 UpdateRectsOp::UpdateRectsOp( SDL_Surface *screen, int numrects, SDL_Rect *rects) 
00435 {
00436    this->numrects = numrects;
00437    this->rects = new SDL_Rect[numrects];
00438    for ( int i = 0; i< numrects; ++i )
00439       this->rects[i] = rects[i];
00440    this->screen = screen;
00441 };
00442 
00443 UpdateRectsOp::~UpdateRectsOp()
00444 {
00445    delete[] rects;
00446 }
00447 
00448 void UpdateRectsOp::execute() 
00449 { 
00450    if ( *mouseUpdateFlag )
00451       SDL_ShowCursor( 0 );
00452 
00453    SDL_UpdateRects( screen, numrects, rects); 
00454    postScreenUpdate( screen );
00455 
00456    if ( *mouseUpdateFlag )
00457       SDL_ShowCursor( 1 );
00458 }
00459 
00460 
00461 void InitScreenOp::execute() 
00462 { 
00463    if ( *mouseUpdateFlag )
00464       SDL_ShowCursor( 0 );
00465 
00466    SDL_Surface* screen = SDL_SetVideoMode(x, y, depth, flags);
00467    if (screen == NULL) 
00468       screen = SDL_SetVideoMode(x, y, depth, flags & ~SDL_FULLSCREEN );
00469 
00470    srf( screen );
00471    initASCGraphicSubsystem( screen );
00472 
00473    if ( *mouseUpdateFlag )
00474       SDL_ShowCursor( 1 );
00475 };
00476 
00477 
00478 bool processGraphicsQueue()
00479 {
00480 #ifdef FirstThreadEvents
00481    GraphicsQueueOperation* gqo = NULL;
00482    SDL_mutexP( graphicsQueueMutex );
00483    if ( !graphicsQueue.empty() ) {
00484       gqo = graphicsQueue.front();
00485       SDL_mutexV( graphicsQueueMutex );
00486       if ( gqo ) {
00487          gqo->execute();
00488 
00489          SDL_mutexP( graphicsQueueMutex );
00490          graphicsQueue.pop_front();
00491          SDL_mutexV( graphicsQueueMutex );
00492          delete gqo;
00493          return true;
00494       } else
00495          return false;
00496    } else {
00497       SDL_mutexV( graphicsQueueMutex );
00498       return false;   
00499    }
00500 #else
00501    return false;
00502 #endif
00503 }
00504 
00505 int eventthread ( void* nothing )
00506 {
00507 #ifdef FirstThreadEvents
00508    eventThreadRunning = true;
00509 #endif
00510    while ( !closeEventThread ) {
00511       if ( !processEvents() )
00512          SDL_Delay(10);
00513       processGraphicsQueue();
00514       ticker = getTicker();
00515    }
00516 #ifdef FirstThreadEvents
00517    eventThreadRunning = false;
00518    while ( processGraphicsQueue() ) 
00519       SDL_Delay(10);
00520 #endif
00521    return closeEventThread;
00522 }
00523 
00524 
00525 int getTicker()
00526 {
00527    return SDL_GetTicks() / 10;
00528 }
00529 
00530 #ifdef FirstThreadEvents 
00531 int (*_gamethread)(void *);
00532 
00533 int gameThreadWrapper ( void* data )
00534 {
00535    try {
00536       int res = _gamethread ( data );
00537       closeEventThread = 1;
00538       return res;
00539    }
00540 #ifndef WIN32
00541    catch ( ... ) {
00542       fatalError ("An unhandled exception occured. Quitting application");
00543    }
00544 #else
00545    catch ( ASCexception ) {
00546       fatalError ("An unhandled exception occured. Quitting application");
00547    }
00548 #endif
00549    closeEventThread = -1;
00550    return -1;
00551 }
00552 #endif
00553 
00554 
00556 SDL_Thread* secondThreadHandle = NULL;
00557 
00558 
00559 
00560 int initializeEventHandling ( int (*gamethread)(void *) , void *data )
00561 {
00562 
00563    mouseparams.xsize = 10;
00564    mouseparams.ysize = 10;
00565 
00566    keyboardmutex = SDL_CreateMutex ();
00567    if ( !keyboardmutex ) {
00568       printf("creating keyboard mutex failed\n" );
00569       exit(1);
00570    }
00571 
00572    eventHandlingMutex = SDL_CreateMutex ();
00573    if ( !eventHandlingMutex ) {
00574       printf("creating eventHandling mutex failed\n" );
00575       exit(1);
00576    }
00577 
00578 
00579    eventQueueMutex = SDL_CreateMutex ();
00580    if ( !eventQueueMutex ) {
00581       printf("creating eventQueueMutex failed\n" );
00582       exit(1);
00583    }
00584 
00585    graphicsQueueMutex = SDL_CreateMutex();
00586    if ( !graphicsQueueMutex ) {
00587       printf("creating graphicsQueueMutex failed\n" );
00588       exit(1);
00589    }
00590 
00591    SDL_EnableUNICODE ( 1 );
00592    SDL_EnableKeyRepeat ( 250, 30 );
00593 
00594    
00595 #ifdef FirstThreadEvents 
00596    _gamethread = gamethread;
00597    secondThreadHandle = SDL_CreateThread ( gameThreadWrapper, data );
00598    int res = eventthread( NULL );
00599 #else
00600    secondThreadHandle = SDL_CreateThread ( eventthread, NULL );
00601    int res = gamethread( data );
00602    closeEventThread = 1;
00603 #endif
00604 
00605 
00606    SDL_WaitThread ( secondThreadHandle, NULL );
00607    return res;
00608 }
00609 
00610 
00611 
00612 void exit_asc( int returnresult )
00613 {
00614 #ifndef FirstThreadEvents 
00615    if ( secondThreadHandle ) {
00616       closeEventThread = 1;
00617       SDL_WaitThread ( secondThreadHandle, NULL );
00618    }   
00619    exit( returnresult );   
00620 #else
00621    if ( secondThreadHandle ) {
00622       throw ThreadExitException();
00623    }
00624    exit( returnresult );   
00625 
00626 
00627 #endif
00628 
00629    
00630 }
00631 
00632 
00633 bool setEventRouting( bool queue, bool legacy )
00634 {
00635   bool prev = _queueEvents;
00636   
00637   _fillLegacyEventStructures = legacy;
00638   
00639   _queueEvents = queue;
00640   if ( !queue ) {
00641       // clear all waiting events in the queue
00642       SDL_mutexP( eventQueueMutex );
00643       while ( !eventQueue.empty())
00644          eventQueue.pop();
00645       SDL_mutexV( eventQueueMutex );
00646    }
00647    
00648    return prev;
00649 }
00650 
00651 bool legacyEventSystemActive()
00652 {
00653    return _fillLegacyEventStructures;   
00654 }
00655 
00656 
00657 bool getQueuedEvent ( SDL_Event& event )
00658 {
00659    SDL_mutexP( eventQueueMutex );
00660    if ( !eventQueue.empty() ) {
00661       event = eventQueue.front();
00662       eventQueue.pop();
00663       SDL_mutexV( eventQueueMutex );
00664       return true;
00665    }
00666    SDL_mutexV( eventQueueMutex );
00667    return false;
00668 }
00669     
00670 bool peekEvent ( SDL_Event& event )
00671 {
00672    SDL_mutexP( eventQueueMutex );
00673    if ( !eventQueue.empty() ) {
00674       event = eventQueue.front();
00675       SDL_mutexV( eventQueueMutex );
00676       return true;
00677    }
00678    SDL_mutexV( eventQueueMutex );
00679    return false;
00680 }
00681 
00682 

Generated on Mon May 21 01:26:32 2012 for Advanced Strategic Command by  doxygen 1.5.1