Info
Get involved
Documentation
00001 /* 00002 SAL - Simple Application Library 00003 Copyright (C) 2006-2006 Kronon 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Lesser General Public 00007 License as published by the Free Software Foundation; either 00008 version 2.1 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Lesser General Public License for more details. 00014 00015 You should have received a copy of the GNU Lesser General Public 00016 License along with this library; if not, write to the Free Software 00017 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00018 00019 Kronon 00020 kronon88@users.sourceforge.net 00021 */ 00022 00023 //SAL event handling 00024 //Created by Kronon 00025 00026 //Doxy gen information 00027 00034 #include "SAL_eventhandler.h" 00035 00036 //Local variables 00037 SDL_Thread *keyboard_thread = NULL; 00038 bool keyboard_active; 00039 00047 struct SAL_reg_key //A key that is registered to the event listener 00048 { 00049 Uint16 unicode; 00050 SAL_gui_object * object; 00051 }; 00052 00059 salList<SAL_reg_key> registered_keys; 00060 00068 struct SAL_keyboard_item 00069 { 00070 SDLKey key; 00071 SDLMod mod; 00072 Uint32 life; 00073 SAL_gui_object * selected; 00074 }; 00075 00082 salList<SAL_keyboard_item> pend_keys; 00086 SDL_mutex *keyboard_mutex; //Protects pend_keys list 00087 00094 struct SAL_keyboard_items 00095 { 00096 int delay; 00097 }; 00102 SAL_keyboard_items keyboard; 00103 00110 struct SAL_mouse_items 00111 { 00112 SDL_Thread *thread; 00113 bool active; 00114 char clicks; 00115 SAL_gui_object * selected; 00116 Uint16 x; 00117 Uint16 y; 00118 char button; 00119 int delay; 00120 }; 00125 SAL_mouse_items mouse; 00126 00135 //In: Point to pend_key in array, Uint16 unicode char 00136 //Out: Bool (match/no match) 00137 //Action: Look if unicode char of keyboard_item and wanted unicode char match 00138 bool remove_key(SAL_keyboard_item item, SAL_keyboard_item target) 00139 { 00140 return (item.key == target.key); 00141 } 00142 00151 //In: default mouse delay time, default keyboard delay time 00152 //Out: Error_code 00153 //Action: Start event listener thread 00154 int SAL_start_event_listener(int & mouse_delay, int & keyboard_delay) 00155 { 00156 //Delay times 00157 mouse.delay = mouse_delay; 00158 keyboard.delay = keyboard_delay; 00159 00160 //Load the event listener 00161 SAL_struct.internal.event.thread = SDL_CreateThread(SAL_event_listener, NULL); 00162 if(SAL_struct.internal.event.thread == NULL) 00163 { 00164 #ifdef SAL_DEBUG_ON 00165 salError("Error: Event handler thread couldn't start"); 00166 #endif 00167 return -1; 00168 } 00169 return 0; 00170 } 00171 00182 //In: Nothing realy 00183 //Out: Error_code 00184 //Action: Listen to the sdl events, convert them to a more useable standard, call defined action handlers 00185 int SAL_event_listener(void * unused) 00186 { 00187 //Set some vars 00188 mouse.thread = NULL; 00189 mouse.active = false; 00190 keyboard_mutex = SDL_CreateMutex(); 00191 keyboard_active = false; 00192 00193 #ifdef SAL_DEBUG_ON 00194 sleep(1); //Debuger crashes in some case because it can't find the thread after termination 00195 #endif 00196 00197 SDL_Event event; 00198 //We want to know new events as long as we don't quit 00199 while(SAL_struct.internal.checks.alive) 00200 { 00201 //Check the next event 00202 SDL_WaitEvent(&event); 00203 switch (event.type) 00204 { 00205 case SDL_MOUSEBUTTONDOWN: 00206 { 00207 mouse.clicks++; 00208 } 00209 break; 00210 case SDL_MOUSEBUTTONUP: 00211 { 00212 if(mouse.active) 00213 mouse.clicks++; //Total clicks is mouse_clicks / 2 00214 else 00215 { 00216 mouse.clicks = 2; 00217 00218 mouse.selected = NULL; 00219 SAL_search_object(event.button.x, event.button.y, mouse.selected); 00220 00221 //We need to register amount of clicks 00222 mouse.x = event.button.x; 00223 mouse.y = event.button.y; 00224 mouse.button = event.button.button; 00225 00226 mouse.active = true; 00227 SDL_WaitThread(mouse.thread, NULL); //Free's memory and solves a bug 00228 mouse.thread = SDL_CreateThread(SAL_mouse_listener, NULL); 00229 00230 if(mouse.thread == NULL) 00231 { 00232 #ifdef SAL_DEBUG_ON 00233 salError("Error: Mouse listener thread couldn't start"); 00234 #endif 00235 return -1; 00236 } 00237 00238 if(mouse.selected) 00239 { 00240 //Select object 00241 mouse.selected->func->pressed(mouse.selected); 00242 } 00243 } 00244 } 00245 break; 00246 case SDL_KEYDOWN: 00247 { 00248 //Add key to key list 00249 SDL_mutexP(keyboard_mutex); 00250 SAL_gui_object * selected = NULL; 00251 #ifdef SAL_DEBUG_ON 00252 printf("Key down = %i\n",event.key.keysym.sym); 00253 #endif 00254 SAL_search_object(event.key.keysym.unicode, selected); 00255 SAL_keyboard_item key = {event.key.keysym.sym,event.key.keysym.mod, SDL_GetTicks() + keyboard.delay, selected}; 00256 00257 pend_keys.append(key); 00258 00259 //Process event 00260 if(SAL_struct.internal.event.active_object == NULL) 00261 { 00262 if(SAL_struct.internal.event.action_handler.keyboard != NULL) 00263 SAL_struct.internal.event.action_handler.keyboard(key.key, key.mod); 00264 } 00265 else 00266 SAL_struct.internal.event.active_object->func->key_down(SAL_struct.internal.event.active_object,key.key, key.mod); 00267 00268 if(!keyboard_active) 00269 { 00270 keyboard_active = true; 00271 SDL_WaitThread(keyboard_thread, NULL); //Free's memory and solves a bug 00272 keyboard_thread = SDL_CreateThread(SAL_keyboard_listener, NULL); 00273 00274 if(keyboard_thread == NULL) 00275 { 00276 #ifdef SAL_DEBUG_ON 00277 salError("Error: Keyboard listener thread couldn't start"); 00278 #endif 00279 return -1; 00280 } 00281 } 00282 SDL_mutexV(keyboard_mutex); 00283 } 00284 break; 00285 case SDL_KEYUP: 00286 { 00287 //Remove key from polled keys 00288 #ifdef SAL_DEBUG_ON 00289 printf("Key up = %i\n",event.key.keysym.sym); 00290 #endif 00291 SDL_mutexP(keyboard_mutex); 00292 pend_keys.funcRemove(remove_key,(SAL_keyboard_item){(SDLKey)event.key.keysym.sym,(SDLMod)NULL,0,NULL},-1); 00293 SDL_mutexV(keyboard_mutex); 00294 } 00295 break; 00296 case SDL_QUIT: 00297 { 00298 //SDL got an signal to quit, so lets exit the program the nice way 00299 salStop(); 00300 break; 00301 } 00302 } 00303 } 00304 SDL_mutexP(keyboard_mutex); //Protect pend_keys list 00305 pend_keys.clear(); 00306 SDL_mutexV(keyboard_mutex); 00307 00308 SDL_WaitThread(keyboard_thread, NULL); 00309 SDL_DestroyMutex(keyboard_mutex); 00310 return 0; 00311 } 00312 00321 //In: None 00322 //Out: Error_code 00323 //Action: After some time this get the ammount of clicks and executes the user defined mouse handler 00324 int SAL_mouse_listener(void * unused) 00325 { 00326 //Wait 00327 SDL_Delay(mouse.delay); 00328 00329 if(mouse.selected) 00330 { 00331 mouse.selected->func->released(mouse.selected); 00332 if(SAL_struct.internal.event.action_handler.action != NULL) 00333 SAL_struct.internal.event.action_handler.action(mouse.selected->id); 00334 } 00335 else if(SAL_struct.internal.event.action_handler.mouse != NULL) 00336 SAL_struct.internal.event.action_handler.mouse(mouse.x, mouse.y, mouse.button, mouse.clicks); 00337 00338 mouse.active = false; //Safe? 00339 return 0; 00340 } 00341 00350 //In: None 00351 //Out: Error_code 00352 //Action: Ass long as any button is pressed this thread generates "button presses(better name?)" 00353 int SAL_keyboard_listener(void * unused) 00354 { 00355 //pend_keys.setLoopBegin(); //Get the beginning of the array with pause times of keys with there corresponding key code 00356 SDL_mutexP(keyboard_mutex); //Protect pend_keys list 00357 while(!pend_keys.isEmpty()) //Only loop while there are keys 00358 { 00359 //Save all active keys to array 00360 //Check if all keys are still active in that array 00361 SDL_mutexV(keyboard_mutex); //Free acces to pend_keys 00362 SDL_Delay(keyboard.delay); //Key poll time 00363 SDL_mutexP(keyboard_mutex); //Protect pend_keys list 00364 00365 for(pend_keys.setLoopBegin(); pend_keys.inLoop(); ) 00366 { 00367 00368 // if(SAL_search_object(pend_keys.getLoopEntry(), object) != -1) 00369 // SAL_struct.internal.event.action_handler.action(object->id); 00370 // else 00371 if(pend_keys.getLoopEntry().life < SDL_GetTicks()) //Key needs to be stroken for at least some time 00372 { 00373 if(SAL_struct.internal.event.active_object == NULL) 00374 { 00375 if(SAL_struct.internal.event.action_handler.keyboard != NULL) 00376 SAL_struct.internal.event.action_handler.keyboard(pend_keys.getLoopEntry().key, pend_keys.getLoopEntry().mod); 00377 } 00378 else 00379 SAL_struct.internal.event.active_object->func->key_down(SAL_struct.internal.event.active_object,pend_keys.getLoopEntry().key, pend_keys.getLoopEntry().mod); 00380 } 00381 } 00382 } 00383 keyboard_active = false; 00384 SDL_mutexV(keyboard_mutex); //Free acces ti pend_keys 00385 return 0; 00386 } 00387 00397 //In: x coordinate, y coordinate, type of click, object id that is to be returned by this function 00398 //Out: Error_code 00399 //Action: Search corresponding block with x,y. Look if an object is located at the given coordinates and return it 00400 inline int SAL_search_object(int x, int y, SAL_gui_object *& target) 00401 { 00402 //Calcultate the ractangle the mouse is in and start searching from that rectangle 00403 //The window is devided in 5x5 rectangles 00404 //TODO: when the window resizes we need to change the contents of the blocks according to the new situation 00405 int blockX, blockY; 00406 blockX = x / (SAL_struct.internal.render.display->w / 5); 00407 blockY = y / (SAL_struct.internal.render.display->h / 5); 00408 00409 //Open the block and search for objects 00410 for(SAL_struct.internal.event.select_matrix[blockX][blockY].setLoopBegin(); SAL_struct.internal.event.select_matrix[blockX][blockY].inLoop(); ) 00411 { 00412 //Check left border 00413 //Check Top border 00414 //Check Right border 00415 //Check bottom border 00416 if(SAL_struct.internal.event.select_matrix[blockX][blockY].getLoopEntry()->x <= x && 00417 SAL_struct.internal.event.select_matrix[blockX][blockY].getLoopEntry()->y <= y && 00418 (SAL_struct.internal.event.select_matrix[blockX][blockY].getLoopEntry()->surface->w + 00419 SAL_struct.internal.event.select_matrix[blockX][blockY].getLoopEntry()->x) >= x && 00420 (SAL_struct.internal.event.select_matrix[blockX][blockY].getLoopEntry()->surface->h + 00421 SAL_struct.internal.event.select_matrix[blockX][blockY].getLoopEntry()->y) >= y) 00422 { 00423 target = SAL_struct.internal.event.select_matrix[blockX][blockY].getLoopEntry(); //Set object id 00424 return 1; //Found an object 00425 } 00426 } 00427 00428 return 0; //Found no object 00429 } 00430 00439 //In: Keyboard character, object that is to be returned 00440 //Out: Error_code 00441 // 0: Normal 00442 // -1: No object registered with that code 00443 //Action: Search object that is connected to the given char 00444 int SAL_search_object(Uint16 unicode, SAL_gui_object *& target) 00445 { 00446 //Search for an object with unicode as fast key and return that object 00447 for(registered_keys.setLoopBegin(); registered_keys.inLoop(); ) 00448 { 00449 if(registered_keys.getLoopEntry().unicode == unicode) 00450 { 00451 target = registered_keys.getLoopEntry().object; 00452 return 0; 00453 } 00454 } 00455 return -1; 00456 } 00457 00464 //In: pointer to user defined action handler 00465 //Out: Error_code 00466 // 0: Normal 00467 //Action: Connect user defined action handler to SAL library 00468 int salSetActionHandler(int (*action)(int action_id)) 00469 { 00470 SAL_struct.internal.event.action_handler.action = action; 00471 return 0; 00472 } 00473 00479 00481 //In: pointer to user defined mouse handler 00482 //Out: Error_code 00483 // 0: Normal 00484 //Action: Connect user defined mouse handler to SAL library 00485 int salSetMouseHandler(int (*mouse)(int x, int y, char button, char clicks)) 00486 { 00487 SAL_struct.internal.event.action_handler.mouse = mouse; 00488 return 0; 00489 } 00490 00497 //In: pointer to user defined keyboard handler 00498 //Out: Error_code 00499 // 0: Normal 00500 //Action: Connect user defined keyboard handler to SAL library 00501 int salSetKeyboardHandler(int (*keyboard)(SDLKey key, SDLMod mod)) 00502 { 00503 SAL_struct.internal.event.action_handler.keyboard = keyboard; 00504 return 0; 00505 }