ManaPlus
setup_video.cpp
Go to the documentation of this file.
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 
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"
35 #include "gui/widgets/label.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 
60 
61 #include <sstream>
62 
63 #include "debug.h"
64 
65 Setup_Video::Setup_Video(const Widget2 *const widget) :
66  SetupTab(widget),
67  KeyListener(),
68  mFullScreenEnabled(config.getBoolValue("screen")),
69  mOpenGLEnabled(intToRenderType(config.getIntValue("opengl"))),
70  mFps(config.getIntValue("fpslimit")),
71  mAltFps(config.getIntValue("altfpslimit")),
72  mModeListModel(new ModeListModel),
73  mOpenGLListModel(new OpenGLListModel),
74  mModeList(CREATEWIDGETR(ListBox, widget, mModeListModel, "")),
75  // TRANSLATORS: video settings checkbox
76  mFsCheckBox(new CheckBox(this, _("Full screen"), mFullScreenEnabled,
77  nullptr, std::string())),
78  mOpenGLDropDown(new DropDown(widget, mOpenGLListModel,
79  false, Modal_false, nullptr, std::string())),
80  // TRANSLATORS: video settings checkbox
81  mFpsCheckBox(new CheckBox(this, _("FPS limit:"), false,
82  nullptr, std::string())),
83  mFpsSlider(new Slider(this, 2.0, 160.0, 1.0)),
84  mFpsLabel(new Label(this)),
85  mAltFpsSlider(new Slider(this, 2.0, 160.0, 1.0)),
86  // TRANSLATORS: video settings label
87  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  mDetectButton(new Button(this, _("Detect best mode"), "detect",
92  BUTTON_SKIN, this)),
93 #endif // !defined(__native_client__) && !defined(__SWITCH__)
94 #endif // !defined(ANDROID) && !defined(__APPLE__) &&
96  mCustomCursorEnabled(config.getBoolValue("customcursor")),
97  mEnableResize(config.getBoolValue("enableresize")),
98  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  _("Custom cursor"),
112 #endif // ANDROID
113  mCustomCursorEnabled,
114  nullptr, std::string())),
115  // TRANSLATORS: video settings checkbox
116  mEnableResizeCheckBox(new CheckBox(this, _("Enable resize"),
117  mEnableResize, nullptr, std::string())),
118  // TRANSLATORS: video settings checkbox
119  mNoFrameCheckBox(new CheckBox(this, _("No frame"), mNoFrame,
120  nullptr, std::string()))
121 {
122  // TRANSLATORS: video settings tab name
123  setName(_("Video"));
124 
125  ScrollArea *const scrollArea = new ScrollArea(this, mModeList,
126  Opaque_true, "setup_video_background.xml");
127  scrollArea->setWidth(150);
129 
131 
132  mModeList->setEnabled(true);
133 
134  // TRANSLATORS: video settings label
135  mFpsLabel->setCaption(mFps > 0 ? toString(mFps) : _("None"));
136  mFpsLabel->setWidth(60);
137  // TRANSLATORS: video settings label
138  mAltFpsLabel->setCaption(_("Alt FPS limit: ") + (mAltFps > 0 ?
139  // TRANSLATORS: video settings label value
140  toString(mAltFps) : _("None")));
141  mAltFpsLabel->setWidth(150);
142  mFpsSlider->setEnabled(mFps > 0);
147 
148  // Pre-select the current video mode.
149  const std::string videoMode = toString(
150  mainGraphics->mActualWidth).append("x").append(
153 
154  mModeList->setActionEventId("videomode");
155  mCustomCursorCheckBox->setActionEventId("customcursor");
156  mFpsCheckBox->setActionEventId("fpslimitcheckbox");
157  mFpsSlider->setActionEventId("fpslimitslider");
158  mAltFpsSlider->setActionEventId("altfpslimitslider");
160  mEnableResizeCheckBox->setActionEventId("enableresize");
162 #ifdef USE_SDL2
163  mAllowHighDPICheckBox->setActionEventId("allowHighDPI");
164  mAllowHighDPICheckBox->addActionListener(this);
165 #endif // USE_SDL2
166 
175 
176  // Do the layout
177  LayoutHelper h(this);
178  ContainerPlacer place = h.getPlacer(0, 0);
179 
180  place(0, 0, scrollArea, 1, 5).setPadding(2);
181  place(0, 5, mOpenGLDropDown, 1, 1);
182 
183  place(1, 0, mFsCheckBox, 2, 1);
184 
185  place(1, 1, mCustomCursorCheckBox, 3, 1);
186 
187  place(1, 2, mEnableResizeCheckBox, 2, 1);
188  place(1, 3, mNoFrameCheckBox, 2, 1);
189 #ifdef USE_SDL2
190  place(1, 4, mAllowHighDPICheckBox, 2, 1);
191 #endif // USE_SDL2
192 
193  place(0, 6, mFpsSlider, 1, 1);
194  place(1, 6, mFpsCheckBox, 1, 1).setPadding(3);
195  place(2, 6, mFpsLabel, 1, 1).setPadding(1);
196 
197  place(0, 7, mAltFpsSlider, 1, 1);
198  place(1, 7, mAltFpsLabel, 1, 1).setPadding(3);
199 
200 #if !defined(ANDROID) && !defined(__APPLE__) && \
201  !defined(__native_client__) && !defined(__SWITCH__)
202  place(0, 8, mDetectButton, 1, 1);
203 #else // !defined(ANDROID) && !defined(__APPLE__) &&
204  // !defined(__native_client__)
207 #ifndef __native_client__
208  mFsCheckBox->setEnabled(false);
209 #endif // __native_client__
210 #endif // !defined(ANDROID) && !defined(__APPLE__) &&
211  // !defined(__native_client__)
212 
213  int width = 600;
214 
215  if (config.getIntValue("screenwidth") >= 730)
216  width += 100;
217 
218  setDimension(Rect(0, 0, width, 300));
219 }
220 
222 {
227 }
228 
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
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  {
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"),
282  Modal_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();
294  if (sel >= 0 && CAST_U32(sel) < sizeof(indexToRender))
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.
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"),
311  Modal_true,
313  nullptr,
314  260);
315  }
316 
318  CAST_S32(mFpsSlider->getValue()) : 0;
319 
321 
322  mFpsSlider->setEnabled(mFps > 0);
323 
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
332  mCustomCursorEnabled = config.getBoolValue("customcursor");
333 
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 
343 {
348  mFpsSlider->setEnabled(mFps > 0);
353  // TRANSLATORS: video settings label
354  ? toString(mFps) : _("None"));
355  // TRANSLATORS: video settings label
356  mAltFpsLabel->setCaption(_("Alt FPS limit: ") + toString(mAltFps));
359 #ifdef USE_SDL2
360  mAllowHighDPICheckBox->setSelected(mAllowHighDPI);
361 #endif // USE_SDL2
362 
364 
365  // Set back to the current video mode.
366  std::string videoMode = toString(mainGraphics->mActualWidth).append("x")
369  config.setValue("screenwidth", mainGraphics->mActualWidth);
370  config.setValue("screenheight", mainGraphics->mActualHeight);
371 
372  config.setValue("customcursor", mCustomCursorEnabled);
374  config.setValue("enableresize", mEnableResize);
375 #ifdef USE_SDL2
376  config.setValue("allowHighDPI", mAllowHighDPI);
377 #endif // USE_SDL2
378 }
379 
381 {
382  const std::string &id = event.getId();
383 
384  if (id == "videomode")
385  {
386  std::string mode = mModeListModel->getElementAt(
388 
389  if (mode == "custom")
390  {
391  if (mDialog != nullptr)
392  {
393  mode = mDialog->getText();
394  mDialog = nullptr;
395  }
396  else
397  {
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  {
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"),
440  Modal_true,
442  nullptr,
443  260);
444  }
445  else
446  {
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"),
456  Modal_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);
497  }
498  else if (id == "altfpslimitslider")
499  {
500  int tempFps = CAST_S32(mAltFpsSlider->getValue());
501  tempFps = tempFps > 0 ? tempFps : CAST_S32(
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);
511  }
512  else if (id == "enableresize")
513  {
514  config.setValue("enableresize", mEnableResizeCheckBox->isSelected());
515  }
516  else if (id == "noframe")
517  {
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  {
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  {
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 }
const std::string BUTTON_SKIN
Definition: button.h:89
#define CAST_S32
Definition: cast.h:30
#define CAST_U32
Definition: cast.h:31
Definition: button.h:102
void setSelected(const bool selected)
Definition: checkbox.h:156
bool isSelected() const
Definition: checkbox.h:147
int getValueInt(const std::string &key, const int deflt) const
std::string getValue(const std::string &key, const std::string &deflt) const
bool getBoolValue(const std::string &key) const
void setValue(const std::string &key, const std::string &value)
int getIntValue(const std::string &key) const
int getSelected() const
Definition: dropdown.cpp:509
void setSelected(int selected)
Definition: dropdown.cpp:514
TestMain * startDetection()
int mActualHeight
Definition: graphics.h:487
void setWindowSize(const int width, const int height)
Definition: graphics.cpp:671
int mActualWidth
Definition: graphics.h:486
Definition: label.h:91
void setCaption(const std::string &caption)
Definition: label.cpp:264
ContainerPlacer getPlacer(const int x, const int y)
int getSelected() const
Definition: listbox.h:168
void setSelected(const int selected)
Definition: listbox.cpp:399
void safeError(const std::string &error_text) __attribute__((noreturn))
Definition: logger.cpp:435
int getIndexOf(const std::string &widthXHeightMode)
std::string getElementAt(int i)
Definition: modelistmodel.h:50
Definition: rect.h:74
void setHorizontalScrollPolicy(const ScrollPolicy hPolicy)
void setWidth(int width)
void setName(const std::string &name)
Definition: setuptab.h:68
CheckBox * mFpsCheckBox
Definition: setup_video.h:67
void action(const ActionEvent &event)
RenderType mOpenGLEnabled
Definition: setup_video.h:59
ListBox * mModeList
Definition: setup_video.h:64
Setup_Video(const Widget2 *const widget)
Definition: setup_video.cpp:65
ModeListModel * mModeListModel
Definition: setup_video.h:62
bool mNoFrame
Definition: setup_video.h:79
CheckBox * mCustomCursorCheckBox
Definition: setup_video.h:84
Slider * mFpsSlider
Definition: setup_video.h:68
CheckBox * mEnableResizeCheckBox
Definition: setup_video.h:85
Label * mFpsLabel
Definition: setup_video.h:69
bool mFullScreenEnabled
Definition: setup_video.h:58
CheckBox * mNoFrameCheckBox
Definition: setup_video.h:86
Button * mDetectButton
Definition: setup_video.h:73
CheckBox * mFsCheckBox
Definition: setup_video.h:65
OpenGLListModel * mOpenGLListModel
Definition: setup_video.h:63
Label * mAltFpsLabel
Definition: setup_video.h:71
bool mEnableResize
Definition: setup_video.h:78
TextDialog * mDialog
Definition: setup_video.h:76
DropDown * mOpenGLDropDown
Definition: setup_video.h:66
bool mCustomCursorEnabled
Definition: setup_video.h:77
Slider * mAltFpsSlider
Definition: setup_video.h:70
Definition: slider.h:89
double getValue() const
Definition: slider.h:204
void setValue(const double value)
Definition: slider.cpp:474
double getScaleStart() const
Definition: slider.h:160
Configuration & getConfig()
Definition: testmain.h:46
const std::string & getText() const
Definition: textdialog.cpp:124
void setWidth(const int width)
Definition: widget.cpp:133
void setEnabled(const bool enabled)
Definition: widget.h:352
void setActionEventId(const std::string &actionEventId)
Definition: widget.h:596
void setDimension(const Rect &dimension)
Definition: widget.cpp:169
bool isEnabled() const
Definition: widget.cpp:375
void addActionListener(ActionListener *const actionListener)
Definition: widget.cpp:252
Configuration config
#define CREATEWIDGET(type,...)
Definition: createwidget.h:29
#define CREATEWIDGETR(type,...)
Definition: createwidget.h:36
#define CREATEWIDGETV(var, type,...)
Definition: createwidget.h:25
#define new
Definition: debug_new.h:147
#define delete2(var)
Definition: delete2.h:25
#define _(s)
Definition: gettext.h:35
Graphics * mainGraphics
Definition: graphics.cpp:109
if(!vert) return
GraphicsManager graphicsManager
#define nullptr
Definition: localconsts.h:45
Logger * logger
Definition: logger.cpp:89
const bool Modal_false
Definition: modal.h:30
const bool Modal_true
Definition: modal.h:30
std::string toString(T const &value)
converts any type to a string
Definition: catch.hpp:1774
NpcDialog * mDialog
Definition: npcrecv.cpp:42
bool setFullScreen(const bool fs)
void doResizeVideo(const int actualWidth, const int actualHeight, const bool always)
const bool Opaque_true
Definition: opaque.h:30
RenderType intToRenderType(const int mode)
Definition: renderers.cpp:43
const int renderToIndex[]
const RenderType indexToRender[]
RenderType
Definition: rendertype.h:26
@ RENDER_SOFTWARE
Definition: rendertype.h:27
const bool ShowCenter_true
Definition: showcenter.h:30