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",
90  BUTTON_SKIN, this)),
91 #endif // !defined(ANDROID) && !defined(__APPLE__) &&
92  // !defined(__native_client__)
94  mCustomCursorEnabled(config.getBoolValue("customcursor")),
95  mEnableResize(config.getBoolValue("enableresize")),
96  mNoFrame(config.getBoolValue("noframe")),
97 #ifdef USE_SDL2
98  mAllowHighDPI(config.getBoolValue("allowHighDPI")),
99  // TRANSLATORS: video settings checkbox
100  mAllowHighDPICheckBox(new CheckBox(this, _("High DPI"), mAllowHighDPI,
101  nullptr, std::string())),
102 #endif // USE_SDL2
103  mCustomCursorCheckBox(new CheckBox(this,
104 #ifdef ANDROID
105  // TRANSLATORS: video settings checkbox
106  _("Show cursor"),
107 #else // ANDROID
108  // TRANSLATORS: video settings checkbox
109  _("Custom cursor"),
110 #endif // ANDROID
111  mCustomCursorEnabled,
112  nullptr, std::string())),
113  // TRANSLATORS: video settings checkbox
114  mEnableResizeCheckBox(new CheckBox(this, _("Enable resize"),
115  mEnableResize, nullptr, std::string())),
116  // TRANSLATORS: video settings checkbox
117  mNoFrameCheckBox(new CheckBox(this, _("No frame"), mNoFrame,
118  nullptr, std::string()))
119 {
120  // TRANSLATORS: video settings tab name
121  setName(_("Video"));
122 
123  ScrollArea *const scrollArea = new ScrollArea(this, mModeList,
124  Opaque_true, "setup_video_background.xml");
125  scrollArea->setWidth(150);
127 
129 
130  mModeList->setEnabled(true);
131 
132  // TRANSLATORS: video settings label
133  mFpsLabel->setCaption(mFps > 0 ? toString(mFps) : _("None"));
134  mFpsLabel->setWidth(60);
135  // TRANSLATORS: video settings label
136  mAltFpsLabel->setCaption(_("Alt FPS limit: ") + (mAltFps > 0 ?
137  // TRANSLATORS: video settings label value
138  toString(mAltFps) : _("None")));
139  mAltFpsLabel->setWidth(150);
140  mFpsSlider->setEnabled(mFps > 0);
145 
146  // Pre-select the current video mode.
147  const std::string videoMode = toString(
148  mainGraphics->mActualWidth).append("x").append(
151 
152  mModeList->setActionEventId("videomode");
153  mCustomCursorCheckBox->setActionEventId("customcursor");
154  mFpsCheckBox->setActionEventId("fpslimitcheckbox");
155  mFpsSlider->setActionEventId("fpslimitslider");
156  mAltFpsSlider->setActionEventId("altfpslimitslider");
158  mEnableResizeCheckBox->setActionEventId("enableresize");
160 #ifdef USE_SDL2
161  mAllowHighDPICheckBox->setActionEventId("allowHighDPI");
162  mAllowHighDPICheckBox->addActionListener(this);
163 #endif // USE_SDL2
164 
173 
174  // Do the layout
175  LayoutHelper h(this);
176  ContainerPlacer place = h.getPlacer(0, 0);
177 
178  place(0, 0, scrollArea, 1, 5).setPadding(2);
179  place(0, 5, mOpenGLDropDown, 1, 1);
180 
181  place(1, 0, mFsCheckBox, 2, 1);
182 
183  place(1, 1, mCustomCursorCheckBox, 3, 1);
184 
185  place(1, 2, mEnableResizeCheckBox, 2, 1);
186  place(1, 3, mNoFrameCheckBox, 2, 1);
187 #ifdef USE_SDL2
188  place(1, 4, mAllowHighDPICheckBox, 2, 1);
189 #endif // USE_SDL2
190 
191  place(0, 6, mFpsSlider, 1, 1);
192  place(1, 6, mFpsCheckBox, 1, 1).setPadding(3);
193  place(2, 6, mFpsLabel, 1, 1).setPadding(1);
194 
195  place(0, 7, mAltFpsSlider, 1, 1);
196  place(1, 7, mAltFpsLabel, 1, 1).setPadding(3);
197 
198 #if !defined(ANDROID) && !defined(__APPLE__) && !defined(__native_client__)
199  place(0, 8, mDetectButton, 1, 1);
200 #else // !defined(ANDROID) && !defined(__APPLE__) &&
201  // !defined(__native_client__)
204 #ifndef __native_client__
205  mFsCheckBox->setEnabled(false);
206 #endif // __native_client__
207 #endif // !defined(ANDROID) && !defined(__APPLE__) &&
208  // !defined(__native_client__)
209 
210  int width = 600;
211 
212  if (config.getIntValue("screenwidth") >= 730)
213  width += 100;
214 
215  setDimension(Rect(0, 0, width, 300));
216 }
217 
219 {
223  delete2(mDialog);
224 }
225 
227 {
228  // Full screen changes
229  bool fullscreen = mFsCheckBox->isSelected();
230  if (fullscreen != config.getBoolValue("screen"))
231  {
232  /* The OpenGL test is only necessary on Windows, since switching
233  * to/from full screen works fine on Linux. On Windows we'd have to
234  * reinitialize the OpenGL state and reload all textures.
235  *
236  * See http://libsdl.org/cgi/docwiki.cgi/SDL_SetVideoMode
237  */
238 
239 #if defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
240  // checks for opengl usage
242  {
243 #endif // defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
244  if (!WindowManager::setFullScreen(fullscreen))
245  {
246  fullscreen = !fullscreen;
247  if (!WindowManager::setFullScreen(fullscreen))
248  {
249  std::stringstream errorMsg;
250  if (fullscreen)
251  {
252  // TRANSLATORS: video error message
253  errorMsg << _("Failed to switch to windowed mode "
254  "and restoration of old mode also "
255  "failed!") << std::endl;
256  }
257  else
258  {
259  // TRANSLATORS: video error message
260  errorMsg << _("Failed to switch to fullscreen mode"
261  " and restoration of old mode also "
262  "failed!") << std::endl;
263  }
264  logger->safeError(errorMsg.str());
265  }
266  }
267 #if defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
268  }
269  else
270  {
272  // TRANSLATORS: video settings warning
273  _("Switching to Full Screen"),
274  // TRANSLATORS: video settings warning
275  _("Restart needed for changes to take effect."),
276  // TRANSLATORS: ok dialog button
277  _("OK"),
279  Modal_true,
281  nullptr,
282  260);
283  }
284 #endif // defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
285 
286  config.setValue("screen", fullscreen);
287  }
288 
289  const int sel = mOpenGLDropDown->getSelected();
291  if (sel >= 0 && CAST_U32(sel) < sizeof(indexToRender))
293 
294  // OpenGL change
295  if (mode != mOpenGLEnabled)
296  {
297  config.setValue("opengl", CAST_S32(mode));
298 
299  // OpenGL can currently only be changed by restarting, notify user.
301  // TRANSLATORS: video settings warning
302  _("Changing to OpenGL"),
303  // TRANSLATORS: video settings warning
304  _("Applying change to OpenGL requires restart."),
305  // TRANSLATORS: ok dialog button
306  _("OK"),
308  Modal_true,
310  nullptr,
311  260);
312  }
313 
315  CAST_S32(mFpsSlider->getValue()) : 0;
316 
318 
319  mFpsSlider->setEnabled(mFps > 0);
320 
321  mAltFpsSlider->setEnabled(mAltFps > 0);
322 
323  // FPS change
324  config.setValue("fpslimit", mFps);
325  config.setValue("altfpslimit", mAltFps);
326 
327  // We sync old and new values at apply time
329  mCustomCursorEnabled = config.getBoolValue("customcursor");
330 
332  mEnableResize = config.getBoolValue("enableresize");
333  mNoFrame = config.getBoolValue("noframe");
334 #ifdef USE_SDL2
335  mAllowHighDPI = config.getBoolValue("allowHighDPI");
336 #endif // USE_SDL2
337 }
338 
340 {
345  mFpsSlider->setEnabled(mFps > 0);
350  // TRANSLATORS: video settings label
351  ? toString(mFps) : _("None"));
352  // TRANSLATORS: video settings label
353  mAltFpsLabel->setCaption(_("Alt FPS limit: ") + toString(mAltFps));
356 #ifdef USE_SDL2
357  mAllowHighDPICheckBox->setSelected(mAllowHighDPI);
358 #endif // USE_SDL2
359 
361 
362  // Set back to the current video mode.
363  std::string videoMode = toString(mainGraphics->mActualWidth).append("x")
366  config.setValue("screenwidth", mainGraphics->mActualWidth);
367  config.setValue("screenheight", mainGraphics->mActualHeight);
368 
369  config.setValue("customcursor", mCustomCursorEnabled);
370  config.setValue("opengl", CAST_S32(mOpenGLEnabled));
371  config.setValue("enableresize", mEnableResize);
372 #ifdef USE_SDL2
373  config.setValue("allowHighDPI", mAllowHighDPI);
374 #endif // USE_SDL2
375 }
376 
378 {
379  const std::string &id = event.getId();
380 
381  if (id == "videomode")
382  {
383  std::string mode = mModeListModel->getElementAt(
385 
386  if (mode == "custom")
387  {
388  if (mDialog != nullptr)
389  {
390  mode = mDialog->getText();
391  mDialog = nullptr;
392  }
393  else
394  {
396  // TRANSLATORS: resolution question dialog
397  _("Custom resolution (example: 1024x768)"),
398  // TRANSLATORS: resolution question dialog
399  _("Enter new resolution: "),
400  nullptr,
401  false);
402  mDialog->setActionEventId("videomode");
403  mDialog->addActionListener(this);
404  return;
405  }
406  }
407  const int width = atoi(mode.substr(0, mode.find('x')).c_str());
408  const int height = atoi(mode.substr(mode.find('x') + 1).c_str());
409  if ((width == 0) || (height == 0))
410  return;
411 
412  if (width != mainGraphics->mActualWidth
413  || height != mainGraphics->mActualHeight)
414  {
415 #if defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
416  if (intToRenderType(config.getIntValue("opengl"))
417  == RENDER_SOFTWARE)
418  {
419  WindowManager::doResizeVideo(width, height, false);
420  }
421  else
422  {
423  if (width < mainGraphics->mActualWidth
424  || height < mainGraphics->mActualHeight)
425  {
427  // TRANSLATORS: video settings warning
428  _("Screen Resolution Changed"),
429  // TRANSLATORS: video settings warning
430  _("Restart your client for the change to take effect.")
431  // TRANSLATORS: video settings warning
432  + std::string("\n") + _("Some windows may be moved to "
433  "fit the lowered resolution."),
434  // TRANSLATORS: ok dialog button
435  _("OK"),
437  Modal_true,
439  nullptr,
440  260);
441  }
442  else
443  {
445  // TRANSLATORS: video settings warning
446  _("Screen Resolution Changed"),
447  // TRANSLATORS: video settings warning
448  _("Restart your client for the change"
449  " to take effect."),
450  // TRANSLATORS: ok dialog button
451  _("OK"),
453  Modal_true,
455  nullptr,
456  260);
457  }
458  }
459 #else // defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
460 
461  mainGraphics->setWindowSize(width, height);
462  WindowManager::doResizeVideo(width, height, false);
463 #endif // defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
464  }
465 
466  config.setValue("oldscreen", config.getBoolValue("screen"));
467  config.setValue("oldscreenwidth", mainGraphics->mActualWidth);
468  config.setValue("oldscreenheight", mainGraphics->mActualHeight);
469  config.setValue("screenwidth", width);
470  config.setValue("screenheight", height);
471  }
472  if (id == "~videomode")
473  {
474  mDialog = nullptr;
475  }
476  else if (id == "customcursor")
477  {
478  config.setValue("customcursor", mCustomCursorCheckBox->isSelected());
479  }
480  else if (id == "fpslimitcheckbox" || id == "fpslimitslider")
481  {
482  int tempFps = CAST_S32(mFpsSlider->getValue());
483  if (id == "fpslimitcheckbox" && !mFpsSlider->isEnabled())
484  tempFps = 60;
485  else
486  tempFps = tempFps > 0 ? tempFps : 60;
487  mFps = mFpsCheckBox->isSelected() ? tempFps : 0;
488  // TRANSLATORS: video settings label
489  const std::string text = mFps > 0 ? toString(mFps) : _("None");
490 
491  mFpsLabel->setCaption(text);
492  mFpsSlider->setEnabled(mFps > 0);
494  }
495  else if (id == "altfpslimitslider")
496  {
497  int tempFps = CAST_S32(mAltFpsSlider->getValue());
498  tempFps = tempFps > 0 ? tempFps : CAST_S32(
500  mAltFps = tempFps;
501  // TRANSLATORS: video settings label
502  const std::string text = mAltFps > 0 ? toString(mAltFps) : _("None");
503 
504  // TRANSLATORS: video settings label
505  mAltFpsLabel->setCaption(_("Alt FPS limit: ") + text);
506  mAltFpsSlider->setEnabled(mAltFps > 0);
507  mAltFpsSlider->setValue(mAltFps);
508  }
509  else if (id == "enableresize")
510  {
511  config.setValue("enableresize", mEnableResizeCheckBox->isSelected());
512  }
513  else if (id == "noframe")
514  {
516  }
517 #ifdef USE_SDL2
518  else if (id == "allowHighDPI")
519  {
520  config.setValue("allowHighDPI", mAllowHighDPICheckBox->isSelected());
521  }
522 #endif // USE_SDL2
523 #if defined(USE_OPENGL) && !defined(ANDROID) && !defined(__APPLE__)
524  else if (id == "detect")
525  {
527  if (test != nullptr)
528  {
529  Configuration &conf = test->getConfig();
530  const int val = conf.getValueInt("opengl", -1);
531  if (val >= 0 && CAST_U32(val)
532  < sizeof(renderToIndex) / sizeof(int))
533  {
535  }
536  config.setValue("textureSize",
537  conf.getValue("textureSize", "1024,1024,1024,1024,1024,1024"));
538  config.setValue("testInfo", conf.getValue("testInfo", ""));
539  delete test;
540  }
541  }
542 #endif // defined(USE_OPENGL) && !defined(ANDROID) && !defined(__APPLE__)
543 }
#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:96
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:88
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:123
#define CAST_S32
Definition: cast.h:29
const std::string BUTTON_SKIN
Definition: button.h:88
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:430
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)