GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/tabs/setup_video.cpp Lines: 99 222 44.6 %
Date: 2020-06-04 Branches: 123 458 26.9 %

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

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

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

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

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

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


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

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

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

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

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

2
    mFpsLabel(new Label(this)),
84

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

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

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

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

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

8
    mNoFrame(config.getBoolValue("noframe")),
98
#ifdef USE_SDL2
99

8
    mAllowHighDPI(config.getBoolValue("allowHighDPI")),
100
    // TRANSLATORS: video settings checkbox
101
4
    mAllowHighDPICheckBox(new CheckBox(this, _("High DPI"), mAllowHighDPI,
102

6
        nullptr, std::string())),
103
#endif  // USE_SDL2
104
    mCustomCursorCheckBox(new CheckBox(this,
105
#ifdef ANDROID
106
        // TRANSLATORS: video settings checkbox
107
        _("Show cursor"),
108
#else  // ANDROID
109
        // TRANSLATORS: video settings checkbox
110
2
        _("Custom cursor"),
111
#endif  // ANDROID
112
2
        mCustomCursorEnabled,
113

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

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





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

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


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


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

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

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

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

3
}