sdlterm/src/sdlterm.cc
changeset 72 6e0656600754
parent 71 cfd3445107b4
child 73 85a282b5e4fc
equal deleted inserted replaced
71:cfd3445107b4 72:6e0656600754
   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)