/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2020 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #ifndef XENIA_UI_WINDOW_H_ #define XENIA_UI_WINDOW_H_ #include #include #include "xenia/base/delegate.h" #include "xenia/ui/graphics_context.h" #include "xenia/ui/loop.h" #include "xenia/ui/menu_item.h" #include "xenia/ui/ui_event.h" #include "xenia/ui/window_listener.h" namespace xe { namespace ui { typedef void* NativePlatformHandle; typedef void* NativeWindowHandle; class ImGuiDrawer; class Window { public: static std::unique_ptr Create(Loop* loop, const std::string& title); virtual ~Window(); Loop* loop() const { return loop_; } virtual NativePlatformHandle native_platform_handle() const = 0; virtual NativeWindowHandle native_handle() const = 0; MenuItem* main_menu() const { return main_menu_.get(); } void set_main_menu(std::unique_ptr main_menu) { main_menu_ = std::move(main_menu); OnMainMenuChange(); } virtual void EnableMainMenu() = 0; virtual void DisableMainMenu() = 0; const std::string& title() const { return title_; } virtual bool set_title(const std::string& title) { if (title == title_) { return false; } title_ = title; return true; } virtual bool SetIcon(const void* buffer, size_t size) = 0; void ResetIcon() { SetIcon(nullptr, 0); } virtual bool CaptureMouse() = 0; virtual bool ReleaseMouse() = 0; virtual bool is_fullscreen() const { return false; } virtual void ToggleFullscreen(bool fullscreen) {} virtual bool is_bordered() const { return false; } virtual void set_bordered(bool enabled) {} virtual int get_dpi() const { return 96; } virtual float get_dpi_scale() const { return get_dpi() / 96.f; } bool has_focus() const { return has_focus_; } virtual void set_focus(bool value) { has_focus_ = value; } bool is_cursor_visible() const { return is_cursor_visible_; } virtual void set_cursor_visible(bool value) { is_cursor_visible_ = value; } int32_t width() const { return width_; } int32_t height() const { return height_; } int32_t scaled_width() const { return int32_t(width_ * get_dpi_scale()); } int32_t scaled_height() const { return int32_t(height_ * get_dpi_scale()); } virtual void Resize(int32_t width, int32_t height) { width_ = width; height_ = height; } virtual void Resize(int32_t left, int32_t top, int32_t right, int32_t bottom) { width_ = right - left; height_ = bottom - top; } GraphicsContext* context() const { return context_.get(); } ImGuiDrawer* imgui_drawer() const { return imgui_drawer_.get(); } bool is_imgui_input_enabled() const { return is_imgui_input_enabled_; } void set_imgui_input_enabled(bool value); void AttachListener(WindowListener* listener); void DetachListener(WindowListener* listener); virtual bool Initialize() { return true; } void set_context(std::unique_ptr context) { context_ = std::move(context); if (context_) { MakeReady(); } } void Layout(); virtual void Invalidate(); virtual void Close() = 0; public: Delegate on_closing; Delegate on_closed; Delegate on_painting; Delegate on_paint; Delegate on_painted; Delegate on_context_lost; Delegate on_file_drop; Delegate on_key_down; Delegate on_key_up; Delegate on_key_char; Delegate on_mouse_down; Delegate on_mouse_move; Delegate on_mouse_up; Delegate on_mouse_wheel; protected: Window(Loop* loop, const std::string& title); void ForEachListener(std::function fn); void TryForEachListener(std::function fn); virtual bool MakeReady(); virtual bool OnCreate(); virtual void OnMainMenuChange(); virtual void OnClose(); virtual void OnDestroy(); virtual void OnDpiChanged(UIEvent* e); virtual void OnResize(UIEvent* e); virtual void OnLayout(UIEvent* e); virtual void OnPaint(UIEvent* e); virtual void OnFileDrop(FileDropEvent* e); virtual void OnVisible(UIEvent* e); virtual void OnHidden(UIEvent* e); virtual void OnGotFocus(UIEvent* e); virtual void OnLostFocus(UIEvent* e); virtual void OnKeyDown(KeyEvent* e); virtual void OnKeyUp(KeyEvent* e); virtual void OnKeyChar(KeyEvent* e); virtual void OnMouseDown(MouseEvent* e); virtual void OnMouseMove(MouseEvent* e); virtual void OnMouseUp(MouseEvent* e); virtual void OnMouseWheel(MouseEvent* e); void OnKeyPress(KeyEvent* e, bool is_down, bool is_char); Loop* loop_ = nullptr; std::unique_ptr main_menu_; std::string title_; int32_t width_ = 0; int32_t height_ = 0; bool has_focus_ = true; bool is_cursor_visible_ = true; bool is_imgui_input_enabled_ = false; std::unique_ptr context_; std::unique_ptr imgui_drawer_; uint32_t frame_count_ = 0; uint32_t fps_ = 0; uint64_t fps_update_time_ticks_ = 0; uint64_t fps_frame_count_ = 0; uint64_t last_paint_time_ticks_ = 0; bool modifier_shift_pressed_ = false; bool modifier_cntrl_pressed_ = false; bool modifier_alt_pressed_ = false; bool modifier_super_pressed_ = false; // All currently-attached listeners that get event notifications. bool in_listener_loop_ = false; std::vector listeners_; std::vector pending_listener_attaches_; std::vector pending_listener_detaches_; }; } // namespace ui } // namespace xe #endif // XENIA_UI_WINDOW_H_