Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
WindowManager.cpp
Go to the documentation of this file.
1
2
4
11
12namespace Divide
13{
14
15namespace
16{
17 [[nodiscard]] SDL_SystemCursor CursorToSDL(const CursorStyle style) noexcept
18 {
19 switch (style)
20 {
21 case CursorStyle::ARROW: return SDL_SYSTEM_CURSOR_ARROW;
22 case CursorStyle::HAND: return SDL_SYSTEM_CURSOR_HAND;
23 case CursorStyle::NONE: return SDL_SYSTEM_CURSOR_NO;
24 case CursorStyle::RESIZE_ALL: return SDL_SYSTEM_CURSOR_SIZEALL;
25 case CursorStyle::RESIZE_EW: return SDL_SYSTEM_CURSOR_SIZEWE;
26 case CursorStyle::RESIZE_NS: return SDL_SYSTEM_CURSOR_SIZENS;
27 case CursorStyle::RESIZE_NESW: return SDL_SYSTEM_CURSOR_SIZENESW;
28 case CursorStyle::RESIZE_NWSE: return SDL_SYSTEM_CURSOR_SIZENWSE;
29 case CursorStyle::TEXT_INPUT: return SDL_SYSTEM_CURSOR_IBEAM;
30 case CursorStyle::COUNT: break;
31 }
32
33 return SDL_SYSTEM_CURSOR_NO;
34 }
35
36 bool Validate(const I32 errCode)
37 {
38 if (errCode != 0)
39 {
40 Console::errorfn(LOCALE_STR("SDL_ERROR"), SDL_GetError());
41 return false;
42 }
43
44 return true;
45 }
46
47 bool ValidateAssert(const I32 errCode)
48 {
49 if (!Validate(errCode))
50 {
51 assert(errCode == 0);
52 return false;
53 }
54
55 return true;
56 }
57
58} // namespace
59
61std::array<SDL_Cursor*, to_base(CursorStyle::COUNT)> WindowManager::s_cursors = create_array<to_base(CursorStyle::COUNT), SDL_Cursor*>(nullptr);
62
64{
65}
66
68{
69 DIVIDE_ASSERT( _windows.empty(), "WindowManager::~WindowManager(): close() was not called before destruction!" );
70}
71
73{
75}
76
78 const RenderAPI renderingAPI,
79 const vec2<I16> initialPosition,
80 const vec2<U16> initialSize,
81 const WindowMode windowMode,
82 const I32 targetDisplayIndex)
83{
84 if (!_monitors.empty())
85 {
86 // Double init
88 }
89
90 if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
91 {
93 }
94
95 _context = &context;
96
98 const I32 displayCount = SDL_GetNumVideoDisplays();
99 for (I32 i = 0; i < displayCount; ++i)
100 {
101 MonitorData data = {};
102
103 SDL_Rect r;
104 SDL_GetDisplayBounds(i, &r);
105 data.viewport.xy = { to_I16(r.x), to_I16(r.y) };
106 data.viewport.zw = { to_I16(r.w), to_I16(r.h) };
107
108 SDL_GetDisplayUsableBounds(i, &r);
109 data.drawableArea.xy = { to_I16(r.x), to_I16(r.y) };
110 data.drawableArea.zw = { to_I16(r.w), to_I16(r.h) };
111
112 SDL_GetDisplayDPI(i, &data.dpi, nullptr, nullptr);
113
114 _monitors.push_back(data);
115 }
116
117 for ( U8 i = 0; i < to_U8( CursorStyle::COUNT ); ++i )
118 {
119 s_cursors[i] = SDL_CreateSystemCursor( CursorToSDL( static_cast<CursorStyle>(i) ) );
120 }
121
122 const I32 displayIndex = std::max(std::min(targetDisplayIndex, displayCount - 1), 0);
123
124 SDL_GetCurrentDisplayMode(displayIndex, &s_mainDisplayMode );
125
126 WindowDescriptor descriptor = {};
127 descriptor.position = initialPosition;
128 descriptor.dimensions = initialSize;
129 descriptor.targetDisplay = to_U32(displayIndex);
130 descriptor.title = _context->config().runtime.title;
131 descriptor.externalClose = false;
132 descriptor.targetAPI = renderingAPI;
133
135 {
137 }
138
140
141 if (windowMode == WindowMode::FULLSCREEN)
142 {
144 }
145 else if(windowMode == WindowMode::BORDERLESS_WINDOWED)
146 {
148 }
149
151 {
152 descriptor.flags &= ~to_base(WindowDescriptor::Flags::RESIZEABLE);
153 }
154
156 DisplayWindow* window = createWindow(descriptor, err);
157
158 if (err == ErrorCode::NO_ERR)
159 {
160 _mainWindowGUID = window->getGUID();
161
162 Application& app = _context->app();
163
164 window->addEventListener(WindowEvent::MINIMIZED, [&app]([[maybe_unused]] const DisplayWindow::WindowEventArgs& args) noexcept
165 {
166 app.mainLoopPaused(true);
167 return true;
168 });
169 window->addEventListener(WindowEvent::MAXIMIZED, [&app]([[maybe_unused]] const DisplayWindow::WindowEventArgs& args) noexcept
170 {
171 app.mainLoopPaused(false);
172 return true;
173 });
174 window->addEventListener(WindowEvent::RESTORED, [&app]([[maybe_unused]] const DisplayWindow::WindowEventArgs& args) noexcept
175 {
176 app.mainLoopPaused(false);
177 return true;
178 });
179
180 // Query available display modes (resolution, bit depth per channel and refresh rates)
181 I32 numberOfDisplayModes[DisplayManager::g_maxDisplayOutputs] = {};
182
183 const U8 numDisplays = to_U8(std::min(SDL_GetNumVideoDisplays(), to_I32( DisplayManager::g_maxDisplayOutputs )));
185
186 for (I32 display = 0; display < numDisplays; ++display)
187 {
188 numberOfDisplayModes[display] = SDL_GetNumDisplayModes(display);
189 }
190
191 DisplayManager::OutputDisplayProperties tempDisplayMode = {};
192 for (U8 display = 0u; display < numDisplays; ++display)
193 {
194 // Register the display modes with the GFXDevice object
195 for (I32 mode = 0; mode < numberOfDisplayModes[display]; ++mode)
196 {
197 SDL_GetDisplayMode(display, mode, &s_mainDisplayMode );
198 tempDisplayMode._maxRefreshRate = to_U8( s_mainDisplayMode.refresh_rate);
199 tempDisplayMode._resolution.set( s_mainDisplayMode.w, s_mainDisplayMode.h);
200 tempDisplayMode._bitsPerPixel = SDL_BITSPERPIXEL( s_mainDisplayMode.format);
201 tempDisplayMode._formatName = SDL_GetPixelFormatName( s_mainDisplayMode.format);
202 Util::ReplaceStringInPlace(tempDisplayMode._formatName, "SDL_PIXELFORMAT_", "");
204 }
205 }
206
207 GFX::InitPools(64u);
208 }
209
210 return err;
211}
212
214{
215 for ( auto& window : _windows)
216 {
217 window->destroyWindow();
218 }
219
220 _windows.clear();
221
222 for (SDL_Cursor* it : s_cursors)
223 {
224 SDL_FreeCursor(it);
225 }
226
227 s_cursors.fill(nullptr);
228
229 SDL_QuitSubSystem(SDL_INIT_VIDEO);
231}
232
234{
235 if ( descriptor.targetAPI == RenderAPI::COUNT )
236 {
238 return nullptr;
239 }
240
241 std::unique_ptr<DisplayWindow> window = std::make_unique<DisplayWindow>(*this, *_context);
242 DIVIDE_ASSERT(window != nullptr);
243
244 if (err != ErrorCode::NO_ERR)
245 {
246 return nullptr;
247 }
248
249 U32 windowFlags = descriptor.targetAPI == RenderAPI::Vulkan ? SDL_WINDOW_VULKAN : descriptor.targetAPI == RenderAPI::OpenGL ? SDL_WINDOW_OPENGL : 0u;
250
252 {
253 windowFlags |= SDL_WINDOW_RESIZABLE;
254 }
256 {
257 windowFlags |= SDL_WINDOW_ALLOW_HIGHDPI;
258 }
260 {
261 windowFlags |= SDL_WINDOW_HIDDEN;
262 }
264 {
265 windowFlags |= SDL_WINDOW_BORDERLESS;
266 }
268 {
269 windowFlags |= SDL_WINDOW_ALWAYS_ON_TOP;
270 }
272 {
273 windowFlags |= SDL_WINDOW_SKIP_TASKBAR;
274 }
275
278 {
279 winType = WindowType::FULLSCREEN;
280 windowFlags |= SDL_WINDOW_FULLSCREEN;
281 }
283 {
285 windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
286 }
287
288 if (err == ErrorCode::NO_ERR)
289 {
290 err = ConfigureAPISettings( *_context, descriptor );
291 }
292
293 if (err != ErrorCode::NO_ERR)
294 {
295 return nullptr;
296 }
297
298 DisplayWindow* crtWindow = activeWindow();
299
300 bool contextChanged = false;
301 if ( descriptor.parentWindow != nullptr )
302 {
303 Validate( SDL_GL_MakeCurrent( descriptor.parentWindow->getRawWindow(), descriptor.parentWindow->userData()._glContext ) );
304 contextChanged = true;
305 }
306
307 err = window->init(windowFlags, winType, descriptor);
308
309 if ( crtWindow != nullptr && contextChanged )
310 {
311 Validate( SDL_GL_MakeCurrent( crtWindow->getRawWindow(), nullptr ) );
312 }
313
314 if (err != ErrorCode::NO_ERR)
315 {
316 return nullptr;
317 }
318
319 const bool isMainWindow = _mainWindow == nullptr;
320 if ( isMainWindow )
321 {
322 DIVIDE_ASSERT( descriptor.parentWindow == nullptr );
323 _mainWindow = window.get();
324 }
325
326 err = ApplyAPISettings( *_context, descriptor.targetAPI, window.get(), crtWindow != nullptr ? crtWindow : mainWindow() );
327
328 if ( err != ErrorCode::NO_ERR )
329 {
330 if ( isMainWindow )
331 {
332 _mainWindow = nullptr;
333 }
334
335 return nullptr;
336 }
337
338 window->addEventListener(WindowEvent::SIZE_CHANGED, [&](const DisplayWindow::WindowEventArgs& args)
339 {
340 SizeChangeParams params{};
341 params.width = to_U16(args.x);
342 params.height = to_U16(args.y);
343 params.isFullScreen = args._flag;
344 params.winGUID = args._windowGUID;
345 params.isMainWindow = isMainWindow;
346 // Only if rendering window
347 return _context->app().onWindowSizeChange(params);
348 });
349
350 if (!descriptor.externalClose)
351 {
352 window->addEventListener(WindowEvent::CLOSE_REQUESTED, [this](const DisplayWindow::WindowEventArgs& args)
353 {
354 Console::d_printfn(LOCALE_STR("WINDOW_CLOSE_EVENT"), args._windowGUID);
355
356 if (_mainWindowGUID == args._windowGUID)
357 {
358 _context->app().RequestShutdown(false);
359 }
360 else
361 {
362 for ( auto& win : _windows)
363 {
364 if (win->getGUID() == args._windowGUID)
365 {
366 auto tempWindow = win.get();
367 if (!destroyWindow(tempWindow))
368 {
369 Console::errorfn(LOCALE_STR("WINDOW_CLOSE_EVENT_ERROR"), args._windowGUID);
370 win->hidden(true);
371 }
372 break;
373 }
374 }
375 return false;
376 }
377 return true;
378 });
379 }
380
381 return _windows.emplace_back(MOV(window)).get();
382}
383
385{
386 if (window == nullptr)
387 {
388 return true;
389 }
390
391 SDL_HideWindow(window->getRawWindow());
392
393 if (window->destroyWindow() == ErrorCode::NO_ERR)
394 {
395 if (window->getGUID() == _mainWindowGUID)
396 {
397 _mainWindowGUID = -1;
398 _mainWindow = nullptr;
399 }
400
401 erase_if(_windows, [targetGUID = window->getGUID()](auto& win) noexcept { return win->getGUID() == targetGUID;});
402 window = nullptr;
403 return true;
404 }
405
406 return false;
407}
408
410{
411 if (!window || !(SDL_GetWindowFlags(window->getRawWindow()) & to_U32(SDL_WINDOW_OPENGL)))
412 {
413 return;
414 }
415
416 if ( window->userData()._glContext != nullptr)
417 {
418 if ( window->userData()._ownsContext)
419 {
420 SDL_GL_DeleteContext( window->userData()._glContext );
421 }
422
423 window->userData()._glContext = nullptr;
424 }
425}
426
428{
429 const RenderAPI api = descriptor.targetAPI;
430
431 if (api == RenderAPI::Vulkan || api == RenderAPI::None)
432 {
433 NOP();
434 }
435 else if (api == RenderAPI::OpenGL)
436 {
437 Uint32 OpenGLFlags = SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG | SDL_GL_CONTEXT_RESET_ISOLATION_FLAG;
438
439 bool useDebugContext = false;
441 {
442 // OpenGL error handling is available in any build configuration if the proper defines are in place.
443 OpenGLFlags |= SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG;
445 {
446 useDebugContext = true;
447 OpenGLFlags |= SDL_GL_CONTEXT_DEBUG_FLAG;
448 }
449 }
450 if (!useDebugContext)
451 {
452 ValidateAssert(SDL_GL_SetAttribute(SDL_GL_CONTEXT_NO_ERROR, 1));
453 }
454
455 ValidateAssert(SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, OpenGLFlags));
456 ValidateAssert(SDL_GL_SetAttribute(SDL_GL_CONTEXT_RELEASE_BEHAVIOR, SDL_GL_CONTEXT_RELEASE_BEHAVIOR_NONE));
457
458 ValidateAssert(SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1));
459 // 32Bit RGBA (R8G8B8A8), 24bit Depth, 8bit Stencil
460 ValidateAssert(SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8));
461 ValidateAssert(SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8));
462 ValidateAssert(SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8));
463 ValidateAssert(SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8));
464 ValidateAssert(SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8));
465 ValidateAssert(SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24));
466
467
468 Validate(SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE));
469 ValidateAssert(SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4));
470 if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6) != 0)
471 {
472 ValidateAssert(SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5));
473 }
474
475 if ( context.config().rendering.MSAASamples > 0u)
476 {
477 ValidateAssert( SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 ) );
478 ValidateAssert( SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, std::min( context.config().rendering.MSAASamples, to_U8(4u)) ) ); // Cap to 4xMSAA as we can't query HW support yet
479 }
480 }
481 else
482 {
484 }
485
486 return ErrorCode::NO_ERR;
487}
488
489ErrorCode WindowManager::ApplyAPISettings( const PlatformContext& context, const RenderAPI api, DisplayWindow* targetWindow, DisplayWindow* activeWindow )
490{
491 // Create a context and make it current
492 if ( targetWindow->parentWindow() != nullptr)
493 {
494 targetWindow->userData( targetWindow->parentWindow()->userData() );
495 targetWindow->userData()._ownsContext = false;
496 }
497
498 if (api == RenderAPI::OpenGL)
499 {
500 if ( targetWindow->userData()._glContext == nullptr )
501 {
502 targetWindow->userData()._glContext = SDL_GL_CreateContext( targetWindow->getRawWindow() );
503 targetWindow->userData()._ownsContext = true;
504 ValidateAssert( SDL_GL_SetAttribute( SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1 ) );
505 }
506
507 if ( targetWindow->userData()._glContext == nullptr)
508 {
509 Console::errorfn(LOCALE_STR("ERROR_SDL_WINDOW"), SDL_GetError());
510 Console::warnfn(LOCALE_STR("WARN_SWITCH_API"));
511 Console::warnfn(LOCALE_STR("WARN_APPLICATION_CLOSE"));
513 }
514
515 if ( targetWindow->flags() & to_base(WindowFlags::VSYNC))
516 {
517 // Vsync is toggled on or off via the external config file
518 bool vsyncSet = false;
519 // Late swap may fail
520 if (context.config().runtime.adaptiveSync)
521 {
522 vsyncSet = SDL_GL_SetSwapInterval(-1) != -1;
523 if (!vsyncSet)
524 {
525 Console::warnfn(LOCALE_STR("WARN_ADAPTIVE_SYNC_NOT_SUPPORTED"));
526 }
527 }
528
529 if (!vsyncSet)
530 {
531 vsyncSet = SDL_GL_SetSwapInterval(1) != -1;
532 }
533
534 DIVIDE_ASSERT(vsyncSet, "VSync change failed!");
535 }
536 else
537 {
538 SDL_GL_SetSwapInterval(0);
539 }
540
541 // Creating a context will also set it as current in SDL. So ... unset it here.
542 Validate(SDL_GL_MakeCurrent( activeWindow->getRawWindow(), nullptr));
543 }
544
545 return ErrorCode::NO_ERR;
546}
547
549{
550
551 if ( window.parentWindow() == nullptr && _resolutionChangeQueued.second )
552 {
553 SizeChangeParams params{};
554 params.isFullScreen = window.fullscreen();
555 params.width = _resolutionChangeQueued.first.width;
556 params.height = _resolutionChangeQueued.first.height;
557 params.winGUID = mainWindow()->getGUID();
558 params.isMainWindow = window.getGUID() == mainWindow()->getGUID();
559
560 if ( _context->app().onResolutionChange( params ) )
561 {
562 NOP();
563 }
564
565 _resolutionChangeQueued.second = false;
566 }
567
568 pushActiveWindow(&window);
569
571}
572
574{
575 DisplayWindow* window = activeWindow();
576 DIVIDE_ASSERT( window != nullptr );
577
579
580 const size_t remainingWindows = popActiveWindow();
581
582 if ( remainingWindows > 0 )
583 {
584 // Switch back to the previous window we were drawing to
585 window = activeWindow();
586 DIVIDE_ASSERT( window != nullptr );
588
589 drawToWindow( *window );
590 }
591}
592
594{
595 switch ( mainWindow()->type() )
596 {
598 mainWindow()->changeType( WindowType::FULLSCREEN_WINDOWED );
599 break;
601 mainWindow()->changeType( WindowType::FULLSCREEN );
602 break;
604 mainWindow()->changeType( WindowType::WINDOW );
605 break;
607 default: DIVIDE_UNEXPECTED_CALL(); break;
608 }
609}
610
612{
613 stepResolution( true );
614}
615
617{
618 stepResolution( false );
619}
620
621void WindowManager::stepResolution( const bool increment )
622{
623 const auto compare = []( const vec2<U16> a, const vec2<U16> b ) noexcept -> bool
624 {
625 return a.x > b.x || a.y > b.y;
626 };
627
628 const auto& displayModes = DisplayManager::GetDisplayModes( mainWindow()->currentDisplayIndex() );
629
630 const auto renderingResolution = _context->gfx().renderingResolution();
631
632 bool found = false;
633 vec2<U16> foundRes;
634 if ( increment )
635 {
636 for ( auto it = displayModes.rbegin(); it != displayModes.rend(); ++it )
637 {
638 const vec2<U16> res = it->_resolution;
639 if ( compare( res, renderingResolution ) )
640 {
641 found = true;
642 foundRes.set( res );
643 break;
644 }
645 }
646 }
647 else
648 {
649 for ( const auto& mode : displayModes )
650 {
651 const vec2<U16> res = mode._resolution;
652 if ( compare( renderingResolution, res ) )
653 {
654 found = true;
655 foundRes.set( res );
656 break;
657 }
658 }
659 }
660
661 if ( found )
662 {
663 _resolutionChangeQueued.first.set( foundRes );
664 _resolutionChangeQueued.second = true;
665 }
666}
667
668void WindowManager::CaptureMouse(const bool state) noexcept
669{
670 SDL_CaptureMouse(state ? SDL_TRUE : SDL_FALSE);
671}
672
674{
675 const DisplayWindow* focusedWindow = getFocusedWindow();
676 if (focusedWindow == nullptr)
677 {
678 focusedWindow = mainWindow();
679 }
680
681 if (x == -1)
682 {
683 x = SDL_WINDOWPOS_CENTERED_DISPLAY(focusedWindow->currentDisplayIndex());
684 }
685
686 if (y == -1)
687 {
688 y = SDL_WINDOWPOS_CENTERED_DISPLAY(focusedWindow->currentDisplayIndex());
689 }
690
691 SDL_WarpMouseInWindow(focusedWindow->getRawWindow(), x, y);
692 return true;
693}
694
696{
697 if (x == -1)
698 {
699 x = SDL_WINDOWPOS_CENTERED;
700 }
701
702 if (y == -1)
703 {
704 y = SDL_WINDOWPOS_CENTERED;
705 }
706
707 return SDL_WarpMouseGlobal(x, y) == 0;
708}
709
711{
712 static CursorStyle s_CurrentStyle = CursorStyle::NONE;
713 if (style != s_CurrentStyle )
714 {
715 s_CurrentStyle = style;
716 SDL_SetCursor( s_cursors[to_base( style )] );
717 }
718}
719
720void WindowManager::ToggleRelativeMouseMode(const bool state) noexcept
721{
722 [[maybe_unused]] const I32 result = SDL_SetRelativeMouseMode(state ? SDL_TRUE : SDL_FALSE);
723 assert(result != -1);
724}
725
727{
728 return SDL_GetRelativeMouseMode() == SDL_TRUE;
729}
730
732{
733 vec2<I32> ret(-1);
734 SDL_GetGlobalMouseState(&ret.x, &ret.y);
735 return ret;
736}
737
739{
740 vec2<I32> ret(-1);
741 SDL_GetMouseState(&ret.x, &ret.y);
742 return ret;
743}
744
745U32 WindowManager::GetMouseState(vec2<I32>& pos, const bool global) noexcept
746{
747 if (global)
748 {
749 return to_U32(SDL_GetGlobalMouseState(&pos.x, &pos.y));
750 }
751
752 return to_U32(SDL_GetMouseState(&pos.x, &pos.y));
753}
754
755void WindowManager::SetCaptureMouse(const bool state) noexcept
756{
757 SDL_CaptureMouse(state ? SDL_TRUE : SDL_FALSE);
758}
759
761{
762 const DisplayWindow* focusedWindow = getFocusedWindow();
763 if (focusedWindow == nullptr)
764 {
765 focusedWindow = mainWindow();
766 }
767
768 const vec2<U16>& center = focusedWindow->getDimensions();
769 setCursorPosition(to_I32(center.x * 0.5f), to_I32(center.y * 0.5f));
770}
771
773{
774 for ( const auto& win : _windows)
775 {
776 win->hidden(true);
777 }
778}
779
780} //namespace Divide
#define LOCALE_STR(X)
Definition: Localization.h:91
#define MOV(...)
#define DIVIDE_ASSERT(...)
#define DIVIDE_UNEXPECTED_CALL()
#define NOP()
Class that provides an interface between our framework and the OS (start/stop, display support,...
Definition: Application.h:97
bool mainLoopPaused() const
Definition: Application.h:129
bool onResolutionChange(const SizeChangeParams &params) const
bool onWindowSizeChange(const SizeChangeParams &params) const
void RequestShutdown(bool clearCache) noexcept
Definition: Application.inl:45
static void RegisterDisplayMode(const U8 displayIndex, const DisplayManager::OutputDisplayProperties &mode)
Definition: Application.h:228
static void SetActiveDisplayCount(const U8 displayCount)
Definition: Application.h:223
static void drawToWindow(GFXDevice &device, DisplayWindow &window)
Definition: GFXDevice.h:667
static void flushWindow(GFXDevice &device, DisplayWindow &window)
Definition: GFXDevice.h:671
bool fullscreen() const noexcept
I32 currentDisplayIndex() const noexcept
vec2< U16 > getDimensions() const noexcept
SDL_Window * getRawWindow() const noexcept
void addEventListener(WindowEvent windowEvent, const EventListener &listener)
vec2< U16 > renderingResolution() const noexcept
Definition: GFXDevice.inl:174
FORCE_INLINE I64 getGUID() const noexcept
Definition: GUIDWrapper.h:51
Application & app() noexcept
GFXDevice & gfx() noexcept
Configuration & config() noexcept
void toggleFullScreen() const
static bool IsRelativeMouseMode() noexcept
static void CaptureMouse(bool state) noexcept
static vec2< U16 > GetFullscreenResolution() noexcept
DisplayWindow * activeWindow() const noexcept
static U32 GetMouseState(vec2< I32 > &pos, bool global) noexcept
DisplayWindow * getFocusedWindow() noexcept
static void DestroyAPISettings(DisplayWindow *window) noexcept
static ErrorCode ConfigureAPISettings(const PlatformContext &context, const WindowDescriptor &descriptor)
vector< std::unique_ptr< DisplayWindow > > _windows
vector< MonitorData > _monitors
static void ToggleRelativeMouseMode(bool state) noexcept
void stepResolution(bool increment)
static void SetCaptureMouse(bool state) noexcept
static vec2< I32 > GetGlobalCursorPosition() noexcept
size_t pushActiveWindow(DisplayWindow *window)
Returns the total number of active windows after the push.
static vec2< I32 > GetCursorPosition() noexcept
PlatformContext * _context
DisplayWindow * createWindow(const WindowDescriptor &descriptor, ErrorCode &err)
static ErrorCode ApplyAPISettings(const PlatformContext &context, RenderAPI api, DisplayWindow *targetWindow, DisplayWindow *activeWindow)
ErrorCode init(PlatformContext &context, RenderAPI renderingAPI, vec2< I16 > initialPosition, vec2< U16 > initialSize, WindowMode windowMode, I32 targetDisplayIndex)
static void SetCursorStyle(CursorStyle style)
size_t popActiveWindow()
Returns the remaining number of windows after the pop.
bool destroyWindow(DisplayWindow *&window)
static SDL_DisplayMode s_mainDisplayMode
static bool SetGlobalCursorPosition(I32 x, I32 y) noexcept
void hideAll() noexcept
bool setCursorPosition(I32 x, I32 y) noexcept
void drawToWindow(DisplayWindow &window)
static std::array< SDL_Cursor *, to_base(CursorStyle::COUNT)> s_cursors
std::pair< vec2< U16 >, bool > _resolutionChangeQueued
void set(const T *v) noexcept
set the 2 components of the vector manually using a source pointer to a (large enough) array
Definition: MathVectors.h:335
vec2< T > xy
Definition: MathVectors.h:1366
vec2< T > zw
Definition: MathVectors.h:1366
constexpr bool ENABLE_GPU_VALIDATION
Error callbacks, validations, buffer checks, etc. are controlled by this flag. Heavy performance impa...
Definition: config.h:192
void DestroyPools() noexcept
void InitPools(const size_t poolSizeFactor)
bool ReplaceStringInPlace(T_str &subject, std::span< const std::string_view > search, std::string_view replace, bool recursive=false)
SDL_SystemCursor CursorToSDL(const CursorStyle style) noexcept
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
constexpr U32 to_U32(const T value)
constexpr U16 to_U16(const T value)
int32_t I32
uint8_t U8
@ Vulkan
not supported yet
@ None
No rendering. Used for testing or server code.
void efficient_clear(eastl::fixed_vector< T, nodeCount, bEnableOverflow, OverflowAllocator > &fixed_vector)
Definition: Vector.h:52
constexpr U8 to_U8(const T value)
constexpr I16 to_I16(const T value)
constexpr I32 to_I32(const T value)
uint32_t U32
constexpr auto to_base(const Type value) -> Type
struct Divide::Configuration::Debug::Renderer renderer
struct Divide::Configuration::Rendering rendering
struct Divide::Configuration::Runtime runtime
struct Divide::Configuration::Debug debug
static NO_INLINE void d_printfn(const char *format, T &&... args)
static NO_INLINE void errorfn(const char *format, T &&... args)
static NO_INLINE void warnfn(const char *format, T &&... args)
U8 _maxRefreshRate
As returned by SDL_GetPixelFormatName.
Definition: Application.h:169
static const OutputDisplayPropertiesContainer & GetDisplayModes(const size_t displayIndex) noexcept
static constexpr U8 g_maxDisplayOutputs
Definition: Application.h:176
U16 width
The new width and height.
bool isFullScreen
Is the window that fired the event fullscreen?
DisplayWindow * parentWindow