[Fix] Correct window event handling and Z-ordering.
Resolves a bug where mouse clicks would "pass through" the top-most window and incorrectly trigger events on windows visually behind it.
This commit is contained in:
		
							parent
							
								
									69eee6da8f
								
							
						
					
					
						commit
						d602a8f1d4
					
				@ -70,17 +70,32 @@ void Desktop::_set_focused_window(UIWindow* window) {
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Unfocus old window. */
 | 
				
			||||||
  if(_focused_window) {
 | 
					  if(_focused_window) {
 | 
				
			||||||
    _focused_window->set_focused(false);
 | 
					    _focused_window->set_focused(false);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Set new focused window. */
 | 
				
			||||||
  _focused_window = window;
 | 
					  _focused_window = window;
 | 
				
			||||||
  if(_focused_window) {
 | 
					  if(_focused_window) {
 | 
				
			||||||
    _focused_window->set_focused(true);
 | 
					    _focused_window->set_focused(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Move newly focused window to end of vector so it's rendered on top. */
 | 
				
			||||||
 | 
					    auto it = std::find_if(_windows.begin(), _windows.end(),
 | 
				
			||||||
 | 
					                           [window](const std::unique_ptr<UIWindow>& p) {
 | 
				
			||||||
 | 
					                             return p.get() == window;
 | 
				
			||||||
 | 
					                           });
 | 
				
			||||||
 | 
					    if(it != _windows.end()) {
 | 
				
			||||||
 | 
					      std::rotate(it, it+1, _windows.end());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Desktop::handle_event(SDL_Event* event, int screen_width, int screen_height) {
 | 
					void Desktop::handle_event(SDL_Event* event, int screen_width, int screen_height) {
 | 
				
			||||||
 | 
					  /* Let focused window handle all events first. */
 | 
				
			||||||
 | 
					  if(_focused_window) {
 | 
				
			||||||
 | 
					    _focused_window->handle_event(event, screen_width, screen_height, _taskbar->get_height());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  if(event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
 | 
					  if(event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
 | 
				
			||||||
    int mouse_x = event->button.x;
 | 
					    int mouse_x = event->button.x;
 | 
				
			||||||
    int mouse_y = event->button.y;
 | 
					    int mouse_y = event->button.y;
 | 
				
			||||||
@ -91,15 +106,20 @@ void Desktop::handle_event(SDL_Event* event, int screen_width, int screen_height
 | 
				
			|||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Find the top-most window that was clicked. */
 | 
					    /* If click no on focused window, find which window should receive focus. */
 | 
				
			||||||
 | 
					    bool click_on_window = false;
 | 
				
			||||||
    for(int i = _windows.size()-1; i >= 0; --i) {
 | 
					    for(int i = _windows.size()-1; i >= 0; --i) {
 | 
				
			||||||
      if(_windows[i].get()->is_point_inside(mouse_x, mouse_y)) {
 | 
					      if(_windows[i].get()->is_point_inside(mouse_x, mouse_y)) {
 | 
				
			||||||
        if(!_windows[i]->is_minimized()) {
 | 
					        if(!_windows[i]->is_minimized()) {
 | 
				
			||||||
          _set_focused_window(_windows[i].get());
 | 
					          _set_focused_window(_windows[i].get());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        click_on_window = true;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if(!click_on_window) {
 | 
				
			||||||
 | 
					      _set_focused_window(nullptr);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  } else if(event->type == SDL_EVENT_MOUSE_BUTTON_UP) {
 | 
					  } else if(event->type == SDL_EVENT_MOUSE_BUTTON_UP) {
 | 
				
			||||||
    if(_taskbar->is_start_button_clicked(event, screen_height)) {
 | 
					    if(_taskbar->is_start_button_clicked(event, screen_height)) {
 | 
				
			||||||
      _launcher_is_open = !_launcher_is_open;
 | 
					      _launcher_is_open = !_launcher_is_open;
 | 
				
			||||||
@ -131,22 +151,14 @@ void Desktop::handle_event(SDL_Event* event, int screen_width, int screen_height
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  } else if(event->type == SDL_EVENT_MOUSE_MOTION) {
 | 
					  } else if(event->type == SDL_EVENT_MOUSE_MOTION) {
 | 
				
			||||||
    bool on_resize_handle = false;
 | 
					    /* Update cursor if hovering over any resize handle. */
 | 
				
			||||||
    /* Iterate backwards since top-most windows are at the end. */
 | 
					 | 
				
			||||||
    for(int i = _windows.size() - 1; i >= 0; --i) {
 | 
					    for(int i = _windows.size() - 1; i >= 0; --i) {
 | 
				
			||||||
      if(_windows[i]->is_mouse_over_resize_handle(event->motion.x, 
 | 
					      if(_windows[i]->is_mouse_over_resize_handle(event->motion.x, 
 | 
				
			||||||
                                                  event->motion.y)) {
 | 
					                                                  event->motion.y)) {
 | 
				
			||||||
        on_resize_handle = true;
 | 
					        return CursorManager::set_cursor(CursorType::RESIZE_NWSE);
 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    CursorManager::set_cursor(on_resize_handle ? CursorType::RESIZE_NWSE
 | 
					    CursorManager::set_cursor(CursorType::ARROW);
 | 
				
			||||||
                                               : CursorType::ARROW);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if(_focused_window) {
 | 
					 | 
				
			||||||
    _focused_window->handle_event(event, screen_width, screen_height,
 | 
					 | 
				
			||||||
                                  _taskbar->get_height());
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -201,15 +213,12 @@ void Desktop::render(const RenderContext& context) {
 | 
				
			|||||||
  _render_wallpaper(context.ui_renderer);
 | 
					  _render_wallpaper(context.ui_renderer);
 | 
				
			||||||
  context.ui_renderer->flush_text();
 | 
					  context.ui_renderer->flush_text();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Pass 2: Windows (back to front). */
 | 
					  /* Pass 2: Windows Render in order, last window is top-most. */
 | 
				
			||||||
  for(const auto& win : _windows) {
 | 
					  for(const auto& win : _windows) {
 | 
				
			||||||
    if(win.get() != _focused_window && !win->is_minimized()) {
 | 
					    if(!win->is_minimized()) {
 | 
				
			||||||
      win.get()->render(context);
 | 
					      win.get()->render(context);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if(_focused_window && !_focused_window->is_minimized()) {
 | 
					 | 
				
			||||||
    _focused_window->render(context);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Pass 3: Top-level static UI (taskbar, Launcher, etc.). */
 | 
					  /* Pass 3: Top-level static UI (taskbar, Launcher, etc.). */
 | 
				
			||||||
  context.ui_renderer->begin_text();
 | 
					  context.ui_renderer->begin_text();
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user