[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