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