369 } |
369 } |
370 |
370 |
371 |
371 |
372 bool Terminal::wait_event(Event &event, Uint32 timeout) |
372 bool Terminal::wait_event(Event &event, Uint32 timeout) |
373 { |
373 { |
|
374 SDL_Event sdl_event; |
|
375 bool translated; |
|
376 |
|
377 // any events pending? |
|
378 while (SDL_PollEvent(&sdl_event)) |
|
379 { |
|
380 translated = _handle_event(sdl_event, event); |
|
381 if (translated) |
|
382 return true; |
|
383 } |
|
384 |
374 // use timer to simulate SDL_WaitEventTimeout, which is not available in SDL 1.2 |
385 // use timer to simulate SDL_WaitEventTimeout, which is not available in SDL 1.2 |
375 SDL_TimerID timer_id = NULL; |
386 SDL_TimerID timer_id = NULL; |
376 if (timeout) |
387 if (timeout) |
377 { |
388 { |
378 timer_id = SDL_AddTimer(timeout, _wait_event_callback, NULL); |
389 timer_id = SDL_AddTimer(timeout, _wait_event_callback, NULL); |
379 } |
390 } |
380 |
391 |
381 // loop until we have something to return |
392 // loop until we have something to return |
382 SDL_Event sdl_event; |
|
383 bool event_ready = false; |
393 bool event_ready = false; |
384 while (SDL_WaitEvent(&sdl_event) && !event_ready) |
394 while (!event_ready && SDL_WaitEvent(&sdl_event)) |
385 { |
395 { |
386 switch (sdl_event.type) |
396 do |
387 { |
397 { |
388 case SDL_USEREVENT: |
398 translated = _handle_event(sdl_event, event); |
389 // timeout |
399 if (translated) |
390 if (sdl_event.user.code == 1) |
400 { |
|
401 event_ready = true; |
|
402 break; |
|
403 } |
|
404 // timeout? |
|
405 if (sdl_event.type == SDL_USEREVENT && sdl_event.user.code == 1) |
|
406 { |
|
407 SDL_RemoveTimer(timer_id); |
|
408 return false; |
|
409 } |
|
410 } |
|
411 while (!event_ready && SDL_PollEvent(&sdl_event)); |
|
412 } |
|
413 |
|
414 // remove timer when other event came before timeout |
|
415 if (timeout) |
|
416 { |
|
417 SDL_RemoveTimer(timer_id); |
|
418 } |
|
419 |
|
420 // ok or error? |
|
421 if (event_ready) |
|
422 { |
|
423 return true; |
|
424 } |
|
425 else |
|
426 { |
|
427 throw SDLTermError(std::string("SDL_WaitEvent: ") + SDL_GetError()); |
|
428 } |
|
429 } |
|
430 |
|
431 |
|
432 // return true when SDL_Event was translated to our Event |
|
433 bool Terminal::_handle_event(const SDL_Event &sdl_event, Event &event) |
|
434 { |
|
435 switch (sdl_event.type) |
|
436 { |
|
437 case SDL_USEREVENT: |
|
438 // toggle blink |
|
439 if (sdl_event.user.code == 2) |
|
440 { |
|
441 _screen.toggle_blink(); |
|
442 } |
|
443 return false; |
|
444 |
|
445 case SDL_QUIT: |
|
446 event.type = Event::QUIT; |
|
447 return true; |
|
448 |
|
449 case SDL_VIDEORESIZE: |
|
450 event.type = Event::RESIZE; |
|
451 _screen.resize(sdl_event.resize.w, sdl_event.resize.h); |
|
452 return true; |
|
453 |
|
454 case SDL_VIDEOEXPOSE: |
|
455 _screen.redraw(); |
|
456 return false; |
|
457 |
|
458 case SDL_KEYDOWN: |
|
459 { |
|
460 //switch(event.key.keysym.sym) |
|
461 event.type = Event::KEYPRESS; |
|
462 const char *keyname = _translate_keyname(sdl_event.key.keysym.sym); |
|
463 // return only keyname or unicode, never both |
|
464 if (keyname) |
|
465 { |
|
466 strncpy(event.key.keyname, keyname, 10); |
|
467 event.key.unicode = 0; |
|
468 } |
|
469 else |
|
470 { |
|
471 event.key.keyname[0] = 0; |
|
472 event.key.unicode = sdl_event.key.keysym.unicode; |
|
473 if (!event.key.unicode) |
391 { |
474 { |
392 SDL_RemoveTimer(timer_id); |
475 // unknown key |
393 return false; |
476 return false; |
394 } |
477 } |
395 // toggle blink |
478 } |
396 if (sdl_event.user.code == 2) |
479 event.key.mod = _translate_mod(sdl_event.key.keysym.mod); |
|
480 return true; |
|
481 } |
|
482 |
|
483 case SDL_MOUSEBUTTONDOWN: |
|
484 case SDL_MOUSEBUTTONUP: |
|
485 event.type = (sdl_event.type == SDL_MOUSEBUTTONDOWN) ? Event::MOUSEDOWN : Event::MOUSEUP; |
|
486 event.mouse.x = sdl_event.button.x / _screen.get_cell_width(); |
|
487 event.mouse.y = sdl_event.button.y / _screen.get_cell_height(); |
|
488 event.mouse.button = sdl_event.button.button; |
|
489 if (sdl_event.button.button == SDL_BUTTON_WHEELUP || sdl_event.button.button == SDL_BUTTON_WHEELDOWN) |
|
490 { |
|
491 if (sdl_event.type == SDL_MOUSEBUTTONUP) |
397 { |
492 { |
398 _screen.toggle_blink(); |
493 // do not report button-up events for mouse wheel |
|
494 return false; |
399 } |
495 } |
400 break; // continue loop |
496 event.type = Event::MOUSEWHEEL; |
401 |
497 } |
402 case SDL_QUIT: |
498 _mousemove_last_x = event.mouse.x; |
403 event.type = Event::QUIT; |
499 _mousemove_last_y = event.mouse.y; |
404 event_ready = true; |
500 return true; |
405 break; |
501 |
406 |
502 case SDL_MOUSEMOTION: |
407 case SDL_VIDEORESIZE: |
503 if (sdl_event.motion.state == 0 || _mousemove_last_x == -1) |
408 event.type = Event::RESIZE; |
504 { |
409 _screen.resize(sdl_event.resize.w, sdl_event.resize.h); |
505 // do not report move events when no button is pressed |
410 event_ready = true; |
506 return false; |
411 break; |
507 } |
412 |
508 event.type = Event::MOUSEMOVE; |
413 case SDL_VIDEOEXPOSE: |
509 event.mouse.x = sdl_event.motion.x / _screen.get_cell_width(); |
414 _screen.redraw(); |
510 event.mouse.y = sdl_event.motion.y / _screen.get_cell_height(); |
415 break; |
511 if (_mousemove_last_x != event.mouse.x || |
416 |
512 _mousemove_last_y != event.mouse.y) |
417 case SDL_KEYDOWN: |
513 { |
418 { |
514 event.mouse.relx = event.mouse.x - _mousemove_last_x; |
419 //switch(event.key.keysym.sym) |
515 event.mouse.rely = event.mouse.y - _mousemove_last_y; |
420 event.type = Event::KEYPRESS; |
516 _mousemove_last_x = event.mouse.x; |
421 const char *keyname = _translate_keyname(sdl_event.key.keysym.sym); |
517 _mousemove_last_y = event.mouse.y; |
422 // return only keyname or unicode, never both |
518 return true; |
423 if (keyname) |
519 } |
424 { |
520 // mouse position did not change |
425 strncpy(event.key.keyname, keyname, 10); |
521 return false; |
426 event.key.unicode = 0; |
522 |
427 } |
523 default: |
428 else |
524 // unknown event |
429 { |
525 return false; |
430 event.key.keyname[0] = 0; |
|
431 event.key.unicode = sdl_event.key.keysym.unicode; |
|
432 if (!event.key.unicode) |
|
433 break; // continue loop (unknown key) |
|
434 } |
|
435 event.key.mod = _translate_mod(sdl_event.key.keysym.mod); |
|
436 event_ready = true; |
|
437 break; |
|
438 } |
|
439 |
|
440 case SDL_MOUSEBUTTONDOWN: |
|
441 case SDL_MOUSEBUTTONUP: |
|
442 event.type = (sdl_event.type == SDL_MOUSEBUTTONDOWN) ? Event::MOUSEDOWN : Event::MOUSEUP; |
|
443 event.mouse.x = sdl_event.button.x / _screen.get_cell_width(); |
|
444 event.mouse.y = sdl_event.button.y / _screen.get_cell_height(); |
|
445 event.mouse.button = sdl_event.button.button; |
|
446 if (sdl_event.button.button == SDL_BUTTON_WHEELUP || sdl_event.button.button == SDL_BUTTON_WHEELDOWN) |
|
447 { |
|
448 if (sdl_event.type == SDL_MOUSEBUTTONUP) |
|
449 break; // do not report button-up events for mouse wheel |
|
450 event.type = Event::MOUSEWHEEL; |
|
451 } |
|
452 _mousemove_last_x = -1; |
|
453 event_ready = true; |
|
454 break; |
|
455 |
|
456 case SDL_MOUSEMOTION: |
|
457 if (sdl_event.motion.state == 0) |
|
458 break; // continue loop, do not report move events when no button is pressed |
|
459 event.type = Event::MOUSEMOVE; |
|
460 event.mouse.x = sdl_event.motion.x / _screen.get_cell_width(); |
|
461 event.mouse.y = sdl_event.motion.y / _screen.get_cell_height(); |
|
462 if (_mousemove_last_x != event.mouse.x || |
|
463 _mousemove_last_y != event.mouse.y) |
|
464 { |
|
465 if (_mousemove_last_x != -1) |
|
466 { |
|
467 event.mouse.relx = event.mouse.x - _mousemove_last_x; |
|
468 event.mouse.rely = event.mouse.y - _mousemove_last_y; |
|
469 event_ready = true; |
|
470 } |
|
471 _mousemove_last_x = event.mouse.x; |
|
472 _mousemove_last_y = event.mouse.y; |
|
473 break; |
|
474 } |
|
475 break; // continue loop when mouse position did not change |
|
476 |
|
477 default: |
|
478 break; // continue loop |
|
479 } |
|
480 } |
|
481 |
|
482 // remove timer when other event came before timeout |
|
483 if (timeout) |
|
484 { |
|
485 SDL_RemoveTimer(timer_id); |
|
486 } |
|
487 |
|
488 // ok or error? |
|
489 if (event_ready) |
|
490 { |
|
491 return true; |
|
492 } |
|
493 else |
|
494 { |
|
495 throw SDLTermError(std::string("SDL_WaitEvent: ") + SDL_GetError()); |
|
496 } |
526 } |
497 } |
527 } |
498 |
528 |
499 |
529 |
500 const char *Terminal::_translate_keyname(SDLKey sym) |
530 const char *Terminal::_translate_keyname(SDLKey sym) |