void pump() { if(boost::this_thread::get_id() != main_thread) { // Can only call this on the main thread! return; } SDL_PumpEvents(); peek_for_resize(); pump_info info; //used to keep track of double click events static int last_mouse_down = -1; static int last_click_x = -1, last_click_y = -1; SDL_Event temp_event; int poll_count = 0; int begin_ignoring = 0; std::vector< SDL_Event > events; while(SDL_PollEvent(&temp_event)) { ++poll_count; peek_for_resize(); if(!begin_ignoring && temp_event.type == SDL_WINDOWEVENT && (temp_event.window.event == SDL_WINDOWEVENT_ENTER || temp_event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED)) { begin_ignoring = poll_count; } else if(begin_ignoring > 0 && is_input(temp_event)) { //ignore user input events that occurred after the window was activated continue; } events.push_back(temp_event); } std::vector<SDL_Event>::iterator ev_it = events.begin(); for(int i=1; i < begin_ignoring; ++i){ if(is_input(*ev_it)) { //ignore user input events that occurred before the window was activated ev_it = events.erase(ev_it); } else { ++ev_it; } } std::vector<SDL_Event>::iterator ev_end = events.end(); bool resize_found = false; for(ev_it = events.begin(); ev_it != ev_end; ++ev_it){ SDL_Event &event = *ev_it; if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED) { resize_found = true; last_resize_event = event; last_resize_event_used = false; } } // remove all inputs, draw events and only keep the last of the resize events // This will turn horrible after ~38 days when the Uint32 wraps. if (resize_found || SDL_GetTicks() <= last_resize_event.window.timestamp + resize_timeout) { events.erase(std::remove_if(events.begin(), events.end(), remove_on_resize), events.end()); } else if(SDL_GetTicks() > last_resize_event.window.timestamp + resize_timeout && !last_resize_event_used) { events.insert(events.begin(), last_resize_event); last_resize_event_used = true; } ev_end = events.end(); for(ev_it = events.begin(); ev_it != ev_end; ++ev_it){ for (context& c : event_contexts) { c.add_staging_handlers(); } SDL_Event &event = *ev_it; switch(event.type) { case SDL_WINDOWEVENT: switch(event.window.event) { case SDL_WINDOWEVENT_ENTER: case SDL_WINDOWEVENT_FOCUS_GAINED: cursor::set_focus(1); break; case SDL_WINDOWEVENT_LEAVE: case SDL_WINDOWEVENT_FOCUS_LOST: cursor::set_focus(1); break; case SDL_WINDOWEVENT_RESIZED: info.resize_dimensions.first = event.window.data1; info.resize_dimensions.second = event.window.data2; break; } //make sure this runs in it's own scope. { flip_locker flip_lock(CVideo::get_singleton()); for( std::deque<context>::iterator i = event_contexts.begin() ; i != event_contexts.end(); ++i) { const handler_list& event_handlers = (*i).handlers; for(auto handler : event_handlers) { handler->handle_window_event(event); } } const handler_list& event_handlers = event_contexts.front().handlers; for(auto handler : event_handlers) { handler->handle_window_event(event); } } //This event was just distributed, don't re-distribute. continue; case SDL_MOUSEMOTION: { //always make sure a cursor is displayed if the //mouse moves or if the user clicks cursor::set_focus(true); raise_help_string_event(event.motion.x,event.motion.y); break; } case SDL_MOUSEBUTTONDOWN: { //always make sure a cursor is displayed if the //mouse moves or if the user clicks cursor::set_focus(true); if(event.button.button == SDL_BUTTON_LEFT) { static const int DoubleClickTime = 500; static const int DoubleClickMaxMove = 3; if(last_mouse_down >= 0 && info.ticks() - last_mouse_down < DoubleClickTime && abs(event.button.x - last_click_x) < DoubleClickMaxMove && abs(event.button.y - last_click_y) < DoubleClickMaxMove) { SDL_UserEvent user_event; user_event.type = DOUBLE_CLICK_EVENT; user_event.code = 0; user_event.data1 = reinterpret_cast<void*>(event.button.x); user_event.data2 = reinterpret_cast<void*>(event.button.y); ::SDL_PushEvent(reinterpret_cast<SDL_Event*>(&user_event)); } last_mouse_down = info.ticks(); last_click_x = event.button.x; last_click_y = event.button.y; } break; } case DRAW_ALL_EVENT: { flip_locker flip_lock(CVideo::get_singleton()); /* iterate backwards as the most recent things will be at the top */ for( std::deque<context>::iterator i = event_contexts.begin() ; i != event_contexts.end(); ++i) { handler_list& event_handlers = (*i).handlers; for( handler_list::iterator i1 = event_handlers.begin(); i1 != event_handlers.end(); ++i1) { (*i1)->handle_event(event); } } continue; //do not do further handling here } #ifndef __APPLE__ case SDL_KEYDOWN: { if(event.key.keysym.sym == SDLK_F4 && (event.key.keysym.mod == KMOD_RALT || event.key.keysym.mod == KMOD_LALT)) { quit_confirmation::quit_to_desktop(); continue; // this event is already handled } break; } #endif #if defined(_X11) && !defined(__APPLE__) case SDL_SYSWMEVENT: { //clipboard support for X11 desktop::clipboard::handle_system_event(event); break; } #endif #if defined _WIN32 case SDL_SYSWMEVENT: { windows_tray_notification::handle_system_event(event); break; } #endif case SDL_QUIT: { quit_confirmation::quit_to_desktop(); continue; //this event is already handled. } } const handler_list& global_handlers = event_contexts.front().handlers; for(auto handler : global_handlers) { handler->handle_event(event); } if(event_contexts.empty() == false) { const handler_list& event_handlers = event_contexts.back().handlers; for(auto handler : event_handlers) { handler->handle_event(event); } } } //inform the pump monitors that an events::pump() has occurred for(size_t i1 = 0, i2 = pump_monitors.size(); i1 != i2 && i1 < pump_monitors.size(); ++i1) { pump_monitors[i1]->process(info); } }
void pump() { SDL_PumpEvents(); #if SDL_VERSION_ATLEAST(2,0,0) peek_for_resize(); #endif pump_info info; //used to keep track of double click events static int last_mouse_down = -1; static int last_click_x = -1, last_click_y = -1; SDL_Event temp_event; int poll_count = 0; int begin_ignoring = 0; std::vector< SDL_Event > events; while(SDL_PollEvent(&temp_event)) { ++poll_count; #if SDL_VERSION_ATLEAST(2, 0, 0) peek_for_resize(); if(!begin_ignoring && temp_event.type == SDL_WINDOWEVENT && (temp_event.window.event == SDL_WINDOWEVENT_ENTER || temp_event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED)) #else if(!begin_ignoring && temp_event.type == SDL_ACTIVEEVENT) #endif { begin_ignoring = poll_count; } else if(begin_ignoring > 0 && is_input(temp_event)) { //ignore user input events that occurred after the window was activated continue; } events.push_back(temp_event); } std::vector<SDL_Event>::iterator ev_it = events.begin(); for(int i=1; i < begin_ignoring; ++i){ if(is_input(*ev_it)) { //ignore user input events that occurred before the window was activated ev_it = events.erase(ev_it); } else { ++ev_it; } } std::vector<SDL_Event>::iterator ev_end = events.end(); for(ev_it = events.begin(); ev_it != ev_end; ++ev_it){ SDL_Event &event = *ev_it; switch(event.type) { #if SDL_VERSION_ATLEAST(2, 0, 0) case SDL_WINDOWEVENT: switch(event.window.event) { case SDL_WINDOWEVENT_ENTER: case SDL_WINDOWEVENT_FOCUS_GAINED: cursor::set_focus(1); break; case SDL_WINDOWEVENT_LEAVE: case SDL_WINDOWEVENT_FOCUS_LOST: cursor::set_focus(1); break; case SDL_WINDOWEVENT_EXPOSED: update_whole_screen(); break; case SDL_WINDOWEVENT_RESIZED: { info.resize_dimensions.first = event.window.data1; info.resize_dimensions.second = event.window.data2; break; } } break; #else case SDL_ACTIVEEVENT: { SDL_ActiveEvent& ae = reinterpret_cast<SDL_ActiveEvent&>(event); if((ae.state & SDL_APPMOUSEFOCUS) != 0 || (ae.state & SDL_APPINPUTFOCUS) != 0) { cursor::set_focus(ae.gain != 0); } break; } //if the window must be redrawn, update the entire screen case SDL_VIDEOEXPOSE: update_whole_screen(); break; case SDL_VIDEORESIZE: { const SDL_ResizeEvent* const resize = reinterpret_cast<SDL_ResizeEvent*>(&event); info.resize_dimensions.first = resize->w; info.resize_dimensions.second = resize->h; break; } #endif case SDL_MOUSEMOTION: { //always make sure a cursor is displayed if the //mouse moves or if the user clicks cursor::set_focus(true); raise_help_string_event(event.motion.x,event.motion.y); break; } case SDL_MOUSEBUTTONDOWN: { //always make sure a cursor is displayed if the //mouse moves or if the user clicks cursor::set_focus(true); if(event.button.button == SDL_BUTTON_LEFT) { static const int DoubleClickTime = 500; static const int DoubleClickMaxMove = 3; if(last_mouse_down >= 0 && info.ticks() - last_mouse_down < DoubleClickTime && abs(event.button.x - last_click_x) < DoubleClickMaxMove && abs(event.button.y - last_click_y) < DoubleClickMaxMove) { SDL_UserEvent user_event; user_event.type = DOUBLE_CLICK_EVENT; user_event.code = 0; user_event.data1 = reinterpret_cast<void*>(event.button.x); user_event.data2 = reinterpret_cast<void*>(event.button.y); ::SDL_PushEvent(reinterpret_cast<SDL_Event*>(&user_event)); } last_mouse_down = info.ticks(); last_click_x = event.button.x; last_click_y = event.button.y; } break; } #ifndef __APPLE__ case SDL_KEYDOWN: { if(event.key.keysym.sym == SDLK_F4 && (event.key.keysym.mod == KMOD_RALT || event.key.keysym.mod == KMOD_LALT)) { quit_confirmation::quit(); continue; // this event is already handled } break; } #endif #if defined(_X11) && !defined(__APPLE__) case SDL_SYSWMEVENT: { //clipboard support for X11 desktop::clipboard::handle_system_event(event); break; } #endif #if defined _WIN32 case SDL_SYSWMEVENT: { windows_tray_notification::handle_system_event(event); break; } #endif case SDL_QUIT: { quit_confirmation::quit(); continue; //this event is already handled. } } if(event_contexts.empty() == false) { const std::vector<sdl_handler*>& event_handlers = event_contexts.back().handlers; //events may cause more event handlers to be added and/or removed, //so we must use indexes instead of iterators here. for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) { event_handlers[i1]->handle_event(event); } } } //inform the pump monitors that an events::pump() has occurred for(size_t i1 = 0, i2 = pump_monitors.size(); i1 != i2 && i1 < pump_monitors.size(); ++i1) { pump_monitors[i1]->process(info); } }