GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/tabs/setup_video.cpp Lines: 86 201 42.8 %
Date: 2017-11-29 Branches: 121 490 24.7 %

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-2017  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
4
Setup_Video::Setup_Video(const Widget2 *const widget) :
65
    SetupTab(widget),
66
    KeyListener(),
67

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

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

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

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

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


16
    mModeList(CREATEWIDGETR(ListBox, widget, mModeListModel, "")),
74
    // TRANSLATORS: video settings checkbox
75

8
    mFsCheckBox(new CheckBox(this, _("Full screen"), mFullScreenEnabled)),
76

4
    mOpenGLDropDown(new DropDown(widget, mOpenGLListModel)),
77
    // TRANSLATORS: video settings checkbox
78

8
    mFpsCheckBox(new CheckBox(this, _("FPS limit:"))),
79

4
    mFpsSlider(new Slider(this, 2.0, 160.0, 1.0)),
80

4
    mFpsLabel(new Label(this)),
81

4
    mAltFpsSlider(new Slider(this, 2.0, 160.0, 1.0)),
82
    // TRANSLATORS: video settings label
83

8
    mAltFpsLabel(new Label(this, _("Alt FPS limit: "))),
84
#if !defined(ANDROID) && !defined(__APPLE__) && !defined(__native_client__)
85
    // TRANSLATORS: video settings button
86

8
    mDetectButton(new Button(this, _("Detect best mode"), "detect", this)),
87
#endif  // !defined(ANDROID) && !defined(__APPLE__) &&
88
        // !defined(__native_client__)
89
    mDialog(nullptr),
90

16
    mCustomCursorEnabled(config.getBoolValue("customcursor")),
91

16
    mEnableResize(config.getBoolValue("enableresize")),
92

16
    mNoFrame(config.getBoolValue("noframe")),
93
#ifdef USE_SDL2
94
    mAllowHighDPI(config.getBoolValue("allowHighDPI")),
95
    // TRANSLATORS: video settings checkbox
96
    mAllowHighDPICheckBox(new CheckBox(this, _("High DPI"), mAllowHighDPI)),
97
#endif  // USE_SDL2
98
    mCustomCursorCheckBox(new CheckBox(this,
99
#ifdef ANDROID
100
        // TRANSLATORS: video settings checkbox
101
        _("Show cursor"),
102
#else  // ANDROID
103
        // TRANSLATORS: video settings checkbox
104
4
        _("Custom cursor"),
105
#endif  // ANDROID
106

4
        mCustomCursorEnabled)),
107
    // TRANSLATORS: video settings checkbox
108
4
    mEnableResizeCheckBox(new CheckBox(this, _("Enable resize"),
109

4
                          mEnableResize)),
110
    // TRANSLATORS: video settings checkbox
111








264
    mNoFrameCheckBox(new CheckBox(this, _("No frame"), mNoFrame))
112
{
113
    // TRANSLATORS: video settings tab name
114
20
    setName(_("Video"));
115
116
4
    ScrollArea *const scrollArea = new ScrollArea(this, mModeList,
117

20
        Opaque_true, "setup_video_background.xml");
118
4
    scrollArea->setWidth(150);
119
4
    scrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
120
121
4
    mOpenGLDropDown->setSelected(renderToIndex[mOpenGLEnabled]);
122
123
8
    mModeList->setEnabled(true);
124
125
    // TRANSLATORS: video settings label
126


8
    mFpsLabel->setCaption(mFps > 0 ? toString(mFps) : _("None"));
127
4
    mFpsLabel->setWidth(60);
128
    // TRANSLATORS: video settings label
129


12
    mAltFpsLabel->setCaption(_("Alt FPS limit: ") + (mAltFps > 0 ?
130
        // TRANSLATORS: video settings label value
131
        toString(mAltFps) : _("None")));
132
4
    mAltFpsLabel->setWidth(150);
133
8
    mFpsSlider->setEnabled(mFps > 0);
134
4
    mFpsSlider->setValue(mFps);
135
8
    mAltFpsSlider->setEnabled(mAltFps > 0);
136
4
    mAltFpsSlider->setValue(mAltFps);
137
8
    mFpsCheckBox->setSelected(mFps > 0);
138
139
    // Pre-select the current video mode.
140
8
    const std::string videoMode = toString(
141
4
        mainGraphics->mActualWidth).append("x").append(
142
20
        toString(mainGraphics->mActualHeight));
143

4
    mModeList->setSelected(mModeListModel->getIndexOf(videoMode));
144
145
20
    mModeList->setActionEventId("videomode");
146
20
    mCustomCursorCheckBox->setActionEventId("customcursor");
147
20
    mFpsCheckBox->setActionEventId("fpslimitcheckbox");
148
20
    mFpsSlider->setActionEventId("fpslimitslider");
149
20
    mAltFpsSlider->setActionEventId("altfpslimitslider");
150
20
    mOpenGLDropDown->setActionEventId("opengl");
151
20
    mEnableResizeCheckBox->setActionEventId("enableresize");
152
20
    mNoFrameCheckBox->setActionEventId("noframe");
153
#ifdef USE_SDL2
154
    mAllowHighDPICheckBox->setActionEventId("allowHighDPI");
155
    mAllowHighDPICheckBox->addActionListener(this);
156
#endif  // USE_SDL2
157
158
4
    mModeList->addActionListener(this);
159
4
    mCustomCursorCheckBox->addActionListener(this);
160
4
    mFpsCheckBox->addActionListener(this);
161
4
    mFpsSlider->addActionListener(this);
162
4
    mAltFpsSlider->addActionListener(this);
163
4
    mOpenGLDropDown->addActionListener(this);
164
4
    mEnableResizeCheckBox->addActionListener(this);
165
4
    mNoFrameCheckBox->addActionListener(this);
166
167
    // Do the layout
168
8
    LayoutHelper h(this);
169
4
    ContainerPlacer place = h.getPlacer(0, 0);
170
171
8
    place(0, 0, scrollArea, 1, 5).setPadding(2);
172

4
    place(0, 5, mOpenGLDropDown, 1);
173
174
4
    place(1, 0, mFsCheckBox, 2);
175
176
4
    place(1, 1, mCustomCursorCheckBox, 3);
177
178
4
    place(1, 2, mEnableResizeCheckBox, 2);
179
4
    place(1, 3, mNoFrameCheckBox, 2);
180
#ifdef USE_SDL2
181
    place(1, 4, mAllowHighDPICheckBox, 2);
182
#endif  // USE_SDL2
183
184
4
    place(0, 6, mFpsSlider);
185
8
    place(1, 6, mFpsCheckBox).setPadding(3);
186
8
    place(2, 6, mFpsLabel).setPadding(1);
187
188
4
    place(0, 7, mAltFpsSlider);
189
8
    place(1, 7, mAltFpsLabel).setPadding(3);
190
191
#if !defined(ANDROID) && !defined(__APPLE__) && !defined(__native_client__)
192
4
    place(0, 8, mDetectButton);
193
#else  // !defined(ANDROID) && !defined(__APPLE__) &&
194
       // !defined(__native_client__)
195
    mNoFrameCheckBox->setEnabled(false);
196
    mEnableResizeCheckBox->setEnabled(false);
197
#ifndef __native_client__
198
    mFsCheckBox->setEnabled(false);
199
#endif  // __native_client__
200
#endif  // !defined(ANDROID) && !defined(__APPLE__) &&
201
        // !defined(__native_client__)
202
203
4
    int width = 600;
204
205

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

6
}