1 /** \file SDLGUI.h \brief Contains SDLGUI, the input driver for using SDL with 2 GG. */ 3 4 #ifndef _SDLGUI_h_ 5 #define _SDLGUI_h_ 6 7 #include <GG/GUI.h> 8 9 #include <SDL2/SDL.h> 10 #include <SDL2/SDL_keyboard.h> 11 12 13 class Framebuffer; 14 15 /** \brief This is an abstract singleton class that represents the GUI 16 framework of an SDL OpenGL application. 17 18 <p>Usage: 19 20 <br>Any application including an object of this class should declare that 21 object as a local variable in main(). The name of this variable will 22 herein be assumed to be "gui". It should be allocated on the stack; if it 23 is created dynamically a leak may occur. SDLGUI is designed so the main() 24 of the application can consist of just the one line "gui();". 25 26 <p>To do this, the user needs only to override the Initialize() and 27 FinalCleanup() methods, and ensure that the program does not terminate 28 abnormally; this ensures FinalCleanup() is called when gui's destructor is 29 invoked. ExitApp() can also perform cleanup and terminate the application 30 cleanly. 31 32 <p>Most of the member methods of SDLGUI have been declared virtual, to 33 give the user great control when subclassing. The virtual function calls 34 are usually not a performance issue, since none of the methods is called 35 repeatedly, except HandleEvent(); if this is a problem, just create a new 36 function in your subclass and call that from within Run() instead of 37 HandleEvent(). Note that though the bulk of the program execution takes 38 place within Run(), Run() itself is also only called once. 39 40 <p>SDLGUI takes a two-tiered approach to event handling. The event pump 41 calls HandleSystemEvents(), which polls for SDL events and handles them by 42 first determining whether the event is GG-related, or some other non-GG 43 event, such as SDL_QUIT, etc. GG events and non-GG events are passed to 44 HandleGGEvent() and HandleNonGGEvent(), respectively. For most uses, 45 there should be no need to override the behavior of HandleSDLEvents(). 46 However, the HandleNonGGEvent() default implementation only responds to 47 SDL_QUIT events, and so should be overridden in most cases. */ 48 class SDLGUI : public GG::GUI 49 { 50 public: 51 /** \name Structors */ ///@{ 52 explicit SDLGUI(int w = 1024, int h = 768, bool calc_FPS = false, const std::string& app_name = "GG", 53 int x = SDL_WINDOWPOS_UNDEFINED, int y = SDL_WINDOWPOS_UNDEFINED, bool fullscreen = false, 54 bool fake_mode_change = false); 55 56 virtual ~SDLGUI(); 57 //@} 58 59 /** \name Accessors */ ///@{ 60 GG::X AppWidth() const override; 61 GG::Y AppHeight() const override; 62 unsigned int Ticks() const override; 63 std::string ClipboardText() const override; 64 virtual std::vector<std::string> GetSupportedResolutions() const override; 65 virtual GG::Pt GetDefaultResolution (int display_id) const override; 66 67 virtual bool Fullscreen() const final; 68 virtual bool FakeModeChange() const final; 69 //@} 70 71 /** \name Mutators */ ///@{ 72 void ExitApp(int code = 0) override; 73 bool SetClipboardText(const std::string& text) override; 74 75 void Enter2DMode() override; 76 void Exit2DMode() override; 77 78 void HandleSystemEvents() override; 79 80 void RenderBegin() override; 81 void RenderEnd() override; 82 83 void Run() override; 84 85 bool AppHasMouseFocus() const override; 86 87 void SetWindowTitle(const std::string& title); 88 void SetVideoMode(GG::X width, GG::Y height, bool fullscreen, bool fake_mode_change); 89 //@} 90 91 static SDLGUI* GetGUI(); ///< allows any code to access the gui framework by calling SDLGUI::GetGUI() 92 93 static GG::Pt GetDefaultResolutionStatic(int display_id); 94 static int NumVideoDisplaysStatic(); 95 bool FramebuffersAvailable() const; 96 97 /** Returns the largest possible width if all displays are aligned horizontally. 98 Ideally it reports actual desktop width using all displays.*/ 99 static int MaximumPossibleWidth(); 100 /** Returns the largest possible height if all displays are aligned vertically. 101 Ideally it reports the actual desktop height using all displays.*/ 102 static int MaximumPossibleHeight(); 103 protected: 104 void SetAppSize(const GG::Pt& size); 105 106 // these are called at the beginning of the gui's execution 107 /** Initializes SDL, FE, and SDL OpenGL functionality. */ 108 void SDLInit(); 109 110 /** Allows user to specify OpenGL initialization code; 111 called at the end of SDLInit(). */ 112 void GLInit(); 113 114 /** Provides one-time gui initialization. */ 115 virtual void Initialize() = 0; 116 117 /** event handler for all SDL events that are not GG-related. */ 118 void HandleNonGGEvent(const SDL_Event& event); 119 120 // these are called at the end of the gui's execution 121 /** Provides one-time gui cleanup. */ 122 void FinalCleanup(); 123 124 /** Cleans up SDL and (if used) FE. */ 125 void SDLQuit(); 126 127 void ResetFramebuffer(); ///< Resizes or deletes the framebuffer for fake fullscreen. 128 129 /** Given is_width = true (false) it returns the largest possible window 130 width (height) if all displays are aligned horizontally (vertically). 131 Ideally it returns the actual width (height) of a multi-monitor display.*/ 132 static int MaximumPossibleDimension(bool is_width = true); 133 134 private: 135 void RelayTextInput (const SDL_TextInputEvent& text, GG::Pt mouse_pos); 136 /** Bare minimum SDL video initialization to allow queries to display sizes etc. 137 If called during static initialization, it will cause OSX to crash on exit. */ 138 static void SDLMinimalInit(); 139 140 GG::X m_app_width{1024}; ///< application width and height (defaults to 1024 x 768) 141 GG::Y m_app_height{768}; 142 GG::X m_initial_x{0}; ///< The initial position of the application window 143 GG::Y m_initial_y{0}; 144 bool m_fullscreen = false; 145 bool m_fake_mode_change = false; 146 int m_display_id = 0; 147 SDL_Window* m_window = nullptr; ///< The sdl window 148 SDL_GLContext m_gl_context = nullptr; ///< The OpenGL context 149 bool m_done = false; ///< Set true true when we should exit. 150 151 /** Virtual screen for fake fullscreen. Equals nullptr ifi 152 m_fake_mode_change == false. */ 153 std::unique_ptr<Framebuffer> m_framebuffer; 154 }; 155 156 #endif 157