[Add] Window focus and event routing.
This commit is contained in:
		
							parent
							
								
									8a902d3034
								
							
						
					
					
						commit
						2d79aba17a
					
				@ -81,9 +81,7 @@ int main(int argc, char** argv) {
 | 
			
		||||
    SDL_Event event;
 | 
			
		||||
    while(SDL_PollEvent(&event)) {
 | 
			
		||||
      if(event.type == SDL_EVENT_QUIT) { running = false; }
 | 
			
		||||
      /* Pass input to terminal. */
 | 
			
		||||
      desktop->handle_event(&event);
 | 
			
		||||
      term->handle_input(&event);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Clear screen. */
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,14 @@
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
#include "desktop.h"
 | 
			
		||||
#include <SDL3/SDL_events.h>
 | 
			
		||||
#include "gfx/shape_renderer.h"
 | 
			
		||||
#include "gfx/txt_renderer.h"
 | 
			
		||||
#include "ui/ui_window.h"
 | 
			
		||||
 | 
			
		||||
Desktop::Desktop(void) {}
 | 
			
		||||
Desktop::Desktop(void) {
 | 
			
		||||
  _focused_window = nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Desktop won't own the windows, so doesn't delete them. */
 | 
			
		||||
Desktop::~Desktop(void) {}
 | 
			
		||||
@ -13,11 +18,36 @@ void Desktop::add_window(UIWindow* window) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Desktop::handle_event(SDL_Event* event) {
 | 
			
		||||
  /* Just pass the even to all windows for the moment.
 | 
			
		||||
   * TODO: Only send event to the focused window.
 | 
			
		||||
   */
 | 
			
		||||
  for(auto win : _windows) {
 | 
			
		||||
    win->handle_event(event);
 | 
			
		||||
  if(event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
 | 
			
		||||
    int mouse_x = event->button.x;
 | 
			
		||||
    int mouse_y = event->button.y;
 | 
			
		||||
 | 
			
		||||
    /* Find the top-most window that was clicked. */
 | 
			
		||||
    for(int i = _windows.size()-1; i >= 0; --i) {
 | 
			
		||||
      if(_windows[i]->is_point_inside(mouse_x, mouse_y)) {
 | 
			
		||||
        /* If not focused, focus it. */
 | 
			
		||||
        if(_windows[i] != _focused_window) {
 | 
			
		||||
          if(_focused_window) {
 | 
			
		||||
            _focused_window->set_focused(false);
 | 
			
		||||
          }
 | 
			
		||||
          _focused_window = _windows[i];
 | 
			
		||||
          _focused_window->set_focused(true);
 | 
			
		||||
 | 
			
		||||
          /* Move window to the front. */
 | 
			
		||||
          _windows.erase(_windows.begin() + i);
 | 
			
		||||
          _windows.push_back(_focused_window);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if(_focused_window) {
 | 
			
		||||
    _focused_window->handle_event(event);
 | 
			
		||||
    Terminal* content = _focused_window->get_content();
 | 
			
		||||
    if(content && (event->type == SDL_EVENT_TEXT_INPUT || event->type == SDL_EVENT_KEY_DOWN)) {
 | 
			
		||||
      content->handle_input(event);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -18,4 +18,5 @@ public:
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  std::vector<UIWindow*> _windows;
 | 
			
		||||
  UIWindow* _focused_window;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -11,20 +11,35 @@ UIWindow::UIWindow(const char* title, int x, int y, int width, int height) {
 | 
			
		||||
  _height       = height;
 | 
			
		||||
  _content      = nullptr;
 | 
			
		||||
  _is_dragging  = false;
 | 
			
		||||
  _is_focused   = false; /* Not focused by default? */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UIWindow::set_content(Terminal* term) {
 | 
			
		||||
  _content = term;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UIWindow::set_focused(bool focused) {
 | 
			
		||||
  _is_focused = focused;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Terminal* UIWindow::get_content(void) {
 | 
			
		||||
  return _content;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool UIWindow::is_point_inside(int x, int y) {
 | 
			
		||||
  return (x >= _x && x <= _x + _width &&
 | 
			
		||||
          y >= _y && y <= _y + _height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UIWindow::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer,
 | 
			
		||||
                      int screen_height) {
 | 
			
		||||
  int title_bar_height = 30;
 | 
			
		||||
 | 
			
		||||
  /* Define colours. */
 | 
			
		||||
  float frame_color[]       = { 0.2f,  0.2f,  0.25f };
 | 
			
		||||
  float title_bar_color[]   = { 0.15f, 0.15f, 0.2f  };
 | 
			
		||||
  float title_text_color[]  = { 0.9f,  0.9f,  0.9f  };
 | 
			
		||||
  float frame_color[]             = { 0.2f,  0.2f,  0.25f };
 | 
			
		||||
  float title_bar_color[]         = { 0.15f, 0.15f, 0.2f  };
 | 
			
		||||
  float focused_title_bar_color[] = { 0.3f, 0.3f, 0.4f };
 | 
			
		||||
  float title_text_color[]        = { 0.9f,  0.9f,  0.9f  };
 | 
			
		||||
 | 
			
		||||
  /* Convert top-left coords to bottom-left for OpenGL. */
 | 
			
		||||
  int y_gl = screen_height - _y - _height;
 | 
			
		||||
@ -33,8 +48,13 @@ void UIWindow::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer,
 | 
			
		||||
  shape_renderer->draw_rect(_x, y_gl, _width, _height, frame_color);
 | 
			
		||||
 | 
			
		||||
  /* Draw title bar. */
 | 
			
		||||
  shape_renderer->draw_rect(_x, y_gl+_height-title_bar_height, _width, title_bar_height,
 | 
			
		||||
                            title_bar_color);
 | 
			
		||||
  if(_is_focused) {
 | 
			
		||||
    shape_renderer->draw_rect(_x, y_gl+_height-title_bar_height, _width, title_bar_height,
 | 
			
		||||
                              focused_title_bar_color);
 | 
			
		||||
  } else {
 | 
			
		||||
    shape_renderer->draw_rect(_x, y_gl+_height-title_bar_height, _width, title_bar_height,
 | 
			
		||||
                              title_bar_color);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Draw title text. */
 | 
			
		||||
  txt_renderer->render_text(_title.c_str(), _x+5, y_gl+_height-title_bar_height+8,
 | 
			
		||||
 | 
			
		||||
@ -12,12 +12,16 @@ public:
 | 
			
		||||
 | 
			
		||||
  void render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, int screen_height);
 | 
			
		||||
  void handle_event(SDL_Event* event);
 | 
			
		||||
  void set_focused(bool focused);
 | 
			
		||||
  bool is_point_inside(int x, int y);
 | 
			
		||||
  void set_content(Terminal* term);
 | 
			
		||||
  Terminal* get_content(void);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  int _x, _y, _width, _height;
 | 
			
		||||
  std::string _title;
 | 
			
		||||
  Terminal* _content;
 | 
			
		||||
  bool _is_focused; /* Managed by desktop. */
 | 
			
		||||
 | 
			
		||||
  bool _is_dragging;
 | 
			
		||||
  int _drag_offset_x, _drag_offset_y;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user