diff --git a/client/src/terminal.cpp b/client/src/terminal.cpp index 405f181..d55c483 100644 --- a/client/src/terminal.cpp +++ b/client/src/terminal.cpp @@ -125,6 +125,8 @@ void Terminal::render(const RenderContext& context, int x, int y_screen, int y_g /* Draw History. */ for(size_t i = _scroll_offset; i < _history.size(); ++i) { float line_y_pos = y_screen + padding + ((i - _scroll_offset) * line_height); + /* Culling: If line is already below the view, stop. */ + if(line_y_pos > y_screen + height) { break; } context.ui_renderer->render_text(_history[i].c_str(), x+padding, line_y_pos+18, white); } diff --git a/client/src/ui/desktop.cpp b/client/src/ui/desktop.cpp index 8fc7f51..86f66db 100644 --- a/client/src/ui/desktop.cpp +++ b/client/src/ui/desktop.cpp @@ -214,9 +214,27 @@ void Desktop::render(const RenderContext& context) { context.ui_renderer->flush_text(); /* Pass 2: Windows Render in order, last window is top-most. */ - for(const auto& win : _windows) { - if(!win->is_minimized()) { - win.get()->render(context); + for(size_t i = 0; i < _windows.size(); ++i) { + auto& win_i = _windows[i]; + if(win_i->is_minimized()) continue; + + bool is_occluded = false; + Rect rect_i = win_i->get_rect(); + + /* Check against all windows on top of this one. */ + for(size_t j = i+1; j < _windows.size(); ++j) { + auto& win_j = _windows[j]; + if(win_j->is_minimized()) continue; + + Rect rect_j = win_j->get_rect(); + if(rect_i.x >= rect_j.x && (rect_i.x + rect_i.w) <= (rect_j.x + rect_j.w) && + rect_i.y >= rect_j.y && (rect_i.y + rect_i.h) <= (rect_j.y + rect_j.h)) { + is_occluded = true; + break; + } + } + if(!is_occluded) { + win_i->render(context); } } diff --git a/client/src/ui/text_view.cpp b/client/src/ui/text_view.cpp index cf418aa..e302a75 100644 --- a/client/src/ui/text_view.cpp +++ b/client/src/ui/text_view.cpp @@ -82,6 +82,14 @@ void TextView::render(UIRenderer* ui_renderer, int x, int y, int width, int heig float current_y = y; for(size_t i = _scroll_offset; i < _buffer->get_line_count(); ++i) { + /* + * Culling: If the top of the current line is already below the bottom of the + * view, we can stop rendering completely. + */ + if(current_y > y + height) { + break; + } + std::string line = _buffer->get_line(i); if(show_cursor && (int)i == cursor_pos.row) { diff --git a/client/src/ui/ui_window.cpp b/client/src/ui/ui_window.cpp index 3ee948c..2cd60c6 100644 --- a/client/src/ui/ui_window.cpp +++ b/client/src/ui/ui_window.cpp @@ -43,6 +43,10 @@ const std::string& UIWindow::get_title(void) const { return _title; } +Rect UIWindow::get_rect(void) const { + return { _x, _y, _width, _height }; +} + bool UIWindow::is_mouse_over_resize_handle(int mouse_x, int mouse_y) const { return (mouse_x >= _x + _width - _resize_margin && mouse_x <= _x + _width && mouse_y >= _y + _height - _resize_margin && diff --git a/client/src/ui/ui_window.h b/client/src/ui/ui_window.h index 67b9d91..2f00b14 100644 --- a/client/src/ui/ui_window.h +++ b/client/src/ui/ui_window.h @@ -43,6 +43,7 @@ public: IWindowContent* get_content(void); bool is_mouse_over_resize_handle(int mouse_x, int mouse_y) const; const std::string& get_title(void) const; + Rect get_rect(void) const; private: friend class Taskbar; /* Allow taskbar to access private members. */