diff --git a/src/events.cpp b/src/events.cpp index 7ce27274850..5ebfc87b6fa 100644 --- a/src/events.cpp +++ b/src/events.cpp @@ -141,6 +141,10 @@ void context::set_focus(const sdl_handler* ptr) //in that context. The current context is the one on the top of the stack std::deque event_contexts; +//add a global context for event handlers. Whichever object has joined this will always +//receive all events, regardless of the current context. +context global_context; + std::vector pump_monitors; } //end anon namespace @@ -185,7 +189,12 @@ event_context::~event_context() sdl_handler::~sdl_handler() { - leave(); + if (has_joined_) + leave(); + + if (has_joined_global_) + leave_global(); + #if !SDL_VERSION_ATLEAST(2, 0, 0) SDL_EnableUNICODE(unicode_); #endif @@ -227,6 +236,38 @@ void sdl_handler::leave() has_joined_ = false; } +void sdl_handler::join_global() +{ + if(has_joined_global_) { + leave_global(); // should not be in multiple event contexts + } + //join self + global_context.add_handler(this); + has_joined_global_ = true; + + //instruct members to join + sdl_handler_vector members = handler_members(); + if(!members.empty()) { + for(sdl_handler_vector::iterator i = members.begin(); i != members.end(); ++i) { + (*i)->join_global(); + } + } +} + +void sdl_handler::leave_global() +{ + sdl_handler_vector members = handler_members(); + if(!members.empty()) { + for(sdl_handler_vector::iterator i = members.begin(); i != members.end(); ++i) { + (*i)->leave_global(); + } + } + + global_context.remove_handler(this); + + has_joined_global_ = false; +} + void focus_handler(const sdl_handler* ptr) { if(event_contexts.empty() == false) { @@ -398,22 +439,14 @@ void pump() case SDL_WINDOWEVENT_EXPOSED: update_whole_screen(); - if (display::get_singleton()) - display::get_singleton()->redraw_everything(); break; - case SDL_WINDOWEVENT_RESIZED: { + case SDL_WINDOWEVENT_RESIZED: info.resize_dimensions.first = event.window.data1; info.resize_dimensions.second = event.window.data2; break; - case SDL_WINDOWEVENT_MOVED: - case SDL_WINDOWEVENT_CLOSE: - break; - default: - if (display::get_singleton()) - display::get_singleton()->redraw_everything(); - } } + break; #else case SDL_ACTIVEEVENT: { @@ -500,6 +533,11 @@ void pump() } } + const std::vector& event_handlers = global_context.handlers; + for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) { + event_handlers[i1]->handle_event(event); + } + if(event_contexts.empty() == false) { const std::vector& event_handlers = event_contexts.back().handlers; @@ -510,6 +548,7 @@ void pump() event_handlers[i1]->handle_event(event); } } + } //inform the pump monitors that an events::pump() has occurred diff --git a/src/events.hpp b/src/events.hpp index c6fcedaee34..aae7f562ccc 100644 --- a/src/events.hpp +++ b/src/events.hpp @@ -55,6 +55,9 @@ public: virtual void join(); /*joins the current event context*/ virtual void leave(); /*leave the event context*/ + virtual void join_global(); /*join the global event context*/ + virtual void leave_global(); /*leave the global event context*/ + protected: sdl_handler(const bool auto_join=true); virtual ~sdl_handler(); @@ -68,6 +71,7 @@ private: int unicode_; #endif bool has_joined_; + bool has_joined_global_; }; void focus_handler(const sdl_handler* ptr); diff --git a/src/video.cpp b/src/video.cpp index f1006353f47..dc20e6e14fc 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -60,10 +60,7 @@ void resize_monitor::process(events::pump_info &info) { } } #else - if(info.resize_dimensions.first > 0 && - info.resize_dimensions.second > 0 - && display::get_singleton()) - display::get_singleton()->redraw_everything(); + UNUSED(info); #endif } @@ -355,6 +352,41 @@ void update_whole_screen() { update_all = true; } + + +void CVideo::video_event_handler::handle_event(const SDL_Event &event) +{ +#if SDL_VERSION_ATLEAST(2, 0, 0) + if (event.type == SDL_WINDOWEVENT) { + switch (event.window.event) { + case SDL_WINDOWEVENT_RESIZED: + case SDL_WINDOWEVENT_RESTORED: + case SDL_WINDOWEVENT_SHOWN: + case SDL_WINDOWEVENT_EXPOSED: + if (display::get_singleton()) + display::get_singleton()->redraw_everything(); + break; +#if !SDL_VERSION_ATLEAST(2, 0, 4) && defined(_WIN32) + case SDL_WINDOWEVENT_FOCUS_GAINED: + + if(SDL_GetWindowFlags(*window) & SDL_WINDOW_MAXIMIZED) { + SDL_RestoreWindow(*window); + SDL_MaximizeWindow(*window); + } + if(SDL_GetWindowFlags(*window) & SDL_WINDOW_FULLSCREEN_DESKTOP) { + SDL_RestoreWindow(*window); + SDL_SetWindowFullscreen(*window, SDL_WINDOW_FULLSCREEN_DESKTOP); + } + break; +#endif + } + } +#else + UNUSED(event); +#endif +} + + CVideo::CVideo(FAKE_TYPES type) : #ifdef SDL_GPU shader_(), @@ -581,6 +613,7 @@ int CVideo::setMode( int x, int y, int bits_per_pixel, int flags ) // Note that x and y in this particular case refer to width and height of the window, not co-ordinates. window = new sdl::twindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, x, y, flags, SDL_RENDERER_SOFTWARE); window->set_minimum_size(preferences::min_allowed_width(), preferences::min_allowed_height()); + event_handler_.join_global(); } else { if(fullScreen) { window->full_screen(); diff --git a/src/video.hpp b/src/video.hpp index 9b51f5cfa24..e3e31fde321 100644 --- a/src/video.hpp +++ b/src/video.hpp @@ -218,6 +218,12 @@ class CVideo : private boost::noncopyable { private: + class video_event_handler : public events::sdl_handler { + public: + virtual void handle_event(const SDL_Event &event); + video_event_handler() : sdl_handler(false) {} + }; + void initSDL(); #ifdef SDL_GPU void update_overlay(SDL_Rect *rect = NULL); @@ -233,6 +239,8 @@ private: //if there is no display at all, but we 'fake' it for clients bool fake_screen_; + video_event_handler event_handler_; + //variables for help strings int help_string_;