• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Return-To-The-Roots / s25client / 20447000712

22 Dec 2025 11:43PM UTC coverage: 50.458% (-0.05%) from 50.503%
20447000712

Pull #1804

github

web-flow
Merge 642be1157 into af2863637
Pull Request #1804: Android build

66 of 229 new or added lines in 13 files covered. (28.82%)

13 existing lines in 4 files now uncovered.

22589 of 44768 relevant lines covered (50.46%)

35177.2 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

9.51
/extras/videoDrivers/SDL2/VideoSDL2.cpp
1
// Copyright (C) 2005 - 2025 Settlers Freaks (sf-team at siedler25.org)
2
//
3
// SPDX-License-Identifier: GPL-2.0-or-later
4

5
#include "VideoSDL2.h"
6
#include "driver/Interface.h"
7
#include "driver/VideoDriverLoaderInterface.h"
8
#include "driver/VideoInterface.h"
9
#include "enum_cast.hpp"
10
#include "helpers/LSANUtils.h"
11
#include "helpers/containerUtils.h"
12
#include "icon.h"
13
#include "openglCfg.hpp"
14
#include <s25util/utf8.h>
15
#include <boost/nowide/iostream.hpp>
16
#include <SDL.h>
17
#include <SDL_hints.h>
18
#include <algorithm>
19
#include <memory>
20

21
#ifdef _WIN32
22
#    include <boost/nowide/convert.hpp>
23
#    ifndef WIN32_LEAN_AND_MEAN
24
#        define WIN32_LEAN_AND_MEAN
25
#    endif
26
#    include <windows.h> // Avoid "Windows headers require the default packing option" due to SDL2
27
#    include <SDL_syswm.h>
28
#endif // _WIN32
29
#if RTTR_OGL_GL4ES
30
#    include <gl4esinit.h>
31
#endif
32

33
#define CHECK_SDL(call)                 \
34
    ([&]() -> bool {                    \
35
        if((call) < 0)                  \
36
        {                               \
37
            PrintError(SDL_GetError()); \
38
            return false;               \
39
        }                               \
40
        return true;                    \
41
    })()
42

43
namespace {
44
template<typename T>
45
struct SDLMemoryDeleter
46
{
47
    void operator()(T* p) const { SDL_free(p); }
×
48
};
49

50
#if RTTR_OGL_ES || RTTR_OGL_GL4ES
51
constexpr SDL_GLprofile RTTR_SDL_GL_PROFILE = SDL_GL_CONTEXT_PROFILE_ES;
52
#elif RTTR_OGL_COMPAT
53
constexpr SDL_GLprofile RTTR_SDL_GL_PROFILE = SDL_GL_CONTEXT_PROFILE_COMPATIBILITY;
54
#else
55
constexpr SDL_GLprofile RTTR_SDL_GL_PROFILE = SDL_GL_CONTEXT_PROFILE_CORE;
56
#endif
57

58
template<typename T>
59
using SDL_memory = std::unique_ptr<T, SDLMemoryDeleter<T>>;
60

61
void setSpecialKeys(KeyEvent& ke, const SDL_Keymod mod)
×
62
{
63
    ke.ctrl = (mod & KMOD_CTRL);
×
64
    ke.shift = (mod & KMOD_SHIFT);
×
65
    ke.alt = (mod & KMOD_ALT);
×
66
}
×
67
void setSpecialKeys(KeyEvent& ke)
×
68
{
69
    setSpecialKeys(ke, SDL_GetModState());
×
70
}
×
71
} // namespace
72

73
IVideoDriver* CreateVideoInstance(VideoDriverLoaderInterface* CallBack)
1✔
74
{
75
    return new VideoSDL2(CallBack);
1✔
76
}
77

78
void FreeVideoInstance(IVideoDriver* driver)
1✔
79
{
80
    delete driver;
1✔
81
}
1✔
82

83
const char* GetDriverName()
5✔
84
{
85
#if RTTR_OGL_GL4ES
86
    return "(SDL2) OpenGL-ES gl4es via SDL2-Library";
87
#else
88
    return "(SDL2) OpenGL via SDL2-Library";
5✔
89
#endif
90
}
91

92
VideoSDL2::VideoSDL2(VideoDriverLoaderInterface* CallBack) : VideoDriver(CallBack), window(nullptr), context(nullptr) {}
1✔
93

94
VideoSDL2::~VideoSDL2()
2✔
95
{
96
    CleanUp();
1✔
97
}
2✔
98

99
const char* VideoSDL2::GetName() const
2✔
100
{
101
    return GetDriverName();
2✔
102
}
103

104
bool VideoSDL2::Initialize()
1✔
105
{
106
    initialized = false;
1✔
107
    rttr::ScopedLeakDisabler _;
1✔
108
    // Do not emulate mouse events using touch
109
    SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
1✔
110
    if(SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
1✔
111
    {
112
        PrintError(SDL_GetError());
×
113
        return false;
×
114
    }
115

116
    initialized = true;
1✔
117
    return initialized;
1✔
118
}
119

120
void VideoSDL2::CleanUp()
1✔
121
{
122
    if(!initialized)
1✔
123
        return;
×
124

125
    if(context)
1✔
126
        SDL_GL_DeleteContext(context);
×
127
    if(window)
1✔
128
        SDL_DestroyWindow(window);
×
129
    SDL_QuitSubSystem(SDL_INIT_VIDEO);
1✔
130
    SDL_Quit();
1✔
131
    initialized = false;
1✔
132
}
133

134
void VideoSDL2::UpdateCurrentSizes()
×
135
{
136
    int w, h, w2, h2;
137
    SDL_GetWindowSize(window, &w, &h);
×
138
    SDL_GL_GetDrawableSize(window, &w2, &h2);
×
139
    SetNewSize(VideoMode(w, h), Extent(w2, h2));
×
140
}
×
141

142
bool VideoSDL2::CreateScreen(const std::string& title, const VideoMode& size, bool fullscreen)
×
143
{
144
    if(!initialized)
×
145
        return false;
×
146

147
    // GL-Attributes
148
    CHECK_SDL(SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RTTR_OGL_MAJOR));
×
149
    CHECK_SDL(SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RTTR_OGL_MINOR));
×
NEW
150
    CHECK_SDL(SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, RTTR_SDL_GL_PROFILE));
×
151

152
    CHECK_SDL(SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8));
×
153
    CHECK_SDL(SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8));
×
154
    CHECK_SDL(SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8));
×
155
    CHECK_SDL(SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1));
×
156

157
    int wndPos = SDL_WINDOWPOS_CENTERED;
×
158

159
    const auto requestedSize = fullscreen ? FindClosestVideoMode(size) : size;
×
160
    unsigned commonFlags = SDL_WINDOW_OPENGL;
×
161
    // TODO: Fix GUI scaling with High DPI support enabled.
162
    // See https://github.com/Return-To-The-Roots/s25client/issues/1621
163
    // commonFlags |= SDL_WINDOW_ALLOW_HIGHDPI;
164

165
    window = SDL_CreateWindow(title.c_str(), wndPos, wndPos, requestedSize.width, requestedSize.height,
×
166
                              commonFlags | (fullscreen ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_RESIZABLE));
×
167

168
    // Fallback to non-fullscreen
169
    if(!window && fullscreen)
×
170
    {
171
        window = SDL_CreateWindow(title.c_str(), wndPos, wndPos, requestedSize.width, requestedSize.height,
×
172
                                  commonFlags | SDL_WINDOW_RESIZABLE);
173
    }
174

175
    if(!window)
×
176
    {
177
        PrintError(SDL_GetError());
×
178
        return false;
×
179
    }
180

181
    isFullscreen_ = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0;
×
182
    UpdateCurrentSizes();
×
183

184
    if(!isFullscreen_)
×
185
        MoveWindowToCenter();
×
186

187
    SDL_Surface* iconSurf =
188
      SDL_CreateRGBSurfaceFrom(image.data(), 48, 48, 32, 48 * 4, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
×
189
    if(iconSurf)
×
190
    {
191
        SDL_SetWindowIcon(window, iconSurf);
×
192
        SDL_FreeSurface(iconSurf);
×
193
    } else
194
        PrintError(SDL_GetError());
×
195

196
    context = SDL_GL_CreateContext(window);
×
197

198
#ifdef _WIN32
199
    SetWindowTextW(GetConsoleWindow(), boost::nowide::widen(title).c_str());
200
#endif
201

202
    std::fill(keyboard.begin(), keyboard.end(), false);
×
203

204
    SDL_ShowCursor(0);
×
205

206
    return true;
×
207
}
208

209
bool VideoSDL2::ResizeScreen(const VideoMode& newSize, bool fullscreen)
×
210
{
211
    if(!initialized)
×
212
        return false;
×
213

214
    if(isFullscreen_ != fullscreen)
×
215
    {
216
        SDL_SetWindowFullscreen(window, fullscreen ? SDL_WINDOW_FULLSCREEN : 0);
×
217
        isFullscreen_ = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0;
×
218
        if(!isFullscreen_)
×
219
        {
220
            SDL_SetWindowResizable(window, SDL_TRUE);
×
221
            MoveWindowToCenter();
×
222
        }
223
    }
224

225
    if(newSize != GetWindowSize())
×
226
    {
227
        if(isFullscreen_)
×
228
        {
229
            auto const targetMode = FindClosestVideoMode(newSize);
×
230
            SDL_DisplayMode target;
231
            target.w = targetMode.width;
×
232
            target.h = targetMode.height;
×
233
            target.format = 0;           // don't care
×
234
            target.refresh_rate = 0;     // don't care
×
235
            target.driverdata = nullptr; // initialize to 0
×
236
            // Explicitly change the window size to avoid a bug with SDL reporting the wrong size until alt+tab
237
            SDL_SetWindowSize(window, target.w, target.h);
×
238
            if(SDL_SetWindowDisplayMode(window, &target) < 0)
×
239
            {
240
                PrintError(SDL_GetError());
×
241
                return false;
×
242
            }
243
        } else
244
        {
245
            SDL_SetWindowSize(window, newSize.width, newSize.height);
×
246
        }
247
        UpdateCurrentSizes();
×
248
    }
249
    return true;
×
250
}
251

252
#ifdef __ANDROID__
253
void VideoSDL2::PrintError(const std::string&) const
254
{ // Not really sure why the nowide::cerr function completely crashes on android
255
}
256
#else
UNCOV
257
void VideoSDL2::PrintError(const std::string& msg) const
×
258
{
259
    boost::nowide::cerr << msg << std::endl;
×
260
}
×
261
#endif
262

263
void VideoSDL2::ShowErrorMessage(const std::string& title, const std::string& message)
×
264
{
265
    // window==nullptr is okay too ("no parent")
266
#ifdef __linux__
267
    // When using window, SDL will try to use a system tool like "zenity" which isn't always installed on every distro
268
    // so rttr will crash. But without a window it will use an x11 backend that should be available on x11 AND wayland
269
    // for compatibility reasons
270
    SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title.c_str(), message.c_str(), nullptr);
×
271
#else
272
    SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title.c_str(), message.c_str(), window);
273
#endif
274
}
×
275

276
void VideoSDL2::HandlePaste()
×
277
{
278
    if(!SDL_HasClipboardText())
×
279
        return;
×
280

281
    SDL_memory<char> text(SDL_GetClipboardText());
×
282
    if(!text || *text == '\0') // empty string indicates error
×
283
        PrintError(text ? SDL_GetError() : "Paste failed.");
×
284

285
    for(const char32_t c : s25util::utf8to32(text.get()))
×
286
        CallBack->Msg_KeyDown(KeyEvent(c));
×
287
}
288

289
void VideoSDL2::DestroyScreen()
×
290
{
291
    CleanUp();
×
292
}
×
293

294
bool VideoSDL2::SwapBuffers()
×
295
{
296
    SDL_GL_SwapWindow(window);
×
297
    return true;
×
298
}
299

300
bool VideoSDL2::MessageLoop()
×
301
{
302
    SDL_Event ev;
303
    while(SDL_PollEvent(&ev))
×
304
    {
305
        switch(ev.type)
×
306
        {
307
            default: break;
×
308

309
            case SDL_QUIT: return false;
×
310
            case SDL_WINDOWEVENT:
×
311
            {
312
                switch(ev.window.event)
×
313
                {
314
                    case SDL_WINDOWEVENT_RESIZED:
×
315
                    {
316
                        isFullscreen_ = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0;
×
317
                        VideoMode newSize(ev.window.data1, ev.window.data2);
×
318
                        if(newSize != GetWindowSize())
×
319
                        {
320
                            UpdateCurrentSizes();
×
321
                            CallBack->WindowResized();
×
322
                        }
323
                    }
324
                    break;
×
325
                }
326
            }
327
            break;
×
328

329
            case SDL_KEYDOWN:
×
330
            {
331
                KeyEvent ke;
×
332

333
                switch(ev.key.keysym.sym)
×
334
                {
335
                    default:
×
336
                    {
337
                        // Die 12 F-Tasten
338
                        if(ev.key.keysym.sym >= SDLK_F1 && ev.key.keysym.sym <= SDLK_F12)
×
339
                            ke.kt = static_cast<KeyType>(rttr::enum_cast(KeyType::F1) + ev.key.keysym.sym - SDLK_F1);
×
340
                    }
341
                    break;
×
342
                    case SDLK_RETURN: ke.kt = KeyType::Return; break;
×
343
                    case SDLK_SPACE: ke.kt = KeyType::Space; break;
×
344
                    case SDLK_LEFT: ke.kt = KeyType::Left; break;
×
345
                    case SDLK_RIGHT: ke.kt = KeyType::Right; break;
×
346
                    case SDLK_UP: ke.kt = KeyType::Up; break;
×
347
                    case SDLK_DOWN: ke.kt = KeyType::Down; break;
×
348
                    case SDLK_BACKSPACE: ke.kt = KeyType::Backspace; break;
×
349
                    case SDLK_DELETE: ke.kt = KeyType::Delete; break;
×
350
                    case SDLK_LSHIFT:
×
351
                    case SDLK_RSHIFT: ke.kt = KeyType::Shift; break;
×
352
                    case SDLK_TAB: ke.kt = KeyType::Tab; break;
×
353
                    case SDLK_HOME: ke.kt = KeyType::Home; break;
×
354
                    case SDLK_END: ke.kt = KeyType::End; break;
×
355
                    case SDLK_ESCAPE: ke.kt = KeyType::Escape; break;
×
356
                    case SDLK_PRINTSCREEN: ke.kt = KeyType::Print; break;
×
357
                    // case SDLK_BACKQUOTE: ev.key.keysym.scancode = '^'; break;
358
                    case SDLK_v:
×
359
                        if(SDL_GetModState() & KMOD_CTRL)
×
360
                        {
361
                            HandlePaste();
×
362
                            continue;
×
363
                        }
364
                        break;
×
365
                }
366

367
                setSpecialKeys(ke, SDL_Keymod(ev.key.keysym.mod));
×
368

369
                if(ke.kt != KeyType::Invalid)
×
370
                    CallBack->Msg_KeyDown(ke);
×
371
                else if(ke.alt || ke.ctrl)
×
372
                {
373
                    // Handle shortcuts (CTRL+x, ALT+y)
374
                    // but not possible combinations (ALT+0054)
375
                    const SDL_Keycode keycode = ev.key.keysym.sym;
×
376
                    if(keycode >= 'a' && keycode <= 'z')
×
377
                    {
378
                        ke.kt = KeyType::Char;
×
379
                        ke.c = static_cast<char32_t>(keycode);
×
380
                        CallBack->Msg_KeyDown(ke);
×
381
                    }
382
                }
383
            }
384
            break;
×
385
            case SDL_TEXTINPUT:
×
386
            {
387
                const std::u32string text = s25util::utf8to32(ev.text.text);
×
388
                KeyEvent ke(0);
×
389
                setSpecialKeys(ke);
×
390
                for(char32_t c : text)
×
391
                {
392
                    ke.c = c;
×
393
                    CallBack->Msg_KeyDown(ke);
×
394
                }
395
                break;
×
396
            }
397
            case SDL_MOUSEBUTTONDOWN:
×
398
                mouse_xy.pos = getGuiScale().screenToView(Position(ev.button.x, ev.button.y));
×
399

400
                if(/*!mouse_xy.ldown && */ ev.button.button == SDL_BUTTON_LEFT)
×
401
                {
402
                    mouse_xy.ldown = true;
×
403
                    CallBack->Msg_LeftDown(mouse_xy);
×
404
                }
405
                if(/*!mouse_xy.rdown &&*/ ev.button.button == SDL_BUTTON_RIGHT)
×
406
                {
407
                    mouse_xy.rdown = true;
×
408
                    CallBack->Msg_RightDown(mouse_xy);
×
409
                }
410
                break;
×
411
            case SDL_MOUSEBUTTONUP:
×
412
                mouse_xy.pos = getGuiScale().screenToView(Position(ev.button.x, ev.button.y));
×
413

414
                if(/*mouse_xy.ldown &&*/ ev.button.button == SDL_BUTTON_LEFT)
×
415
                {
416
                    mouse_xy.ldown = false;
×
417
                    CallBack->Msg_LeftUp(mouse_xy);
×
418
                }
419
                if(/*mouse_xy.rdown &&*/ ev.button.button == SDL_BUTTON_RIGHT)
×
420
                {
421
                    mouse_xy.rdown = false;
×
422
                    CallBack->Msg_RightUp(mouse_xy);
×
423
                }
424
                break;
×
425
            case SDL_MOUSEWHEEL:
×
426
            {
427
                int y = ev.wheel.y;
×
428
                if(ev.wheel.direction == SDL_MOUSEWHEEL_FLIPPED)
×
429
                    y = -y;
×
430
                if(y > 0)
×
431
                    CallBack->Msg_WheelUp(mouse_xy);
×
432
                else if(y < 0)
×
433
                    CallBack->Msg_WheelDown(mouse_xy);
×
434
            }
435
            break;
×
436
            case SDL_MOUSEMOTION:
×
437
            {
438
                const auto newPos = getGuiScale().screenToView(Position(ev.motion.x, ev.motion.y));
×
439
                // Avoid duplicate events especially when warping the mouse
440
                if(newPos != mouse_xy.pos)
×
441
                {
442
                    mouse_xy.pos = newPos;
×
443
                    CallBack->Msg_MouseMove(mouse_xy);
×
444
                }
445
            }
446
            break;
×
NEW
447
            case SDL_FINGERDOWN:
×
448
            {
NEW
449
                VideoMode wnSize = GetWindowSize();
×
NEW
450
                mouse_xy.pos = getGuiScale().screenToView(Position(static_cast<int>(ev.tfinger.x * wnSize.width),
×
NEW
451
                                                                   static_cast<int>(ev.tfinger.y * wnSize.height)));
×
NEW
452
                mouse_xy.ldown = true;
×
NEW
453
                mouse_xy.num_tfingers++;
×
NEW
454
                CallBack->Msg_LeftDown(mouse_xy);
×
NEW
455
                break;
×
456
            }
NEW
457
            case SDL_FINGERUP:
×
458
            {
NEW
459
                VideoMode wnSize = GetWindowSize();
×
NEW
460
                mouse_xy.pos = getGuiScale().screenToView(Position(static_cast<int>(ev.tfinger.x * wnSize.width),
×
NEW
461
                                                                   static_cast<int>(ev.tfinger.y * wnSize.height)));
×
NEW
462
                mouse_xy.ldown = false;
×
NEW
463
                CallBack->Msg_LeftUp(mouse_xy);
×
NEW
464
                mouse_xy.num_tfingers--; // Dirty way to count leftUp as touch event without extra isTouch bool
×
NEW
465
                break;
×
466
            }
NEW
467
            case SDL_FINGERMOTION:
×
468
            {
NEW
469
                VideoMode wnSize = GetWindowSize();
×
NEW
470
                const auto newPos = getGuiScale().screenToView(Position(
×
NEW
471
                  static_cast<int>(ev.tfinger.x * wnSize.width), static_cast<int>(ev.tfinger.y * wnSize.height)));
×
472

NEW
473
                if(newPos != mouse_xy.pos)
×
474
                {
NEW
475
                    mouse_xy.pos = newPos;
×
NEW
476
                    CallBack->Msg_MouseMove(mouse_xy);
×
477
                }
NEW
478
                break;
×
479
            }
NEW
480
            case SDL_MULTIGESTURE:
×
481
            {
NEW
482
                if(std::fabs(ev.mgesture.dDist) > 0.001)
×
483
                {
NEW
484
                    if(ev.mgesture.dDist > 0)
×
NEW
485
                        CallBack->Msg_WheelUp(mouse_xy);
×
486
                    else
NEW
487
                        CallBack->Msg_WheelDown(mouse_xy);
×
488
                }
NEW
489
                break;
×
490
            }
491
        }
492
    }
493

494
    return true;
×
495
}
496

497
unsigned long VideoSDL2::GetTickCount() const
×
498
{
499
    return SDL_GetTicks();
×
500
}
501

502
void VideoSDL2::ListVideoModes(std::vector<VideoMode>& video_modes) const
×
503
{
504
    int display = SDL_GetWindowDisplayIndex(window);
×
505
    if(display < 0)
×
506
        display = 0;
×
507
    for(int i = SDL_GetNumDisplayModes(display) - 1; i >= 0; --i)
×
508
    {
509
        SDL_DisplayMode mode;
510
        if(SDL_GetDisplayMode(display, i, &mode) != 0)
×
511
            PrintError(SDL_GetError());
×
512
        else
513
        {
514
            VideoMode vm(mode.w, mode.h);
×
515
            if(!helpers::contains(video_modes, vm))
×
516
                video_modes.push_back(vm);
×
517
        }
518
    }
519
}
×
520

521
OpenGL_Loader_Proc VideoSDL2::GetLoaderFunction() const
×
522
{
523
#if RTTR_OGL_GL4ES
524
    return gl4es_GetProcAddress;
525
#else
UNCOV
526
    return SDL_GL_GetProcAddress;
×
527
#endif
528
}
529

530
void VideoSDL2::SetMousePos(Position pos)
×
531
{
532
    const auto screenPos = getGuiScale().viewToScreen(pos);
×
533
    mouse_xy.pos = pos;
×
534
    SDL_WarpMouseInWindow(window, screenPos.x, screenPos.y);
×
535
}
×
536

537
KeyEvent VideoSDL2::GetModKeyState() const
×
538
{
539
    KeyEvent ke;
×
540
    setSpecialKeys(ke);
×
541
    return ke;
×
542
}
543

544
void* VideoSDL2::GetMapPointer() const
×
545
{
546
#ifdef WIN32
547
    SDL_SysWMinfo wmInfo;
548
    SDL_VERSION(&wmInfo.version);
549
    SDL_GetWindowWMInfo(window, &wmInfo);
550
    // return (void*)wmInfo.info.win.window;
551
    return (void*)wmInfo.info.win.window;
552
#else
553
    return nullptr;
×
554
#endif
555
}
556

557
void VideoSDL2::MoveWindowToCenter()
×
558
{
559
    SDL_Rect usableBounds;
560
    CHECK_SDL(SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(window), &usableBounds));
×
561
    int top, left, bottom, right;
NEW
562
    if(CHECK_SDL(SDL_GetWindowBordersSize(window, &top, &left, &bottom, &right)) != 0)
×
NEW
563
        top = left = bottom = right = 0;
×
564
    usableBounds.w -= left + right;
×
565
    usableBounds.h -= top + bottom;
×
566
    if(usableBounds.w < GetWindowSize().width || usableBounds.h < GetWindowSize().height)
×
567
    {
568
        SDL_SetWindowSize(window, usableBounds.w, usableBounds.h);
×
569
        UpdateCurrentSizes();
×
570
    }
571
    SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
×
572
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc