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-2018 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 
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"
34 #include "gui/widgets/label.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 
59 
60 #include <sstream>
61 
62 #include "debug.h"
63 
64 Setup_Video::Setup_Video(const Widget2 *const widget) :
65  SetupTab(widget),
66  KeyListener(),
67  mFullScreenEnabled(config.getBoolValue("screen")),
68  mOpenGLEnabled(intToRenderType(config.getIntValue("opengl"))),
69  mFps(config.getIntValue("fpslimit")),
70  mAltFps(config.getIntValue("altfpslimit")),
71  mModeListModel(new ModeListModel),
72  mOpenGLListModel(new OpenGLListModel),
73  mModeList(CREATEWIDGETR(ListBox, widget, mModeListModel, "")),
74  // TRANSLATORS: video settings checkbox
75  mFsCheckBox(new CheckBox(this, _("Full screen"), mFullScreenEnabled,
76  nullptr, std::string())),
77  mOpenGLDropDown(new DropDown(widget, mOpenGLListModel,
78  false, Modal_false, nullptr, std::string())),
79  // TRANSLATORS: video settings checkbox
80  mFpsCheckBox(new CheckBox(this, _("FPS limit:"), false,
81  nullptr, std::string())),
82  mFpsSlider(new Slider(this, 2.0, 160.0, 1.0)),
83  mFpsLabel(new Label(this)),
84  mAltFpsSlider(new Slider(this, 2.0, 160.0, 1.0)),
85  // TRANSLATORS: video settings label
86  mAltFpsLabel(new Label(this, _("Alt FPS limit: "))),
87 #if !defined(ANDROID) && !defined(__APPLE__) && !defined(__native_client__)
88  // TRANSLATORS: video settings button
89  mDetectButton(new Button(this, _("Detect best mode"), "detect", this)),
90 #endif // !defined(ANDROID) && !defined(__APPLE__) &&
91  // !defined(__native_client__)
93  mCustomCursorEnabled(config.getBoolValue("customcursor")),
94  mEnableResize(config.getBoolValue("enableresize")),
95  mNoFrame(config.getBoolValue("noframe")),
96 #ifdef USE_SDL2
97  mAllowHighDPI(config.getBoolValue("allowHighDPI")),
98  // TRANSLATORS: video settings checkbox
99  mAllowHighDPICheckBox(new CheckBox(this, _("High DPI"), mAllowHighDPI,
100  nullptr, std::string())),
101 #endif // USE_SDL2
102  mCustomCursorCheckBox(new CheckBox(this,
103 #ifdef ANDROID
104  // TRANSLATORS: video settings checkbox
105  _("Show cursor"),
106 #else // ANDROID
107  // TRANSLATORS: video settings checkbox
108  _("Custom cursor"),
109 #endif // ANDROID
110  mCustomCursorEnabled,
111  nullptr, std::string())),
112  // TRANSLATORS: video settings checkbox
113  mEnableResizeCheckBox(new CheckBox(this, _("Enable resize"),
114  mEnableResize, nullptr, std::string())),
115  // TRANSLATORS: video settings checkbox
116  mNoFrameCheckBox(new CheckBox(this, _("No frame"), mNoFrame,
117  nullptr, std::string()))
118 {
119  // TRANSLATORS: video settings tab name
120  setName(_("Video"));
121 
122  ScrollArea *const scrollArea = new ScrollArea(this, mModeList,
123  Opaque_true, "setup_video_background.xml");
124  scrollArea->setWidth(150);
126 
128 
129  mModeList->setEnabled(true);
130 
131  // TRANSLATORS: video settings label
132  mFpsLabel->setCaption(mFps > 0 ? toString(mFps) : _("None"));
133  mFpsLabel->setWidth(60);
134  // TRANSLATORS: video settings label
135  mAltFpsLabel->setCaption(_("Alt FPS limit: ") + (mAltFps > 0 ?
136  // TRANSLATORS: video settings label value
137  toString(mAltFps) : _("None")));
138  mAltFpsLabel->setWidth(150);
139  mFpsSlider->setEnabled(mFps > 0);
144 
145  // Pre-select the current video mode.
146  const std::string videoMode = toString(
147  mainGraphics->mActualWidth).append("x").append(
150 
151  mModeList->setActionEventId("videomode");
152  mCustomCursorCheckBox->setActionEventId("customcursor");
153  mFpsCheckBox->setActionEventId("fpslimitcheckbox");
154  mFpsSlider->setActionEventId("fpslimitslider");
155  mAltFpsSlider->setActionEventId("altfpslimitslider");
157  mEnableResizeCheckBox->setActionEventId("enableresize");
159 #ifdef USE_SDL2
160  mAllowHighDPICheckBox->setActionEventId("allowHighDPI");
161  mAllowHighDPICheckBox->addActionListener(this);
162 #endif // USE_SDL2
163 
172 
173  // Do the layout
174  LayoutHelper h(this);
175  ContainerPlacer place = h.getPlacer(0, 0);
176 
177  place(0, 0, scrollArea, 1, 5).setPadding(2);
178  place(0, 5, mOpenGLDropDown, 1, 1);
179 
180  place(1, 0, mFsCheckBox, 2, 1);
181 
182  place(1, 1, mCustomCursorCheckBox, 3, 1);
183 
184  place(1, 2, mEnableResizeCheckBox, 2, 1);
185  place(1, 3, mNoFrameCheckBox, 2, 1);
186 #ifdef USE_SDL2
187  place(1, 4, mAllowHighDPICheckBox, 2, 1);
188 #endif // USE_SDL2
189 
190  place(0, 6, mFpsSlider, 1, 1);
191  place(1, 6, mFpsCheckBox, 1, 1).setPadding(3);
192  place(2, 6, mFpsLabel, 1, 1).setPadding(1);
193 
194  place(0, 7, mAltFpsSlider, 1, 1);
195  place(1, 7, mAltFpsLabel, 1, 1).setPadding(3);
196 
197 #if !defined(ANDROID) && !defined(__APPLE__) && !defined(__native_client__)
198  place(0, 8, mDetectButton, 1, 1);
199 #else // !defined(ANDROID) && !defined(__APPLE__) &&
200  // !defined(__native_client__)
203 #ifndef __native_client__
204  mFsCheckBox->setEnabled(false);
205 #endif // __native_client__
206 #endif // !defined(ANDROID) && !defined(__APPLE__) &&
207  // !defined(__native_client__)
208 
209  int width = 600;
210 
211  if (config.getIntValue("screenwidth") >= 730)
212  width += 100;
213 
214  setDimension(Rect(0, 0, width, 300));
215 }
216 
218 {
222  delete2(mDialog);
223 }
224 
226 {
227  // Full screen changes
228  bool fullscreen = mFsCheckBox->isSelected();
229  if (fullscreen != config.getBoolValue("screen"))
230  {
231  /* The OpenGL test is only necessary on Windows, since switching
232  * to/from full screen works fine on Linux. On Windows we'd have to
233  * reinitialize the OpenGL state and reload all textures.
234  *
235  * See http://libsdl.org/cgi/docwiki.cgi/SDL_SetVideoMode
236  */
237 
238 #if defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
239  // checks for opengl usage
241  {
242 #endif // defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
243  if (!WindowManager::setFullScreen(fullscreen))
244  {
245  fullscreen = !fullscreen;
246  if (!WindowManager::setFullScreen(fullscreen))
247  {
248  std::stringstream errorMsg;
249  if (fullscreen)
250  {
251  // TRANSLATORS: video error message
252  errorMsg << _("Failed to switch to windowed mode "
253  "and restoration of old mode also "
254  "failed!") << std::endl;
255  }
256  else
257  {
258  // TRANSLATORS: video error message
259  errorMsg << _("Failed to switch to fullscreen mode"
260  " and restoration of old mode also "
261  "failed!") << std::endl;
262  }
263  logger->safeError(errorMsg.str());
264  }
265  }
266 #if defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
267  }
268  else
269  {
271  // TRANSLATORS: video settings warning
272  _("Switching to Full Screen"),
273  // TRANSLATORS: video settings warning
274  _("Restart needed for changes to take effect."),
275  // TRANSLATORS: ok dialog button
276  _("OK"),
278  Modal_true,
280  nullptr,
281  260);
282  }
283 #endif // defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
284 
285  config.setValue("screen", fullscreen);
286  }
287 
288  const int sel = mOpenGLDropDown->getSelected();
290  if (sel >= 0 && CAST_U32(sel) < sizeof(indexToRender))
292 
293  // OpenGL change
294  if (mode != mOpenGLEnabled)
295  {
296  config.setValue("opengl", CAST_S32(mode));
297 
298  // OpenGL can currently only be changed by restarting, notify user.
300  // TRANSLATORS: video settings warning
301  _("Changing to OpenGL"),
302  // TRANSLATORS: video settings warning
303  _("Applying change to OpenGL requires restart."),
304  // TRANSLATORS: ok dialog button
305  _("OK"),
307  Modal_true,
309  nullptr,
310  260);
311  }
312 
314  CAST_S32(mFpsSlider->getValue()) : 0;
315 
317 
318  mFpsSlider->setEnabled(mFps > 0);
319 
320  mAltFpsSlider->setEnabled(mAltFps > 0);
321 
322  // FPS change
323  config.setValue("fpslimit", mFps);
324  config.setValue("altfpslimit", mAltFps);
325 
326  // We sync old and new values at apply time
328  mCustomCursorEnabled = config.getBoolValue("customcursor");
329 
331  mEnableResize = config.getBoolValue("enableresize");
332  mNoFrame = config.getBoolValue("noframe");
333 #ifdef USE_SDL2
334  mAllowHighDPI = config.getBoolValue("allowHighDPI");
335 #endif // USE_SDL2
336 }
337 
339 {
344  mFpsSlider->setEnabled(mFps > 0);
349  // TRANSLATORS: video settings label
350  ? toString(mFps) : _("None"));
351  // TRANSLATORS: video settings label
352  mAltFpsLabel->setCaption(_("Alt FPS limit: ") + toString(mAltFps));
355 #ifdef USE_SDL2
356  mAllowHighDPICheckBox->setSelected(mAllowHighDPI);
357 #endif // USE_SDL2
358 
360 
361  // Set back to the current video mode.
362  std::string videoMode = toString(mainGraphics->mActualWidth).append("x")
365  config.setValue("screenwidth", mainGraphics->mActualWidth);
366  config.setValue("screenheight", mainGraphics->mActualHeight);
367 
368  config.setValue("customcursor", mCustomCursorEnabled);
369  config.setValue("opengl", CAST_S32(mOpenGLEnabled));
370  config.setValue("enableresize", mEnableResize);
371 #ifdef USE_SDL2
372  config.setValue("allowHighDPI", mAllowHighDPI);
373 #endif // USE_SDL2
374 }
375 
377 {
378  const std::string &id = event.getId();
379 
380  if (id == "videomode")
381  {
382  std::string mode = mModeListModel->getElementAt(
384 
385  if (mode == "custom")
386  {
387  if (mDialog != nullptr)
388  {
389  mode = mDialog->getText();
390  mDialog = nullptr;
391  }
392  else
393  {
395  // TRANSLATORS: resolution question dialog
396  _("Custom resolution (example: 1024x768)"),
397  // TRANSLATORS: resolution question dialog
398  _("Enter new resolution: "),
399  nullptr,
400  false);
401  mDialog->setActionEventId("videomode");
402  mDialog->addActionListener(this);
403  return;
404  }
405  }
406  const int width = atoi(mode.substr(0, mode.find('x')).c_str());
407  const int height = atoi(mode.substr(mode.find('x') + 1).c_str());
408  if ((width == 0) || (height == 0))
409  return;
410 
411  if (width != mainGraphics->mActualWidth
412  || height != mainGraphics->mActualHeight)
413  {
414 #if defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
415  if (intToRenderType(config.getIntValue("opengl"))
416  == RENDER_SOFTWARE)
417  {
418  WindowManager::doResizeVideo(width, height, false);
419  }
420  else
421  {
422  if (width < mainGraphics->mActualWidth
423  || height < mainGraphics->mActualHeight)
424  {
426  // TRANSLATORS: video settings warning
427  _("Screen Resolution Changed"),
428  // TRANSLATORS: video settings warning
429  _("Restart your client for the change to take effect.")
430  // TRANSLATORS: video settings warning
431  + std::string("\n") + _("Some windows may be moved to "
432  "fit the lowered resolution."),
433  // TRANSLATORS: ok dialog button
434  _("OK"),
436  Modal_true,
438  nullptr,
439  260);
440  }
441  else
442  {
444  // TRANSLATORS: video settings warning
445  _("Screen Resolution Changed"),
446  // TRANSLATORS: video settings warning
447  _("Restart your client for the change"
448  " to take effect."),
449  // TRANSLATORS: ok dialog button
450  _("OK"),
452  Modal_true,
454  nullptr,
455  260);
456  }
457  }
458 #else // defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
459 
460  mainGraphics->setWindowSize(width, height);
461  WindowManager::doResizeVideo(width, height, false);
462 #endif // defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
463  }
464 
465  config.setValue("oldscreen", config.getBoolValue("screen"));
466  config.setValue("oldscreenwidth", mainGraphics->mActualWidth);
467  config.setValue("oldscreenheight", mainGraphics->mActualHeight);
468  config.setValue("screenwidth", width);
469  config.setValue("screenheight", height);
470  }
471  if (id == "~videomode")
472  {
473  mDialog = nullptr;
474  }
475  else if (id == "customcursor")
476  {
477  config.setValue("customcursor", mCustomCursorCheckBox->isSelected());
478  }
479  else if (id == "fpslimitcheckbox" || id == "fpslimitslider")
480  {
481  int tempFps = CAST_S32(mFpsSlider->getValue());
482  if (id == "fpslimitcheckbox" && !mFpsSlider->isEnabled())
483  tempFps = 60;
484  else
485  tempFps = tempFps > 0 ? tempFps : 60;
486  mFps = mFpsCheckBox->isSelected() ? tempFps : 0;
487  // TRANSLATORS: video settings label
488  const std::string text = mFps > 0 ? toString(mFps) : _("None");
489 
490  mFpsLabel->setCaption(text);
491  mFpsSlider->setEnabled(mFps > 0);
493  }
494  else if (id == "altfpslimitslider")
495  {
496  int tempFps = CAST_S32(mAltFpsSlider->getValue());
497  tempFps = tempFps > 0 ? tempFps : CAST_S32(
499  mAltFps = tempFps;
500  // TRANSLATORS: video settings label
501  const std::string text = mAltFps > 0 ? toString(mAltFps) : _("None");
502 
503  // TRANSLATORS: video settings label
504  mAltFpsLabel->setCaption(_("Alt FPS limit: ") + text);
505  mAltFpsSlider->setEnabled(mAltFps > 0);
506  mAltFpsSlider->setValue(mAltFps);
507  }
508  else if (id == "enableresize")
509  {
510  config.setValue("enableresize", mEnableResizeCheckBox->isSelected());
511  }
512  else if (id == "noframe")
513  {
515  }
516 #ifdef USE_SDL2
517  else if (id == "allowHighDPI")
518  {
519  config.setValue("allowHighDPI", mAllowHighDPICheckBox->isSelected());
520  }
521 #endif // USE_SDL2
522 #if defined(USE_OPENGL) && !defined(ANDROID) && !defined(__APPLE__)
523  else if (id == "detect")
524  {
526  if (test != nullptr)
527  {
528  Configuration &conf = test->getConfig();
529  const int val = conf.getValueInt("opengl", -1);
530  if (val >= 0 && CAST_U32(val)
531  < sizeof(renderToIndex) / sizeof(int))
532  {
534  }
535  config.setValue("textureSize",
536  conf.getValue("textureSize", "1024,1024,1024,1024,1024,1024"));
537  config.setValue("testInfo", conf.getValue("testInfo", ""));
538  delete test;
539  }
540  }
541 #endif // defined(USE_OPENGL) && !defined(ANDROID) && !defined(__APPLE__)
542 }
#define CAST_U32
Definition: cast.h:30
bool mEnableResize
Definition: setup_video.h:77
#define _(s)
Definition: gettext.h:34
void setSelected(const int selected)
Definition: listbox.cpp:398
void setWidth(const int width)
Definition: widget.cpp:132
void doResizeVideo(const int actualWidth, const int actualHeight, const bool always)
bool mCustomCursorEnabled
Definition: setup_video.h:76
Button * mDetectButton
Definition: setup_video.h:72
void addActionListener(ActionListener *const actionListener)
Definition: widget.cpp:251
Configuration & getConfig()
Definition: testmain.h:45
CheckBox * mFpsCheckBox
Definition: setup_video.h:66
NpcDialog * mDialog
Definition: npcrecv.cpp:41
Definition: rect.h:72
Definition: button.h:94
Configuration config
void setDimension(const Rect &dimension)
Definition: widget.cpp:168
void setWidth(int width)
if(!vert) return
Slider * mAltFpsSlider
Definition: setup_video.h:69
int getIntValue(const std::string &key) const
void setActionEventId(const std::string &actionEventId)
Definition: widget.h:595
#define CREATEWIDGETV(var, type,...)
Definition: createwidget.h:24
#define delete2(var)
Definition: delete2.h:24
TestMain * startDetection()
Logger * logger
Definition: logger.cpp:95
Label * mAltFpsLabel
Definition: setup_video.h:70
#define new
Definition: debug_new.h:147
TextDialog * mDialog
Definition: setup_video.h:75
bool getBoolValue(const std::string &key) const
const std::string & getText() const
Definition: textdialog.cpp:119
#define CAST_S32
Definition: cast.h:29
void setCaption(const std::string &caption)
Definition: label.cpp:261
CheckBox * mNoFrameCheckBox
Definition: setup_video.h:85
CheckBox * mEnableResizeCheckBox
Definition: setup_video.h:84
Definition: label.h:87
Setup_Video(const Widget2 *const widget)
Definition: setup_video.cpp:64
double getValue() const
Definition: slider.h:203
RenderType mOpenGLEnabled
Definition: setup_video.h:58
void safeError(const std::string &error_text) __attribute__((noreturn))
Definition: logger.cpp:378
CheckBox * mFsCheckBox
Definition: setup_video.h:64
bool mFullScreenEnabled
Definition: setup_video.h:57
OpenGLListModel * mOpenGLListModel
Definition: setup_video.h:62
const int renderToIndex[]
int getSelected() const
Definition: listbox.h:167
#define nullptr
Definition: localconsts.h:44
Graphics * mainGraphics
Definition: graphics.cpp:108
ModeListModel * mModeListModel
Definition: setup_video.h:61
const bool ShowCenter_true
Definition: showcenter.h:29
bool isEnabled() const
Definition: widget.cpp:374
RenderType intToRenderType(const int mode)
Definition: renderers.cpp:42
bool mNoFrame
Definition: setup_video.h:78
int mActualHeight
Definition: graphics.h:486
CheckBox * mCustomCursorCheckBox
Definition: setup_video.h:83
ContainerPlacer getPlacer(const int x, const int y)
void setEnabled(const bool enabled)
Definition: widget.h:351
void action(const ActionEvent &event)
std::string toString(T const &value)
converts any type to a string
Definition: catch.hpp:1774
std::string getValue(const std::string &key, const std::string &deflt) const
bool setFullScreen(const bool fs)
#define CREATEWIDGET(type,...)
Definition: createwidget.h:28
void setName(const std::string &name)
Definition: setuptab.h:67
void setValue(const double value)
Definition: slider.cpp:473
const bool Opaque_true
Definition: opaque.h:29
DropDown * mOpenGLDropDown
Definition: setup_video.h:65
ListBox * mModeList
Definition: setup_video.h:63
const RenderType indexToRender[]
double getScaleStart() const
Definition: slider.h:159
Label * mFpsLabel
Definition: setup_video.h:68
int getIndexOf(const std::string &widthXHeightMode)
Slider * mFpsSlider
Definition: setup_video.h:67
int mActualWidth
Definition: graphics.h:485
void setWindowSize(const int width, const int height)
Definition: graphics.cpp:670
#define CREATEWIDGETR(type,...)
Definition: createwidget.h:35
int getValueInt(const std::string &key, const int deflt) const
Definition: slider.h:85
void setSelected(const bool selected)
Definition: checkbox.h:155
bool isSelected() const
Definition: checkbox.h:146
void setSelected(int selected)
Definition: dropdown.cpp:514
GraphicsManager graphicsManager
void setValue(const std::string &key, const std::string &value)
int getSelected() const
Definition: dropdown.cpp:509
std::string getElementAt(int i)
Definition: modelistmodel.h:49
RenderType
Definition: rendertype.h:24
void setHorizontalScrollPolicy(const ScrollPolicy hPolicy)