GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/tabs/setup_video.cpp Lines: 93 211 44.1 %
Date: 2021-03-17 Branches: 115 436 26.4 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2004-2009  The Mana World Development Team
4
 *  Copyright (C) 2009-2010  The Mana Developers
5
 *  Copyright (C) 2011-2019  The ManaPlus Developers
6
 *  Copyright (C) 2019-2021  Andrei Karas
7
 *
8
 *  This file is part of The ManaPlus Client.
9
 *
10
 *  This program is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU General Public License as published by
12
 *  the Free Software Foundation; either version 2 of the License, or
13
 *  any later version.
14
 *
15
 *  This program is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU General Public License
21
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 */
23
24
#include "gui/widgets/tabs/setup_video.h"
25
26
#include "gui/windowmanager.h"
27
28
#include "gui/windows/okdialog.h"
29
#include "gui/windows/textdialog.h"
30
31
#include "gui/widgets/button.h"
32
#include "gui/widgets/checkbox.h"
33
#include "gui/widgets/containerplacer.h"
34
#include "gui/widgets/createwidget.h"
35
#include "gui/widgets/label.h"
36
#include "gui/widgets/layouthelper.h"
37
#include "gui/widgets/listbox.h"
38
#include "gui/widgets/scrollarea.h"
39
#include "gui/widgets/slider.h"
40
#include "gui/widgets/dropdown.h"
41
42
#include "utils/delete2.h"
43
44
#if defined(USE_OPENGL) && !defined(ANDROID) && !defined(__APPLE__)
45
#include "graphicsmanager.h"
46
47
#include "test/testmain.h"
48
#endif  // defined(USE_OPENGL) && !defined(ANDROID) && !defined(__APPLE__)
49
50
#if defined(ANDROID) || defined(__APPLE__) || !defined(USE_OPENGL)
51
#include "configuration.h"
52
#endif  // defined(ANDROID) || defined(__APPLE__) || !defined(USE_OPENGL)
53
54
#if defined(ANDROID) || defined(__APPLE__)
55
#include "utils/stringutils.h"
56
#endif  // defined(ANDROID) || defined(__APPLE__)
57
58
#include "gui/models/modelistmodel.h"
59
#include "gui/models/opengllistmodel.h"
60
61
#include <sstream>
62
63
#include "debug.h"
64
65
2
Setup_Video::Setup_Video(const Widget2 *const widget) :
66
    SetupTab(widget),
67
    KeyListener(),
68

8
    mFullScreenEnabled(config.getBoolValue("screen")),
69

8
    mOpenGLEnabled(intToRenderType(config.getIntValue("opengl"))),
70

8
    mFps(config.getIntValue("fpslimit")),
71

8
    mAltFps(config.getIntValue("altfpslimit")),
72

2
    mModeListModel(new ModeListModel),
73
4
    mOpenGLListModel(new OpenGLListModel),
74


8
    mModeList(CREATEWIDGETR(ListBox, widget, mModeListModel, "")),
75
    // TRANSLATORS: video settings checkbox
76
4
    mFsCheckBox(new CheckBox(this, _("Full screen"), mFullScreenEnabled,
77

6
        nullptr, std::string())),
78
2
    mOpenGLDropDown(new DropDown(widget, mOpenGLListModel,
79

6
        false, Modal_false, nullptr, std::string())),
80
    // TRANSLATORS: video settings checkbox
81
2
    mFpsCheckBox(new CheckBox(this, _("FPS limit:"), false,
82

4
        nullptr, std::string())),
83

2
    mFpsSlider(new Slider(this, 2.0, 160.0, 1.0)),
84

2
    mFpsLabel(new Label(this)),
85

2
    mAltFpsSlider(new Slider(this, 2.0, 160.0, 1.0)),
86
    // TRANSLATORS: video settings label
87

4
    mAltFpsLabel(new Label(this, _("Alt FPS limit: "))),
88
#if !defined(ANDROID) && !defined(__APPLE__)
89
#if !defined(__native_client__) && !defined(__SWITCH__)
90
    // TRANSLATORS: video settings button
91
2
    mDetectButton(new Button(this, _("Detect best mode"), "detect",
92

2
        BUTTON_SKIN, this)),
93
#endif  // !defined(__native_client__) && !defined(__SWITCH__)
94
#endif  // !defined(ANDROID) && !defined(__APPLE__) &&
95
    mDialog(nullptr),
96

8
    mCustomCursorEnabled(config.getBoolValue("customcursor")),
97

8
    mEnableResize(config.getBoolValue("enableresize")),
98

8
    mNoFrame(config.getBoolValue("noframe")),
99
#ifdef USE_SDL2
100
    mAllowHighDPI(config.getBoolValue("allowHighDPI")),
101
    // TRANSLATORS: video settings checkbox
102
    mAllowHighDPICheckBox(new CheckBox(this, _("High DPI"), mAllowHighDPI,
103
        nullptr, std::string())),
104
#endif  // USE_SDL2
105
    mCustomCursorCheckBox(new CheckBox(this,
106
#ifdef ANDROID
107
        // TRANSLATORS: video settings checkbox
108
        _("Show cursor"),
109
#else  // ANDROID
110
        // TRANSLATORS: video settings checkbox
111
2
        _("Custom cursor"),
112
#endif  // ANDROID
113
2
        mCustomCursorEnabled,
114

6
        nullptr, std::string())),
115
    // TRANSLATORS: video settings checkbox
116
2
    mEnableResizeCheckBox(new CheckBox(this, _("Enable resize"),
117

4
        mEnableResize, nullptr, std::string())),
118
    // TRANSLATORS: video settings checkbox
119
4
    mNoFrameCheckBox(new CheckBox(this, _("No frame"), mNoFrame,
120





104
        nullptr, std::string()))
121
{
122
    // TRANSLATORS: video settings tab name
123
10
    setName(_("Video"));
124
125
2
    ScrollArea *const scrollArea = new ScrollArea(this, mModeList,
126

10
        Opaque_true, "setup_video_background.xml");
127
2
    scrollArea->setWidth(150);
128
2
    scrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
129
130
2
    mOpenGLDropDown->setSelected(renderToIndex[mOpenGLEnabled]);
131
132
4
    mModeList->setEnabled(true);
133
134
    // TRANSLATORS: video settings label
135


4
    mFpsLabel->setCaption(mFps > 0 ? toString(mFps) : _("None"));
136
2
    mFpsLabel->setWidth(60);
137
    // TRANSLATORS: video settings label
138


6
    mAltFpsLabel->setCaption(_("Alt FPS limit: ") + (mAltFps > 0 ?
139
        // TRANSLATORS: video settings label value
140
2
        toString(mAltFps) : _("None")));
141
2
    mAltFpsLabel->setWidth(150);
142
4
    mFpsSlider->setEnabled(mFps > 0);
143
2
    mFpsSlider->setValue(mFps);
144
4
    mAltFpsSlider->setEnabled(mAltFps > 0);
145
2
    mAltFpsSlider->setValue(mAltFps);
146
4
    mFpsCheckBox->setSelected(mFps > 0);
147
148
    // Pre-select the current video mode.
149
4
    const std::string videoMode = toString(
150
2
        mainGraphics->mActualWidth).append("x").append(
151
10
        toString(mainGraphics->mActualHeight));
152

2
    mModeList->setSelected(mModeListModel->getIndexOf(videoMode));
153
154
10
    mModeList->setActionEventId("videomode");
155
10
    mCustomCursorCheckBox->setActionEventId("customcursor");
156
10
    mFpsCheckBox->setActionEventId("fpslimitcheckbox");
157
10
    mFpsSlider->setActionEventId("fpslimitslider");
158
10
    mAltFpsSlider->setActionEventId("altfpslimitslider");
159
10
    mOpenGLDropDown->setActionEventId("opengl");
160
10
    mEnableResizeCheckBox->setActionEventId("enableresize");
161
10
    mNoFrameCheckBox->setActionEventId("noframe");
162
#ifdef USE_SDL2
163
    mAllowHighDPICheckBox->setActionEventId("allowHighDPI");
164
    mAllowHighDPICheckBox->addActionListener(this);
165
#endif  // USE_SDL2
166
167
2
    mModeList->addActionListener(this);
168
2
    mCustomCursorCheckBox->addActionListener(this);
169
2
    mFpsCheckBox->addActionListener(this);
170
2
    mFpsSlider->addActionListener(this);
171
2
    mAltFpsSlider->addActionListener(this);
172
2
    mOpenGLDropDown->addActionListener(this);
173
2
    mEnableResizeCheckBox->addActionListener(this);
174
2
    mNoFrameCheckBox->addActionListener(this);
175
176
    // Do the layout
177
4
    LayoutHelper h(this);
178
2
    ContainerPlacer place = h.getPlacer(0, 0);
179
180
4
    place(0, 0, scrollArea, 1, 5).setPadding(2);
181

2
    place(0, 5, mOpenGLDropDown, 1, 1);
182
183
2
    place(1, 0, mFsCheckBox, 2, 1);
184
185
2
    place(1, 1, mCustomCursorCheckBox, 3, 1);
186
187
2
    place(1, 2, mEnableResizeCheckBox, 2, 1);
188
2
    place(1, 3, mNoFrameCheckBox, 2, 1);
189
#ifdef USE_SDL2
190
    place(1, 4, mAllowHighDPICheckBox, 2, 1);
191
#endif  // USE_SDL2
192
193
2
    place(0, 6, mFpsSlider, 1, 1);
194
4
    place(1, 6, mFpsCheckBox, 1, 1).setPadding(3);
195
4
    place(2, 6, mFpsLabel, 1, 1).setPadding(1);
196
197
2
    place(0, 7, mAltFpsSlider, 1, 1);
198
4
    place(1, 7, mAltFpsLabel, 1, 1).setPadding(3);
199
200
#if !defined(ANDROID) && !defined(__APPLE__) && \
201
    !defined(__native_client__)  && !defined(__SWITCH__)
202
2
    place(0, 8, mDetectButton, 1, 1);
203
#else  // !defined(ANDROID) && !defined(__APPLE__) &&
204
       // !defined(__native_client__)
205
    mNoFrameCheckBox->setEnabled(false);
206
    mEnableResizeCheckBox->setEnabled(false);
207
#ifndef __native_client__
208
    mFsCheckBox->setEnabled(false);
209
#endif  // __native_client__
210
#endif  // !defined(ANDROID) && !defined(__APPLE__) &&
211
        // !defined(__native_client__)
212
213
2
    int width = 600;
214
215

8
    if (config.getIntValue("screenwidth") >= 730)
216
2
        width += 100;
217
218
2
    setDimension(Rect(0, 0, width, 300));
219
2
}
220
221
8
Setup_Video::~Setup_Video()
222
{
223
4
    delete2(mModeListModel)
224
2
    delete2(mModeList)
225
4
    delete2(mOpenGLListModel)
226
2
    delete2(mDialog)
227
4
}
228
229
void Setup_Video::apply()
230
{
231
    // Full screen changes
232
    bool fullscreen = mFsCheckBox->isSelected();
233
    if (fullscreen != config.getBoolValue("screen"))
234
    {
235
        /* The OpenGL test is only necessary on Windows, since switching
236
         * to/from full screen works fine on Linux. On Windows we'd have to
237
         * reinitialize the OpenGL state and reload all textures.
238
         *
239
         * See http://libsdl.org/cgi/docwiki.cgi/SDL_SetVideoMode
240
         */
241
242
#if defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
243
        // checks for opengl usage
244
        if (intToRenderType(config.getIntValue("opengl")) == RENDER_SOFTWARE)
245
        {
246
#endif  // defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
247
            if (!WindowManager::setFullScreen(fullscreen))
248
            {
249
                fullscreen = !fullscreen;
250
                if (!WindowManager::setFullScreen(fullscreen))
251
                {
252
                    std::stringstream errorMsg;
253
                    if (fullscreen)
254
                    {
255
                        // TRANSLATORS: video error message
256
                        errorMsg << _("Failed to switch to windowed mode "
257
                            "and restoration of old mode also "
258
                            "failed!") << std::endl;
259
                    }
260
                    else
261
                    {
262
                        // TRANSLATORS: video error message
263
                        errorMsg << _("Failed to switch to fullscreen mode"
264
                            " and restoration of old mode also "
265
                            "failed!") << std::endl;
266
                    }
267
                    logger->safeError(errorMsg.str());
268
                }
269
            }
270
#if defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
271
        }
272
        else
273
        {
274
            CREATEWIDGET(OkDialog,
275
                // TRANSLATORS: video settings warning
276
                _("Switching to Full Screen"),
277
                // TRANSLATORS: video settings warning
278
                _("Restart needed for changes to take effect."),
279
                // TRANSLATORS: ok dialog button
280
                _("OK"),
281
                DialogType::OK,
282
                Modal_true,
283
                ShowCenter_true,
284
                nullptr,
285
                260);
286
        }
287
#endif  // defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
288
289
        config.setValue("screen", fullscreen);
290
    }
291
292
    const int sel = mOpenGLDropDown->getSelected();
293
    RenderType mode = RENDER_SOFTWARE;
294
    if (sel >= 0 && CAST_U32(sel) < sizeof(indexToRender))
295
        mode = indexToRender[mOpenGLDropDown->getSelected()];
296
297
    // OpenGL change
298
    if (mode != mOpenGLEnabled)
299
    {
300
        config.setValue("opengl", CAST_S32(mode));
301
302
        // OpenGL can currently only be changed by restarting, notify user.
303
        CREATEWIDGET(OkDialog,
304
            // TRANSLATORS: video settings warning
305
            _("Changing to OpenGL"),
306
            // TRANSLATORS: video settings warning
307
            _("Applying change to OpenGL requires restart."),
308
            // TRANSLATORS: ok dialog button
309
            _("OK"),
310
            DialogType::OK,
311
            Modal_true,
312
            ShowCenter_true,
313
            nullptr,
314
            260);
315
    }
316
317
    mFps = mFpsCheckBox->isSelected() ?
318
        CAST_S32(mFpsSlider->getValue()) : 0;
319
320
    mAltFps = CAST_S32(mAltFpsSlider->getValue());
321
322
    mFpsSlider->setEnabled(mFps > 0);
323
324
    mAltFpsSlider->setEnabled(mAltFps > 0);
325
326
    // FPS change
327
    config.setValue("fpslimit", mFps);
328
    config.setValue("altfpslimit", mAltFps);
329
330
    // We sync old and new values at apply time
331
    mFullScreenEnabled = config.getBoolValue("screen");
332
    mCustomCursorEnabled = config.getBoolValue("customcursor");
333
334
    mOpenGLEnabled = intToRenderType(config.getIntValue("opengl"));
335
    mEnableResize = config.getBoolValue("enableresize");
336
    mNoFrame = config.getBoolValue("noframe");
337
#ifdef USE_SDL2
338
    mAllowHighDPI = config.getBoolValue("allowHighDPI");
339
#endif  // USE_SDL2
340
}
341
342
void Setup_Video::cancel()
343
{
344
    mFpsCheckBox->setSelected(mFps > 0);
345
    mFsCheckBox->setSelected(mFullScreenEnabled);
346
    mOpenGLDropDown->setSelected(renderToIndex[mOpenGLEnabled]);
347
    mCustomCursorCheckBox->setSelected(mCustomCursorEnabled);
348
    mFpsSlider->setEnabled(mFps > 0);
349
    mFpsSlider->setValue(mFps);
350
    mAltFpsSlider->setEnabled(mAltFps > 0);
351
    mAltFpsSlider->setValue(mAltFps);
352
    mFpsLabel->setCaption(mFpsCheckBox->isSelected()
353
    // TRANSLATORS: video settings label
354
                          ? toString(mFps) : _("None"));
355
    // TRANSLATORS: video settings label
356
    mAltFpsLabel->setCaption(_("Alt FPS limit: ") + toString(mAltFps));
357
    mEnableResizeCheckBox->setSelected(mEnableResize);
358
    mNoFrameCheckBox->setSelected(mNoFrame);
359
#ifdef USE_SDL2
360
    mAllowHighDPICheckBox->setSelected(mAllowHighDPI);
361
#endif  // USE_SDL2
362
363
    config.setValue("screen", mFullScreenEnabled);
364
365
    // Set back to the current video mode.
366
    std::string videoMode = toString(mainGraphics->mActualWidth).append("x")
367
        .append(toString(mainGraphics->mActualHeight));
368
    mModeList->setSelected(mModeListModel->getIndexOf(videoMode));
369
    config.setValue("screenwidth", mainGraphics->mActualWidth);
370
    config.setValue("screenheight", mainGraphics->mActualHeight);
371
372
    config.setValue("customcursor", mCustomCursorEnabled);
373
    config.setValue("opengl", CAST_S32(mOpenGLEnabled));
374
    config.setValue("enableresize", mEnableResize);
375
#ifdef USE_SDL2
376
    config.setValue("allowHighDPI", mAllowHighDPI);
377
#endif  // USE_SDL2
378
}
379
380
void Setup_Video::action(const ActionEvent &event)
381
{
382
    const std::string &id = event.getId();
383
384
    if (id == "videomode")
385
    {
386
        std::string mode = mModeListModel->getElementAt(
387
            mModeList->getSelected());
388
389
        if (mode == "custom")
390
        {
391
            if (mDialog != nullptr)
392
            {
393
                mode = mDialog->getText();
394
                mDialog = nullptr;
395
            }
396
            else
397
            {
398
                CREATEWIDGETV(mDialog, TextDialog,
399
                    // TRANSLATORS: resolution question dialog
400
                    _("Custom resolution (example: 1024x768)"),
401
                    // TRANSLATORS: resolution question dialog
402
                    _("Enter new resolution:                "),
403
                    nullptr,
404
                    false);
405
                mDialog->setActionEventId("videomode");
406
                mDialog->addActionListener(this);
407
                return;
408
            }
409
        }
410
        const int width = atoi(mode.substr(0, mode.find('x')).c_str());
411
        const int height = atoi(mode.substr(mode.find('x') + 1).c_str());
412
        if ((width == 0) || (height == 0))
413
            return;
414
415
        if (width != mainGraphics->mActualWidth
416
            || height != mainGraphics->mActualHeight)
417
        {
418
#if defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
419
            if (intToRenderType(config.getIntValue("opengl"))
420
                == RENDER_SOFTWARE)
421
            {
422
                WindowManager::doResizeVideo(width, height, false);
423
            }
424
            else
425
            {
426
                if (width < mainGraphics->mActualWidth
427
                    || height < mainGraphics->mActualHeight)
428
                {
429
                    CREATEWIDGET(OkDialog,
430
                        // TRANSLATORS: video settings warning
431
                        _("Screen Resolution Changed"),
432
                        // TRANSLATORS: video settings warning
433
                       _("Restart your client for the change to take effect.")
434
                        // TRANSLATORS: video settings warning
435
                       + std::string("\n") + _("Some windows may be moved to "
436
                        "fit the lowered resolution."),
437
                        // TRANSLATORS: ok dialog button
438
                        _("OK"),
439
                        DialogType::OK,
440
                        Modal_true,
441
                        ShowCenter_true,
442
                        nullptr,
443
                        260);
444
                }
445
                else
446
                {
447
                    CREATEWIDGET(OkDialog,
448
                        // TRANSLATORS: video settings warning
449
                        _("Screen Resolution Changed"),
450
                        // TRANSLATORS: video settings warning
451
                        _("Restart your client for the change"
452
                        " to take effect."),
453
                        // TRANSLATORS: ok dialog button
454
                        _("OK"),
455
                        DialogType::OK,
456
                        Modal_true,
457
                        ShowCenter_true,
458
                        nullptr,
459
                        260);
460
                }
461
            }
462
#else  // defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
463
464
            mainGraphics->setWindowSize(width, height);
465
            WindowManager::doResizeVideo(width, height, false);
466
#endif  // defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
467
        }
468
469
        config.setValue("oldscreen", config.getBoolValue("screen"));
470
        config.setValue("oldscreenwidth", mainGraphics->mActualWidth);
471
        config.setValue("oldscreenheight", mainGraphics->mActualHeight);
472
        config.setValue("screenwidth", width);
473
        config.setValue("screenheight", height);
474
    }
475
    if (id == "~videomode")
476
    {
477
        mDialog = nullptr;
478
    }
479
    else if (id == "customcursor")
480
    {
481
        config.setValue("customcursor", mCustomCursorCheckBox->isSelected());
482
    }
483
    else if (id == "fpslimitcheckbox" || id == "fpslimitslider")
484
    {
485
        int tempFps = CAST_S32(mFpsSlider->getValue());
486
        if (id == "fpslimitcheckbox" && !mFpsSlider->isEnabled())
487
            tempFps = 60;
488
        else
489
            tempFps = tempFps > 0 ? tempFps : 60;
490
        mFps = mFpsCheckBox->isSelected() ? tempFps : 0;
491
        // TRANSLATORS: video settings label
492
        const std::string text = mFps > 0 ? toString(mFps) : _("None");
493
494
        mFpsLabel->setCaption(text);
495
        mFpsSlider->setEnabled(mFps > 0);
496
        mFpsSlider->setValue(mFps);
497
    }
498
    else if (id == "altfpslimitslider")
499
    {
500
        int tempFps = CAST_S32(mAltFpsSlider->getValue());
501
        tempFps = tempFps > 0 ? tempFps : CAST_S32(
502
            mAltFpsSlider->getScaleStart());
503
        mAltFps = tempFps;
504
        // TRANSLATORS: video settings label
505
        const std::string text = mAltFps > 0 ? toString(mAltFps) : _("None");
506
507
        // TRANSLATORS: video settings label
508
        mAltFpsLabel->setCaption(_("Alt FPS limit: ") + text);
509
        mAltFpsSlider->setEnabled(mAltFps > 0);
510
        mAltFpsSlider->setValue(mAltFps);
511
    }
512
    else if (id == "enableresize")
513
    {
514
        config.setValue("enableresize", mEnableResizeCheckBox->isSelected());
515
    }
516
    else if (id == "noframe")
517
    {
518
        config.setValue("noframe", mNoFrameCheckBox->isSelected());
519
    }
520
#ifdef USE_SDL2
521
    else if (id == "allowHighDPI")
522
    {
523
        config.setValue("allowHighDPI", mAllowHighDPICheckBox->isSelected());
524
    }
525
#endif  // USE_SDL2
526
#if defined(USE_OPENGL) && !defined(ANDROID) && !defined(__APPLE__)
527
    else if (id == "detect")
528
    {
529
        TestMain *test = graphicsManager.startDetection();
530
        if (test != nullptr)
531
        {
532
            Configuration &conf = test->getConfig();
533
            const int val = conf.getValueInt("opengl", -1);
534
            if (val >= 0 && CAST_U32(val)
535
                < sizeof(renderToIndex) / sizeof(int))
536
            {
537
                mOpenGLDropDown->setSelected(renderToIndex[val]);
538
            }
539
            config.setValue("textureSize",
540
                conf.getValue("textureSize", "1024,1024,1024,1024,1024,1024"));
541
            config.setValue("testInfo", conf.getValue("testInfo", ""));
542
            delete test;
543
        }
544
    }
545
#endif  // defined(USE_OPENGL) && !defined(ANDROID) && !defined(__APPLE__)
546

3
}