1 module gfm.sdl2.window; 2 3 import std..string; 4 5 import derelict.sdl2.sdl; 6 7 static if( __VERSION__ >= 2067 ) 8 import std.experimental.logger; 9 else 10 import std.historical.logger; 11 12 import gfm.sdl2.sdl, 13 gfm.sdl2.surface, 14 gfm.sdl2.mouse, 15 gfm.sdl2.keyboard; 16 17 18 /// SDL Window wrapper. 19 /// There is two ways to receive events, either by polling a SDL2 object, 20 /// or by overriding the event callbacks. 21 final class SDL2Window 22 { 23 public 24 { 25 /// Creates a SDL window which targets a window. 26 /// See_also: $(LINK http://wiki.libsdl.org/SDL_CreateWindow) 27 /// Throws: $(D SDL2Exception) on error. 28 this(SDL2 sdl2, int x, int y, int width, int height, int flags) 29 { 30 _sdl2 = sdl2; 31 _logger = sdl2._logger; 32 _surface = null; 33 _glContext = null; 34 _surfaceMustBeRenewed = false; 35 36 bool OpenGL = (flags & SDL_WINDOW_OPENGL) != 0; 37 _window = SDL_CreateWindow(toStringz(""), x, y, width, height, flags); 38 if (_window == null) 39 { 40 string message = "SDL_CreateWindow failed: " ~ _sdl2.getErrorString().idup; 41 throw new SDL2Exception(message); 42 } 43 44 _id = SDL_GetWindowID(_window); 45 46 if (OpenGL) 47 _glContext = new SDL2GLContext(this); 48 } 49 50 /// Creates a SDL window from anexisting handle. 51 /// See_also: $(LINK http://wiki.libsdl.org/SDL_CreateWindowFrom) 52 /// Throws: $(D SDL2Exception) on error. 53 this(SDL2 sdl2, void* windowData) 54 { 55 _sdl2 = sdl2; 56 _logger = sdl2._logger; 57 _surface = null; 58 _glContext = null; 59 _surfaceMustBeRenewed = false; 60 _window = SDL_CreateWindowFrom(windowData); 61 if (_window == null) 62 { 63 string message = "SDL_CreateWindowFrom failed: " ~ _sdl2.getErrorString().idup; 64 throw new SDL2Exception(message); 65 } 66 67 _id = SDL_GetWindowID(_window); 68 } 69 70 71 /// Releases the SDL resource. 72 /// See_also: $(LINK http://wiki.libsdl.org/SDL_DestroyWindow) 73 final void close() 74 { 75 if (_glContext !is null) 76 { 77 _glContext.close(); 78 _glContext = null; 79 } 80 81 if (_window !is null) 82 { 83 SDL_DestroyWindow(_window); 84 _window = null; 85 } 86 } 87 88 /// 89 ~this() 90 { 91 close(); 92 } 93 94 /// See_also: $(LINK http://wiki.libsdl.org/SDL_SetWindowFullscreen) 95 /// Throws: $(D SDL2Exception) on error. 96 final void setFullscreenSetting(uint flags) 97 { 98 if (SDL_SetWindowFullscreen(_window, flags) != 0) 99 _sdl2.throwSDL2Exception("SDL_SetWindowFullscreen"); 100 } 101 102 /// Returns: X window coordinate. 103 /// See_also: $(LINK http://wiki.libsdl.org/SDL_GetWindowPosition) 104 final int getX() 105 { 106 return getPosition().x; 107 } 108 109 /// Returns: Y window coordinate. 110 /// See_also: $(LINK http://wiki.libsdl.org/SDL_GetWindowPosition) 111 final int getY() 112 { 113 return getPosition().y; 114 } 115 116 /// Returns: Window coordinates. 117 /// See_also: $(LINK http://wiki.libsdl.org/SDL_GetWindowPosition) 118 final SDL_Point getPosition() 119 { 120 int x, y; 121 SDL_GetWindowPosition(_window, &x, &y); 122 return SDL_Point(x, y); 123 } 124 125 /// See_also: $(LINK http://wiki.libsdl.org/SDL_SetWindowPosition) 126 final void setPosition(int positionX, int positionY) 127 { 128 SDL_SetWindowPosition(_window, positionX, positionY); 129 } 130 131 /// See_also: $(LINK http://wiki.libsdl.org/SDL_SetWindowSize) 132 final void setSize(int width, int height) 133 { 134 SDL_SetWindowSize(_window, width, height); 135 } 136 137 /// See_also: $(LINK http://wiki.libsdl.org/SDL_GetWindowSize) 138 /// Returns: Window size in pixels. 139 final SDL_Point getSize() 140 { 141 int w, h; 142 SDL_GetWindowSize(_window, &w, &h); 143 return SDL_Point(w, h); 144 } 145 146 /// See_also: $(LINK http://wiki.libsdl.org/SDL_SetWindowIcon) 147 final void setIcon(SDL2Surface icon) 148 { 149 SDL_SetWindowIcon(_window, icon.handle()); 150 } 151 152 /// See_also: $(LINK http://wiki.libsdl.org/SDL_SetWindowBordered) 153 final void setBordered(bool bordered) 154 { 155 SDL_SetWindowBordered(_window, bordered ? SDL_TRUE : SDL_FALSE); 156 } 157 158 /// See_also: $(LINK http://wiki.libsdl.org/SDL_GetWindowSize) 159 /// Returns: Window width in pixels. 160 final int getWidth() 161 { 162 int w, h; 163 SDL_GetWindowSize(_window, &w, &h); 164 return w; 165 } 166 167 /// See_also: $(LINK http://wiki.libsdl.org/SDL_GetWindowSize) 168 /// Returns: Window height in pixels. 169 final int getHeight() 170 { 171 int w, h; 172 SDL_GetWindowSize(_window, &w, &h); 173 return h; 174 } 175 176 /// See_also: $(LINK http://wiki.libsdl.org/SDL_SetWindowTitle) 177 final void setTitle(string title) 178 { 179 SDL_SetWindowTitle(_window, toStringz(title)); 180 } 181 182 /// See_also: $(LINK http://wiki.libsdl.org/SDL_ShowWindow) 183 final void show() 184 { 185 SDL_ShowWindow(_window); 186 } 187 188 /// See_also: $(LINK http://wiki.libsdl.org/SDL_HideWindow) 189 final void hide() 190 { 191 SDL_HideWindow(_window); 192 } 193 194 /// See_also: $(LINK http://wiki.libsdl.org/SDL_MinimizeWindow) 195 final void minimize() 196 { 197 SDL_MinimizeWindow(_window); 198 } 199 200 /// See_also: $(LINK http://wiki.libsdl.org/SDL_MaximizeWindow) 201 final void maximize() 202 { 203 SDL_MaximizeWindow(_window); 204 } 205 206 /// Returns: Window surface. 207 /// See_also: $(LINK http://wiki.libsdl.org/SDL_GetWindowSurface) 208 /// Throws: $(D SDL2Exception) on error. 209 final SDL2Surface surface() 210 { 211 if (!hasValidSurface()) 212 { 213 SDL_Surface* internalSurface = SDL_GetWindowSurface(_window); 214 if (internalSurface is null) 215 _sdl2.throwSDL2Exception("SDL_GetWindowSurface"); 216 217 // renews surface as needed 218 _surfaceMustBeRenewed = false; 219 _surface = new SDL2Surface(_sdl2, internalSurface, SDL2Surface.Owned.NO); 220 } 221 return _surface; 222 } 223 224 /// Submit changes to the window surface. 225 /// See_also: $(LINK http://wiki.libsdl.org/SDL_UpdateWindowSurface) 226 /// Throws: $(D SDL2Exception) on error. 227 final void updateSurface() 228 { 229 if (!hasValidSurface()) 230 surface(); 231 232 int res = SDL_UpdateWindowSurface(_window); 233 if (res != 0) 234 _sdl2.throwSDL2Exception("SDL_UpdateWindowSurface"); 235 236 } 237 238 /// Returns: Window ID. 239 /// See_also: $(LINK http://wiki.libsdl.org/SDL_GetWindowID) 240 final int id() 241 { 242 return _id; 243 } 244 245 /// Returns: System-specific window information, useful to use a third-party rendering library. 246 /// See_also: $(LINK http://wiki.libsdl.org/SDL_GetWindowWMInfo) 247 /// Throws: $(D SDL2Exception) on error. 248 SDL_SysWMinfo getWindowInfo() 249 { 250 SDL_SysWMinfo info; 251 SDL_VERSION(&info.version_); 252 int res = SDL_GetWindowWMInfo(_window, &info); 253 if (res != SDL_TRUE) 254 _sdl2.throwSDL2Exception("SDL_GetWindowWMInfo"); 255 return info; 256 } 257 258 /// Swap OpenGL buffers. 259 /// See_also: $(LINK http://wiki.libsdl.org/SDL_GL_SwapWindow) 260 /// Throws: $(D SDL2Exception) on error. 261 void swapBuffers() 262 { 263 if (_glContext is null) 264 throw new SDL2Exception("swapBuffers failed: not an OpenGL window"); 265 SDL_GL_SwapWindow(_window); 266 } 267 } 268 269 package 270 { 271 SDL2 _sdl2; 272 SDL_Window* _window; 273 } 274 275 private 276 { 277 Logger _logger; 278 SDL2Surface _surface; 279 SDL2GLContext _glContext; 280 uint _id; 281 282 bool _surfaceMustBeRenewed; 283 284 bool hasValidSurface() 285 { 286 return (!_surfaceMustBeRenewed) && (_surface !is null); 287 } 288 } 289 } 290 291 /// SDL OpenGL context wrapper. You probably don't need to use it directly. 292 final class SDL2GLContext 293 { 294 public 295 { 296 /// Creates an OpenGL context for a given SDL window. 297 this(SDL2Window window) 298 { 299 _window = window; 300 _context = SDL_GL_CreateContext(window._window); 301 _initialized = true; 302 } 303 304 ~this() 305 { 306 close(); 307 } 308 309 /// Release the associated SDL ressource. 310 void close() 311 { 312 if (_initialized) 313 { 314 // work-around Issue #19 315 // SDL complains with log message "wglMakeCurrent(): The handle is invalid." 316 // in the SDL_DestroyWindow() call if we destroy the OpenGL context before-hand 317 // 318 // SDL_GL_DeleteContext(_context); 319 _initialized = false; 320 } 321 } 322 323 /// Makes this OpenGL context current. 324 /// Throws: $(D SDL2Exception) on error. 325 void makeCurrent() 326 { 327 if (0 != SDL_GL_MakeCurrent(_window._window, _context)) 328 _window._sdl2.throwSDL2Exception("SDL_GL_MakeCurrent"); 329 } 330 } 331 332 package 333 { 334 SDL_GLContext _context; 335 SDL2Window _window; 336 } 337 338 private 339 { 340 bool _initialized; 341 } 342 } 343