cpp-sdl2
C++ header-only SDL2 wrapper
window.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <SDL.h>
4 #include <SDL_syswm.h>
5 #include <string>
6 
7 #include "renderer.hpp"
8 #include "vec2.hpp"
9 
10 #ifdef CPP_SDL2_ENABLE_VULKAN
11 #include <SDL_vulkan.h>
12 #include <vulkan/vulkan.hpp>
13 #endif
14 
15 namespace sdl
16 {
19 class Window
20 {
21 public:
26  Window(std::string const& title, Vec2i const& size, Uint32 flags = SDL_WINDOW_SHOWN)
27  : window_{SDL_CreateWindow(
28  title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, size.x, size.y, flags)}
29  {
30  if (!window_) throw Exception{"SDL_CreateWindow"};
31  }
32 
34  Window() = default;
35 
37  Window(Window&& other) noexcept { *this = std::move(other); }
38 
42  Window& operator=(Window&& other) noexcept
43  {
44  if (this->window_ != other.window_)
45  {
46  SDL_DestroyWindow(window_);
47  window_ = other.window_;
48  other.window_ = nullptr;
49  }
50  return *this;
51  }
52 
53  // Non copyable class
54  Window(Window&) = delete;
55  Window& operator=(Window&) = delete;
56 
58  virtual ~Window() { SDL_DestroyWindow(window_); }
59 
61  SDL_Window* ptr() const { return window_; }
62 
66  Renderer make_renderer(Uint32 flags = SDL_RENDERER_ACCELERATED) const
67  {
68  const auto render = SDL_CreateRenderer(window_, -1, flags);
69  if (!render) throw Exception{"SDL_CreateRenderer"};
70  return Renderer{render};
71  }
72 
74  int display_index() const
75  {
76  const auto r = SDL_GetWindowDisplayIndex(window_);
77  if (r == -1) throw Exception{"SDL_GetWindowDisplayIndex"};
78  return r;
79  }
80 
83  void set_display_mode(SDL_DisplayMode const& mode) const
84  {
85  if (SDL_SetWindowDisplayMode(window_, &mode) != 0)
86  {
87  throw Exception{"SDL_SetWindowDisplayMode"};
88  }
89  }
90 
92  SDL_DisplayMode display_mode() const
93  {
94  SDL_DisplayMode mode;
95  if (SDL_GetWindowDisplayMode(window_, &mode) != 0)
96  {
97  throw Exception{"SDL_GetWindowDisplayMode"};
98  }
99  return mode;
100  }
101 
103  Uint32 flags() const { return SDL_GetWindowFlags(window_); }
104 
106  Window& grab(bool g = true)
107  {
108  SDL_SetWindowGrab(window_, static_cast<SDL_bool>(g));
109  return *this;
110  }
111 
113  Window& release(bool r = true) { return grab(!r); }
114 
116  bool grabbed() const { return SDL_GetWindowGrab(window_); }
117 
120  Window& move_to(Vec2i const& v)
121  {
122  SDL_SetWindowPosition(window_, v.x, v.y);
123  return *this;
124  }
127  Window& move_by(Vec2i const& v) { return move_to(position() + v); }
129  Vec2i position() const
130  {
131  Vec2i pos;
132  SDL_GetWindowPosition(window_, &pos.x, &pos.y);
133  return pos;
134  }
135 
138  void resize(Vec2i const& newsize) const { SDL_SetWindowSize(window_, newsize.x, newsize.y); }
140  Vec2i size() const
141  {
142  Vec2i s;
143  SDL_GetWindowSize(window_, &s.x, &s.y);
144  return s;
145  }
146 
149  Window& rename(std::string const& t)
150  {
151  SDL_SetWindowTitle(window_, t.c_str());
152  return *this;
153  }
155  std::string title() const { return std::string{SDL_GetWindowTitle(window_)}; }
156 
159  void set_icon(Surface const& icon) const { SDL_SetWindowIcon(window_, icon.ptr()); }
160 
163  void set_icon(std::string const& filename) const
164  {
165  auto icon = Surface{filename};
166  SDL_SetWindowIcon(window_, icon.ptr());
167  }
168 
171  {
172  SDL_HideWindow(window_);
173  return *this;
174  }
177  {
178  SDL_MaximizeWindow(window_);
179  return *this;
180  }
183  {
184  SDL_MinimizeWindow(window_);
185  return *this;
186  }
188  Window& raise()
189  {
190  SDL_RaiseWindow(window_);
191  return *this;
192  }
195  {
196  SDL_RestoreWindow(window_);
197  return *this;
198  }
199 
202  bool fullscreen() const
203  {
204  return flags() & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP);
205  }
208  {
209  if (SDL_SetWindowFullscreen(window_, fs ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0) != 0)
210  {
211  throw Exception{"SDL_SetWindowFullscreen"};
212  }
213  return *this;
214  }
215 
218 
220  SDL_SysWMinfo wm_info() const
221  {
222  SDL_SysWMinfo info;
223  SDL_VERSION(&info.version);
224  if (SDL_GetWindowWMInfo(window_, &info) == SDL_FALSE)
225  {
226  throw Exception("SDL_GetWindowWMInfo");
227  }
228  return info;
229  }
230 
231 #ifdef CPP_SDL2_ENABLE_VULKAN
232  std::vector<const char*> vk_get_instance_extensions()
235  {
236  std::vector<const char*> extensions;
237  Uint32 count;
238 
239  if (!SDL_Vulkan_GetInstanceExtensions(window_, &count, nullptr))
240  throw Exception("SDL_Vulkan_GetInstanceExtensions");
241 
242  extensions.resize(count);
243 
244  if (!SDL_Vulkan_GetInstanceExtensions(window_, &count, extensions.data()))
245  throw Exception("SDL_Vulkan_GetInstaceExtensions");
246 
247  return extensions; // Benefit from enforced RVO
248  }
249 
252  VkSurfaceKHR vk_create_surface(VkInstance instance)
253  {
254  VkSurfaceKHR surface;
255  if (!SDL_Vulkan_CreateSurface(window_, instance, &surface))
256  throw Exception("SDL_Vulkan_CreateSurface");
257 
258  return surface;
259  }
260 
262  vk::UniqueSurfaceKHR vk_create_unique_surface(vk::Instance instance)
263  {
264  auto nakedSurface = vk_create_surface(instance);
265  return vk::UniqueSurfaceKHR(nakedSurface, instance);
266  }
267 
271  {
272  Vec2i size;
273  SDL_Vulkan_GetDrawableSize(window_, &size.x, &size.y);
274  return size;
275  }
276 #endif // vulkan methods
277 
278 #ifdef CPP_SDL2_ENABLE_OPENGL
279 
280  // This function is mostly used to set values regarding SDL GL context, and
281  // is intertwined with window creation. However, this can be called before
282  // creation the window. This wrapping is mostly for API consistency and for
283  // automatic error checking.
284  static void gl_set_attribute(SDL_GLattr attr, int val)
285  {
286  if (SDL_GL_SetAttribute(attr, val) < 0) throw Exception("SDL_GL_SetAttribute");
287  }
288 
289  static void gl_set_attribute(SDL_GLattr attr, bool val) { gl_set_attribute(attr, val ? 1 : 0); }
290 
292  static int gl_get_attribute(SDL_GLattr attr)
293  {
294  int value;
295  if (SDL_GL_GetAttribute(attr, &value) != 0) throw Exception("SDL_GL_GetAttribute");
296  return value;
297  }
298 
300  static void gl_reset_attribute() { SDL_GL_ResetAttributes(); }
301 
303  static bool gl_is_extension_supported(std::string const& ext_name)
304  {
305  return SDL_GL_ExtensionSupported(ext_name.c_str()) == SDL_TRUE;
306  }
307 
309  enum class gl_swap_interval
310  {
311  immediate,
312  vsync,
314  };
315 
317  static void gl_set_swap_interval(gl_swap_interval swap_mode)
318  {
319  auto result = 0;
320  switch (swap_mode)
321  {
322  case gl_swap_interval::immediate: result = SDL_GL_SetSwapInterval(0); break;
323  case gl_swap_interval::vsync: result = SDL_GL_SetSwapInterval(1); break;
324  case gl_swap_interval::adaptive_vsync: result = SDL_GL_SetSwapInterval(-1); break;
325  }
326 
327  if (result != 0) throw Exception("SDL_GL_SetSwapInterval");
328  }
329 
332  {
333  const auto value = SDL_GL_GetSwapInterval();
334  if (value == 1) return gl_swap_interval::vsync;
335  if (value == -1) return gl_swap_interval::adaptive_vsync;
337  }
338 
340  class GlContext
341  {
342  public:
345  GlContext(SDL_Window* w) : context_{SDL_GL_CreateContext(w)}, owner_{w}
346  {
347  if (!context_) throw Exception("SDL_GL_CreateContext");
348  }
349 
351  GlContext() = default;
352 
354  ~GlContext() { SDL_GL_DeleteContext(context_); }
355 
356  // Only movable, not copyable
357  GlContext(GlContext const&) = delete;
358  GlContext& operator=(GlContext const&) = delete;
359 
360  GlContext(GlContext&& other) noexcept { *this = std::move(other); }
361 
362  GlContext& operator=(GlContext&& other) noexcept
363  {
364  if (context_ != other.context_)
365  {
366  context_ = other.context_;
367  owner_ = other.owner_;
368  other.context_ = nullptr;
369  }
370  return *this;
371  }
372 
373  void make_current() const
374  {
375  if (SDL_GL_MakeCurrent(owner_, context_) < 0) throw Exception("SDL_GL_MakeCurrent");
376  }
377 
378  SDL_GLContext ptr() const { return context_; }
379 
380  private:
381  SDL_GLContext context_ = nullptr;
382  SDL_Window* owner_ = nullptr;
383  };
384 
387 
389  void gl_swap() const { SDL_GL_SwapWindow(window_); }
390 
393  {
394  Vec2i size{};
395  SDL_GL_GetDrawableSize(window_, &size.x, &size.y);
396  return size;
397  }
398 
399 #endif
400 
401 private:
403  SDL_Window* window_ = nullptr;
404 };
405 
406 } // namespace sdl
static void gl_set_swap_interval(gl_swap_interval swap_mode)
Set the swap interval. If exception thrown while attempting to use adaptive vsync, use standard vsync.
Definition: window.hpp:317
Vec2i vk_get_drawable_size()
Get the underlayoing drawable size of the window.
Definition: window.hpp:270
GlContext & operator=(GlContext &&other) noexcept
Definition: window.hpp:362
Vec2i gl_get_drawable_size() const
Get the actual size of the OpenGL drawing area on the window. May not match window size on platform t...
Definition: window.hpp:392
Window & set_fullscreen(bool fs)
Set the window fullscreen.
Definition: window.hpp:207
Window & maximize()
Maximize the window.
Definition: window.hpp:176
static void gl_set_attribute(SDL_GLattr attr, bool val)
Definition: window.hpp:289
Generic templated 2D vector class.
Definition: vec2.hpp:24
void resize(Vec2i const &newsize) const
Change the size of the window the size of the window.
Definition: window.hpp:138
VkSurfaceKHR vk_create_surface(VkInstance instance)
Create a vulkan surface for the current platform.
Definition: window.hpp:252
GlContext(SDL_Window *w)
Create a GlContext for the given window.
Definition: window.hpp:345
static void gl_reset_attribute()
Reset all OpenGL attributes to their default values.
Definition: window.hpp:300
Window & move_by(Vec2i const &v)
Translate window on screen.
Definition: window.hpp:127
std::vector< const char * > vk_get_instance_extensions()
Enumerate the required extensions to create a VkSurfaceKHR on the current system. ...
Definition: window.hpp:234
void set_icon(std::string const &filename) const
Set the window icon (may require linking and activating SDL_Image)
Definition: window.hpp:163
Window & toggle_fullscreen()
Toggle the window fullscreen.
Definition: window.hpp:217
static gl_swap_interval gl_get_swap_interval()
Get the current swap interval.
Definition: window.hpp:331
virtual ~Window()
Destructor. Calls SDL_DestroyWindow() automatically for you.
Definition: window.hpp:58
Uint32 flags() const
Get the flags of this window.
Definition: window.hpp:103
Represent an SDL window.
Definition: window.hpp:19
Window & release(bool r=true)
Release window.
Definition: window.hpp:113
Window & move_to(Vec2i const &v)
Move window to specific location on screen.
Definition: window.hpp:120
void set_display_mode(SDL_DisplayMode const &mode) const
Set the window display mode.
Definition: window.hpp:83
Window & grab(bool g=true)
Grab window.
Definition: window.hpp:106
GlContext create_context() const
Create an OpenGL context from the current window.
Definition: window.hpp:386
SDL_Window * window_
Raw naked pointer to an SDL window.
Definition: window.hpp:403
Window()=default
Construct an invalid window object. You will need to initialize it by moving in a real sdl::Window in...
~GlContext()
Dtor will call SDL_GL_DeleteContext on the enclosed context.
Definition: window.hpp:354
Nested class that represent a managed OpenGL Context by the SDL.
Definition: window.hpp:340
Define to deactivate exception support.
Definition: color.hpp:7
static int gl_get_attribute(SDL_GLattr attr)
Get the value of the specified OpenGL attribute.
Definition: window.hpp:292
SDL_GLContext ptr() const
Definition: window.hpp:378
SDL_SysWMinfo wm_info() const
Get window manager info. Exact content of this structure is fully platform dependant.
Definition: window.hpp:220
Window & restore()
Restore the window.
Definition: window.hpp:194
static void gl_set_attribute(SDL_GLattr attr, int val)
Definition: window.hpp:284
std::string title() const
the current window title
Definition: window.hpp:155
GlContext(GlContext &&other) noexcept
Definition: window.hpp:360
int display_index() const
Get the current window display index.
Definition: window.hpp:74
Window & hide()
Hide the window.
Definition: window.hpp:170
Window & operator=(Window &&other) noexcept
Move assign operator.
Definition: window.hpp:42
static bool gl_is_extension_supported(std::string const &ext_name)
Return true if the specified extension is supported.
Definition: window.hpp:303
SDL_Surface * ptr() const
Get C SDL_Surface object.
Definition: surface.hpp:144
Represent an SDL_Surface.
Definition: surface.hpp:21
SDL_Window * ptr() const
Getter for the raw SDL2 window pointer.
Definition: window.hpp:61
void make_current() const
Definition: window.hpp:373
bool grabbed() const
Is window grabed.
Definition: window.hpp:116
gl_swap_interval
Define the type of window swapping strategy for opengl windows.
Definition: window.hpp:309
Vec2i size() const
Get current window size.
Definition: window.hpp:140
Vec2i position() const
Get current window position.
Definition: window.hpp:129
vk::UniqueSurfaceKHR vk_create_unique_surface(vk::Instance instance)
Create a vulkan surface using the C++ wrapper around UniqueHandle.
Definition: window.hpp:262
Renderer make_renderer(Uint32 flags=SDL_RENDERER_ACCELERATED) const
2D renderer factory.
Definition: window.hpp:66
Window & minimize()
Minimize the window.
Definition: window.hpp:182
Define to deactivate exception support.
Definition: exception.hpp:21
void gl_swap() const
Swap buffers for GL when using double buffering on the current window.
Definition: window.hpp:389
SDL_DisplayMode display_mode() const
Get the current display mode.
Definition: window.hpp:92
bool fullscreen() const
Returns true if window is currently fullscreen (both real and "desktop mode")
Definition: window.hpp:202
Window(std::string const &title, Vec2i const &size, Uint32 flags=SDL_WINDOW_SHOWN)
Construct a window.
Definition: window.hpp:26
SDL_GLContext context_
Definition: window.hpp:381
Class that represent a SDL2 2D renderer.
Definition: renderer.hpp:18
Window & rename(std::string const &t)
Change window name.
Definition: window.hpp:149
Window(Window &&other) noexcept
Default move ctor.
Definition: window.hpp:37
void set_icon(Surface const &icon) const
Set the window icon.
Definition: window.hpp:159