Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "global.hpp"
00017
00018 #include "clipboard.hpp"
00019 #include "cursor.hpp"
00020 #include "events.hpp"
00021 #include "log.hpp"
00022 #include "preferences_display.hpp"
00023 #include "sound.hpp"
00024 #include "video.hpp"
00025
00026 #include "SDL.h"
00027
00028 #include <algorithm>
00029 #include <cassert>
00030 #include <deque>
00031 #include <utility>
00032 #include <vector>
00033
00034 #define ERR_GEN LOG_STREAM(err, lg::general)
00035
00036 namespace events
00037 {
00038
00039 namespace {
00040
00041 struct context
00042 {
00043 context() :
00044 handlers(),
00045 focused_handler(-1)
00046 {
00047 }
00048
00049 void add_handler(handler* ptr);
00050 bool remove_handler(handler* ptr);
00051 int cycle_focus();
00052 void set_focus(const handler* ptr);
00053
00054 std::vector<handler*> handlers;
00055 int focused_handler;
00056
00057 void delete_handler_index(size_t handler);
00058 };
00059
00060 void context::add_handler(handler* ptr)
00061 {
00062 handlers.push_back(ptr);
00063 }
00064
00065 void context::delete_handler_index(size_t handler)
00066 {
00067 if(focused_handler == static_cast<int>(handler)) {
00068 focused_handler = -1;
00069 } else if(focused_handler > static_cast<int>(handler)) {
00070 --focused_handler;
00071 }
00072
00073 handlers.erase(handlers.begin()+handler);
00074 }
00075
00076 bool context::remove_handler(handler* ptr)
00077 {
00078 if(handlers.empty()) {
00079 return false;
00080 }
00081
00082 static int depth = 0;
00083 ++depth;
00084
00085
00086
00087 if(handlers.back() == ptr) {
00088 delete_handler_index(handlers.size()-1);
00089 } else {
00090 const std::vector<handler*>::iterator i = std::find(handlers.begin(),handlers.end(),ptr);
00091 if(i != handlers.end()) {
00092 delete_handler_index(i - handlers.begin());
00093 } else {
00094 return false;
00095 }
00096 }
00097
00098 --depth;
00099
00100 if(depth == 0) {
00101 cycle_focus();
00102 } else {
00103 focused_handler = -1;
00104 }
00105
00106 return true;
00107 }
00108
00109 int context::cycle_focus()
00110 {
00111 int index = focused_handler+1;
00112 for(size_t i = 0; i != handlers.size(); ++i) {
00113 if(size_t(index) == handlers.size()) {
00114 index = 0;
00115 }
00116
00117 if(handlers[size_t(index)]->requires_event_focus()) {
00118 focused_handler = index;
00119 break;
00120 }
00121 }
00122
00123 return focused_handler;
00124 }
00125
00126 void context::set_focus(const handler* ptr)
00127 {
00128 const std::vector<handler*>::const_iterator i = std::find(handlers.begin(),handlers.end(),ptr);
00129 if(i != handlers.end() && (**i).requires_event_focus()) {
00130 focused_handler = int(i - handlers.begin());
00131 }
00132 }
00133
00134
00135
00136
00137
00138 std::deque<context> event_contexts;
00139
00140 std::vector<pump_monitor*> pump_monitors;
00141
00142 }
00143
00144 pump_monitor::pump_monitor() {
00145 pump_monitors.push_back(this);
00146 }
00147
00148 pump_monitor::~pump_monitor() {
00149 pump_monitors.erase(
00150 std::remove(pump_monitors.begin(), pump_monitors.end(), this),
00151 pump_monitors.end());
00152 }
00153
00154 event_context::event_context()
00155 {
00156 event_contexts.push_back(context());
00157 }
00158
00159 event_context::~event_context()
00160 {
00161 assert(event_contexts.empty() == false);
00162 event_contexts.pop_back();
00163 }
00164
00165 handler::handler(const bool auto_join) : unicode_(SDL_EnableUNICODE(1)), has_joined_(false)
00166 {
00167 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,SDL_DEFAULT_REPEAT_INTERVAL);
00168 if(auto_join) {
00169 assert(!event_contexts.empty());
00170 event_contexts.back().add_handler(this);
00171 has_joined_ = true;
00172 }
00173 }
00174
00175 handler::~handler()
00176 {
00177 leave();
00178 SDL_EnableUNICODE(unicode_);
00179 }
00180
00181 void handler::join()
00182 {
00183 if(has_joined_) {
00184 leave();
00185 }
00186
00187 event_contexts.back().add_handler(this);
00188 has_joined_ = true;
00189
00190
00191 handler_vector members = handler_members();
00192 if(!members.empty()) {
00193 for(handler_vector::iterator i = members.begin(); i != members.end(); ++i) {
00194 (*i)->join();
00195 }
00196 }
00197 }
00198
00199 void handler::leave()
00200 {
00201 handler_vector members = handler_members();
00202 if(!members.empty()) {
00203 for(handler_vector::iterator i = members.begin(); i != members.end(); ++i) {
00204 (*i)->leave();
00205 }
00206 } else {
00207 assert(event_contexts.empty() == false);
00208 }
00209 for(std::deque<context>::reverse_iterator i = event_contexts.rbegin(); i != event_contexts.rend(); ++i) {
00210 if(i->remove_handler(this)) {
00211 break;
00212 }
00213 }
00214 has_joined_ = false;
00215 }
00216
00217 void focus_handler(const handler* ptr)
00218 {
00219 if(event_contexts.empty() == false) {
00220 event_contexts.back().set_focus(ptr);
00221 }
00222 }
00223
00224 bool has_focus(const handler* hand, const SDL_Event* event)
00225 {
00226 if(event_contexts.empty()) {
00227 return true;
00228 }
00229
00230 if(hand->requires_event_focus(event) == false) {
00231 return true;
00232 }
00233
00234 const int foc_i = event_contexts.back().focused_handler;
00235
00236
00237
00238 if(foc_i == -1) {
00239 focus_handler(hand);
00240 return true;
00241 }
00242
00243 handler *const foc_hand = event_contexts.back().handlers[foc_i];
00244 if(foc_hand == hand){
00245 return true;
00246 } else if(!foc_hand->requires_event_focus(event)) {
00247
00248
00249 int back_i = event_contexts.back().handlers.size() - 1;
00250 for(int i=back_i; i>=0; --i) {
00251 handler *const thief_hand = event_contexts.back().handlers[i];
00252 if(i != foc_i && thief_hand->requires_event_focus(event)) {
00253
00254 focus_handler(thief_hand);
00255 if(foc_i < back_i) {
00256
00257 event_contexts.back().delete_handler_index(foc_i);
00258 event_contexts.back().add_handler(foc_hand);
00259 }
00260 return thief_hand == hand;
00261 }
00262 }
00263 }
00264 return false;
00265 }
00266
00267 void pump()
00268 {
00269 SDL_PumpEvents();
00270
00271 pump_info info;
00272
00273
00274 static int last_mouse_down = -1;
00275 static int last_click_x = -1, last_click_y = -1;
00276
00277 SDL_Event temp_event;
00278 int poll_count = 0;
00279 int begin_ignoring = 0;
00280 std::vector< SDL_Event > events;
00281 while(SDL_PollEvent(&temp_event)) {
00282 ++poll_count;
00283 if(!begin_ignoring && temp_event.type == SDL_ACTIVEEVENT) {
00284 begin_ignoring = poll_count;
00285 } else if(begin_ignoring > 0 && SDL_EVENTMASK(temp_event.type)&INPUT_MASK) {
00286
00287 continue;
00288 }
00289 events.push_back(temp_event);
00290 }
00291 std::vector<SDL_Event>::iterator ev_it = events.begin();
00292 for(int i=1; i < begin_ignoring; ++i){
00293 if(SDL_EVENTMASK(ev_it->type)&INPUT_MASK) {
00294
00295 ev_it = events.erase(ev_it);
00296 } else {
00297 ++ev_it;
00298 }
00299 }
00300 std::vector<SDL_Event>::iterator ev_end = events.end();
00301 for(ev_it = events.begin(); ev_it != ev_end; ++ev_it){
00302 SDL_Event &event = *ev_it;
00303 switch(event.type) {
00304
00305 case SDL_ACTIVEEVENT: {
00306 SDL_ActiveEvent& ae = reinterpret_cast<SDL_ActiveEvent&>(event);
00307 if((ae.state & SDL_APPMOUSEFOCUS) != 0 || (ae.state & SDL_APPINPUTFOCUS) != 0) {
00308 cursor::set_focus(ae.gain != 0);
00309 }
00310 break;
00311 }
00312
00313
00314 case SDL_VIDEOEXPOSE: {
00315 update_whole_screen();
00316 break;
00317 }
00318
00319 case SDL_VIDEORESIZE: {
00320 const SDL_ResizeEvent* const resize = reinterpret_cast<SDL_ResizeEvent*>(&event);
00321 info.resize_dimensions.first = resize->w;
00322 info.resize_dimensions.second = resize->h;
00323 break;
00324 }
00325
00326 case SDL_MOUSEMOTION: {
00327
00328
00329 cursor::set_focus(true);
00330 raise_help_string_event(event.motion.x,event.motion.y);
00331 break;
00332 }
00333
00334 case SDL_MOUSEBUTTONDOWN: {
00335
00336
00337 cursor::set_focus(true);
00338 if(event.button.button == SDL_BUTTON_LEFT) {
00339 static const int DoubleClickTime = 500;
00340 static const int DoubleClickMaxMove = 3;
00341 if(last_mouse_down >= 0 && info.ticks() - last_mouse_down < DoubleClickTime &&
00342 abs(event.button.x - last_click_x) < DoubleClickMaxMove &&
00343 abs(event.button.y - last_click_y) < DoubleClickMaxMove) {
00344 SDL_UserEvent user_event;
00345 user_event.type = DOUBLE_CLICK_EVENT;
00346 user_event.code = 0;
00347 user_event.data1 = reinterpret_cast<void*>(event.button.x);
00348 user_event.data2 = reinterpret_cast<void*>(event.button.y);
00349 ::SDL_PushEvent(reinterpret_cast<SDL_Event*>(&user_event));
00350 }
00351 last_mouse_down = info.ticks();
00352 last_click_x = event.button.x;
00353 last_click_y = event.button.y;
00354 }
00355 break;
00356 }
00357
00358 #if defined(_X11) && !defined(__APPLE__)
00359 case SDL_SYSWMEVENT: {
00360
00361 handle_system_event(event);
00362 break;
00363 }
00364 #endif
00365
00366 case SDL_QUIT: {
00367 throw CVideo::quit();
00368 }
00369 }
00370
00371 if(event_contexts.empty() == false) {
00372
00373 const std::vector<handler*>& event_handlers = event_contexts.back().handlers;
00374
00375
00376
00377 for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) {
00378 event_handlers[i1]->handle_event(event);
00379 }
00380 }
00381 }
00382
00383
00384 for(size_t i1 = 0, i2 = pump_monitors.size(); i1 != i2 && i1 < pump_monitors.size(); ++i1) {
00385 pump_monitors[i1]->process(info);
00386 }
00387 }
00388
00389 void raise_process_event()
00390 {
00391 if(event_contexts.empty() == false) {
00392
00393 const std::vector<handler*>& event_handlers = event_contexts.back().handlers;
00394
00395
00396
00397 for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) {
00398 event_handlers[i1]->process_event();
00399 }
00400 }
00401 }
00402
00403 void raise_draw_event()
00404 {
00405 if(event_contexts.empty() == false) {
00406
00407 const std::vector<handler*>& event_handlers = event_contexts.back().handlers;
00408
00409
00410
00411 for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) {
00412 event_handlers[i1]->draw();
00413 }
00414 }
00415 }
00416
00417 void raise_volatile_draw_event()
00418 {
00419 if(event_contexts.empty() == false) {
00420
00421 const std::vector<handler*>& event_handlers = event_contexts.back().handlers;
00422
00423
00424
00425 for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) {
00426 event_handlers[i1]->volatile_draw();
00427 }
00428 }
00429 }
00430
00431 void raise_volatile_undraw_event()
00432 {
00433 if(event_contexts.empty() == false) {
00434
00435 const std::vector<handler*>& event_handlers = event_contexts.back().handlers;
00436
00437
00438
00439 for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) {
00440 event_handlers[i1]->volatile_undraw();
00441 }
00442 }
00443 }
00444
00445 void raise_help_string_event(int mousex, int mousey)
00446 {
00447 if(event_contexts.empty() == false) {
00448
00449 const std::vector<handler*>& event_handlers = event_contexts.back().handlers;
00450
00451 for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) {
00452 event_handlers[i1]->process_help_string(mousex,mousey);
00453 }
00454 }
00455 }
00456
00457 int discard(Uint32 event_mask)
00458 {
00459 int discard_count = 0;
00460 SDL_Event temp_event;
00461 std::vector< SDL_Event > keepers;
00462 SDL_Delay(10);
00463 while(SDL_PollEvent(&temp_event) > 0) {
00464 if((SDL_EVENTMASK(temp_event.type) & event_mask) == 0) {
00465 keepers.push_back( temp_event );
00466 } else {
00467 ++discard_count;
00468 }
00469 }
00470
00471
00472 for (unsigned int i=0; i < keepers.size(); ++i)
00473 {
00474 if(SDL_PushEvent(&keepers[i]) != 0) {
00475 ERR_GEN << "failed to return an event to the queue.";
00476 }
00477 }
00478
00479 return discard_count;
00480 }
00481
00482 int pump_info::ticks(unsigned *refresh_counter, unsigned refresh_rate) {
00483 if(!ticks_ && !(refresh_counter && ++*refresh_counter % refresh_rate)) {
00484 ticks_ = ::SDL_GetTicks();
00485 }
00486 return ticks_;
00487 }
00488
00489 }