Fix bug #24209 and add a global event scope
This adds a global event scope that an sdl_handler can register to in order to receive all current events, regardless of the current scope. Care should be taken to not be registerd in a local event context and the global context at the same time as it will lead to the event handler potentially being invoked twice. This also adds the workaround needed for #24209 in the new event handler in the video class.
This commit is contained in:
parent
6c0ecb6785
commit
544b61534c
4 changed files with 99 additions and 15 deletions
|
@ -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<context> 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_monitor*> 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<sdl_handler*>& 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<sdl_handler*>& 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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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_;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue