Fix window focus bugs for Windows

This commit is contained in:
2025-04-21 11:20:02 -05:00
parent 780e722076
commit 07c15dc1e7
9 changed files with 43 additions and 21 deletions

View File

@@ -764,9 +764,6 @@ void cDialog::handle_one_event(const sf::Event& currentEvent, cFramerateLimiter&
for(int i = dialog_stack.size() - 1; i >= 0; --i){ for(int i = dialog_stack.size() - 1; i >= 0; --i){
makeFrontWindow(*(dialog_stack[i])); makeFrontWindow(*(dialog_stack[i]));
} }
// that generates more LostFocus and GainedFocus event(s)
sf::Event evt;
while(pollEvent(win, evt));
} }
BOOST_FALLTHROUGH; BOOST_FALLTHROUGH;
case sf::Event::MouseMoved:{ case sf::Event::MouseMoved:{

View File

@@ -692,7 +692,7 @@ void init_mini_map() {
mini_map().setVisible(false); mini_map().setVisible(false);
map_visible=false; map_visible=false;
setWindowFloating(mini_map(), true); setWindowFloating(mini_map(), true);
makeFrontWindow(mainPtr()); makeFrontWindow(mainPtr(), mini_map());
// Create and initialize map gworld // Create and initialize map gworld
if(!map_gworld().create(384, 384)) { if(!map_gworld().create(384, 384)) {

View File

@@ -233,13 +233,10 @@ void dialog_lost_focus(sf::RenderWindow& win) {
void dialog_gained_focus(sf::RenderWindow& win) { void dialog_gained_focus(sf::RenderWindow& win) {
setWindowFloating(mini_map(), true); setWindowFloating(mini_map(), true);
makeFrontWindow(mainPtr());
if(map_visible){ if(map_visible){
makeFrontWindow(mini_map()); makeFrontWindow(mini_map());
} }
// that generates more LostFocus and GainedFocus event(s) makeFrontWindow(mainPtr(), mini_map());
sf::Event evt;
while(pollEvent(win, evt));
} }
// Comment this line out for exact exception callstacks: // Comment this line out for exact exception callstacks:
@@ -1294,8 +1291,8 @@ void handle_events() {
setWindowFloating(mini_map(), true); setWindowFloating(mini_map(), true);
if(map_visible){ if(map_visible){
makeFrontWindow(mini_map()); makeFrontWindow(mini_map());
makeFrontWindow(mainPtr());
} }
makeFrontWindow(mainPtr(), mini_map());
} }
main_window_lost_focus = main_window_gained_focus = main_window_lost_focus = main_window_gained_focus =
@@ -1375,7 +1372,7 @@ void handle_one_event(const sf::Event& event, cFramerateLimiter& fps_limiter) {
case sf::Event::GainedFocus: case sf::Event::GainedFocus:
check_window_moved(mainPtr(), last_window_x, last_window_y, "MainWindow"); check_window_moved(mainPtr(), last_window_x, last_window_y, "MainWindow");
main_window_gained_focus = true; main_window_gained_focus = true;
makeFrontWindow(mainPtr()); makeFrontWindow(mainPtr(), mini_map());
change_cursor(); change_cursor();
return; return;
@@ -1415,7 +1412,7 @@ void handle_one_minimap_event(const sf::Event& event) {
}else if(event.type == sf::Event::GainedFocus){ }else if(event.type == sf::Event::GainedFocus){
map_window_gained_focus = true; map_window_gained_focus = true;
check_window_moved(mini_map(), last_map_x, last_map_y, "MapWindow"); check_window_moved(mini_map(), last_map_x, last_map_y, "MapWindow");
makeFrontWindow(mainPtr()); makeFrontWindow(mainPtr(), mini_map());
}else if(event.type == sf::Event::LostFocus){ }else if(event.type == sf::Event::LostFocus){
map_window_lost_focus = true; map_window_lost_focus = true;
}else if(event.type == sf::Event::MouseMoved){ }else if(event.type == sf::Event::MouseMoved){

View File

@@ -1575,7 +1575,7 @@ void display_map() {
mini_map().setVisible(true); mini_map().setVisible(true);
map_visible = true; map_visible = true;
draw_map(true); draw_map(true);
makeFrontWindow(mainPtr()); makeFrontWindow(mainPtr(), mini_map());
set_cursor(sword_curs); set_cursor(sword_curs);
} }

View File

@@ -90,3 +90,25 @@ bool check_window_moved(sf::RenderWindow& win, int& winLastX, int& winLastY, std
winLastY = winPosition.y; winLastY = winPosition.y;
return moved; return moved;
} }
void makeFrontWindow(sf::Window& win) {
static sf::Event evt;
_makeFrontWindow(win);
// Discard GainedFocus events generated by our own meddling:
while(pollEvent(win, evt));
}
void makeFrontWindow(sf::Window& win, sf::Window& prev) {
static sf::Event evt;
_makeFrontWindow(win);
// Discard GainedFocus and LostFocus events generated by our own meddling:
while(pollEvent(win, evt));
while(pollEvent(prev, evt));
}
void setWindowFloating(sf::Window& win, bool floating) {
static sf::Event evt;
_setWindowFloating(win, floating);
// Discard GainedFocus and LostFocus events generated by our own meddling:
while(pollEvent(win, evt));
}

View File

@@ -23,8 +23,14 @@ sf::RenderWindow& mainPtr();
char keyToChar(sf::Keyboard::Key key, bool isShift); char keyToChar(sf::Keyboard::Key key, bool isShift);
// public-facing overloads which discard events generated by the operation:
void makeFrontWindow(sf::Window& win); void makeFrontWindow(sf::Window& win);
void makeFrontWindow(sf::Window& win, sf::Window& prev);
void setWindowFloating(sf::Window& win, bool floating); void setWindowFloating(sf::Window& win, bool floating);
// OS-specific implementations:
void _makeFrontWindow(sf::Window& win);
void _setWindowFloating(sf::Window& win, bool floating);
// Necessary wrapper for sf::Window.pollEvent() // Necessary wrapper for sf::Window.pollEvent()
bool pollEvent(sf::Window& win, sf::Event& event); bool pollEvent(sf::Window& win, sf::Event& event);

View File

@@ -91,10 +91,10 @@ std::string get_os_version() {
return version.str(); return version.str();
} }
void makeFrontWindow(sf::Window& win) { void _makeFrontWindow(sf::Window& win) {
} }
void setWindowFloating(sf::Window& win, bool floating) { void _setWindowFloating(sf::Window& win, bool floating) {
// Code adapted from <http://stackoverflow.com/a/16235920> // Code adapted from <http://stackoverflow.com/a/16235920>
auto display = XOpenDisplay(NULL); auto display = XOpenDisplay(NULL);
Atom wmStateAbove = XInternAtom(display, "_NET_WM_STATE_ABOVE", true); Atom wmStateAbove = XInternAtom(display, "_NET_WM_STATE_ABOVE", true);

View File

@@ -83,7 +83,7 @@ std::string get_os_version() {
return os.str(); return os.str();
} }
void makeFrontWindow(sf::Window& win) { void _makeFrontWindow(sf::Window& win) {
sf::WindowHandle handle = win.getSystemHandle(); sf::WindowHandle handle = win.getSystemHandle();
id nsHandle = id(handle); id nsHandle = id(handle);
if([nsHandle isKindOfClass: [NSWindow class]]) { if([nsHandle isKindOfClass: [NSWindow class]]) {
@@ -92,7 +92,7 @@ void makeFrontWindow(sf::Window& win) {
} }
} }
void setWindowFloating(sf::Window& win, bool floating) { void _setWindowFloating(sf::Window& win, bool floating) {
sf::WindowHandle handle = win.getSystemHandle(); sf::WindowHandle handle = win.getSystemHandle();
id nsHandle = id(handle); id nsHandle = id(handle);
if([nsHandle isKindOfClass: [NSWindow class]]) { if([nsHandle isKindOfClass: [NSWindow class]]) {

View File

@@ -144,15 +144,15 @@ std::string get_os_version() {
return version.str(); return version.str();
} }
void makeFrontWindow(sf::Window& win) { void _makeFrontWindow(sf::Window& win) {
HWND win_handle = win.getSystemHandle(); HWND win_handle = win.getSystemHandle();
BringWindowToTop(win_handle); BringWindowToTop(win_handle);
} }
void setWindowFloating(sf::Window& win, bool floating) { void _setWindowFloating(sf::Window& win, bool floating) {
HWND win_handle = win.getSystemHandle(); HWND win_handle = win.getSystemHandle();
UINT flags = SWP_NOMOVE | SWP_NOSIZE; UINT flags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE;
HWND newPos = floating ? HWND_TOPMOST : HWND_TOP; HWND newPos = floating ? HWND_TOPMOST : HWND_BOTTOM;
// The flags param specifies that these 0's are ignored. // The flags param specifies that these 0's are ignored.
SetWindowPos(win_handle, newPos, 0, 0, 0, 0, flags); SetWindowPos(win_handle, newPos, 0, 0, 0, 0, flags);
} }