MythTV  master
mythdisplay.cpp
Go to the documentation of this file.
1 //Qt
2 #include <QTimer>
3 #include <QThread>
4 #include <QApplication>
5 #include <QElapsedTimer>
6 #include <QWindow>
7 
8 // MythTV
9 #include "mythlogging.h"
10 #include "compat.h"
11 #include "mythcorecontext.h"
12 #include "mythuihelper.h"
13 #include "mythdisplay.h"
14 #include "mythegl.h"
15 #include "mythmainwindow.h"
16 
17 #ifdef USING_DBUS
19 #endif
20 #ifdef Q_OS_ANDROID
22 #endif
23 #if defined(Q_OS_MAC)
25 #endif
26 #ifdef USING_X11
28 #endif
29 #ifdef USING_DRM
31 #endif
32 #if defined(Q_OS_WIN)
34 #endif
35 #ifdef USING_MMAL
37 #endif
38 
39 #define LOC QString("Display: ")
40 
76 {
77  MythDisplay* result = nullptr;
78 #ifdef USING_X11
80  result = new MythDisplayX11();
81 #endif
82 #ifdef USING_DBUS
83  /* disabled until testing can be completed (add docs on subclass choice when done)
84  if (!result)
85  result = MythDisplayMutter::Create();
86  */
87 #endif
88 #ifdef USING_MMAL
89  if (!result)
90  result = new MythDisplayRPI();
91 #endif
92 #ifdef USING_DRM
93  // this will only work by validating the screen's serial number
94  if (!result)
95  result = new MythDisplayDRM();
96 #endif
97 #if defined(Q_OS_MAC)
98  if (!result)
99  result = new MythDisplayOSX();
100 #endif
101 #ifdef Q_OS_ANDROID
102  if (!result)
103  result = new MythDisplayAndroid();
104 #endif
105 #if defined(Q_OS_WIN)
106  if (!result)
107  result = new MythDisplayWindows();
108 #endif
109  if (!result)
110  result = new MythDisplay();
111  return result;
112 }
113 
115 {
116  QStringList result;
117  bool spanall = false;
118  int screencount = MythDisplay::GetScreenCount();
119  if (MythDisplay::SpanAllScreens() && screencount > 1)
120  {
121  spanall = true;
122  result.append(tr("Spanning %1 screens").arg(screencount));
123  result.append(tr("Total bounds") + QString("\t: %1x%2")
124  .arg(GetScreenBounds().width()).arg(GetScreenBounds().height()));
125  result.append("");
126  }
127 
128  QScreen *current = GetCurrentScreen();
129  QList<QScreen*> screens = QGuiApplication::screens();
130  bool first = true;
131  for (auto *screen : qAsConst(screens))
132  {
133  if (!first)
134  result.append("");
135  first = false;
136  QString id = QString("(%1)").arg(screen->manufacturer());
137  if (screen == current && !spanall)
138  result.append(tr("Current screen %1 %2:").arg(screen->name()).arg(id));
139  else
140  result.append(tr("Screen %1 %2:").arg(screen->name()).arg(id));
141  result.append(tr("Size") + QString("\t\t: %1mmx%2mm")
142  .arg(screen->physicalSize().width()).arg(screen->physicalSize().height()));
143  if (screen == current)
144  {
145  QString source;
146  double aspect = GetAspectRatio(source);
147  result.append(tr("Aspect ratio") + QString("\t: %1 (%2)")
148  .arg(aspect, 0, 'f', 3).arg(source));
149  if (!spanall)
150  {
151  result.append(tr("Current mode") + QString("\t: %1x%2@%3Hz")
152  .arg(GetResolution().width()).arg(GetResolution().height())
153  .arg(GetRefreshRate(), 0, 'f', 2));
154  }
155  }
156  }
157  return result;
158 }
159 
161  : ReferenceCounter("Display")
162 {
164  DebugScreen(m_screen, "Using");
165  if (m_screen)
166  {
167  connect(m_screen, &QScreen::geometryChanged, this, &MythDisplay::GeometryChanged);
168  connect(m_screen, &QScreen::physicalDotsPerInchChanged, this, &MythDisplay::PhysicalDPIChanged);
169  }
170 
171  auto *guiapp = qobject_cast<QGuiApplication *>(QCoreApplication::instance());
172  if (guiapp == nullptr)
173  return;
174 
175  connect(guiapp, &QGuiApplication::screenRemoved, this, &MythDisplay::ScreenRemoved);
176  connect(guiapp, &QGuiApplication::screenAdded, this, &MythDisplay::ScreenAdded);
177  connect(guiapp, &QGuiApplication::primaryScreenChanged, this, &MythDisplay::PrimaryScreenChanged);
178 }
179 
181 {
182  LOG(VB_GENERAL, LOG_INFO, LOC + "Deleting");
183 }
184 
198 void MythDisplay::SetWidget(QWidget *MainWindow)
199 {
200  QWidget* oldwidget = m_widget;
201  m_widget = MainWindow;
202  if (!m_modeComplete)
204 
205  QWindow* oldwindow = m_window;
206  if (m_widget)
207  m_window = m_widget->windowHandle();
208  else
209  m_window = nullptr;
210 
211  if (m_widget && (m_widget != oldwidget))
212  LOG(VB_GENERAL, LOG_INFO, LOC + "Have main widget");
213 
214  if (m_window && (m_window != oldwindow))
215  {
216  LOG(VB_GENERAL, LOG_INFO, LOC + "Have main window");
217 
218  connect(m_window, &QWindow::screenChanged, this, &MythDisplay::ScreenChanged, Qt::UniqueConnection);
219  QScreen *desired = GetDesiredScreen();
220  // If we have changed the video mode for the old screen then reset
221  // it to the default/desktop mode
222  SwitchToDesktop();
223  // Ensure we completely re-initialise when the new screen is set
224  m_initialised = false;
225  if (desired != m_screen)
226  DebugScreen(desired, "Moving to");
227  m_window->setScreen(desired);
228  // WaitForNewScreen doesn't work as intended. It successfully filters
229  // out unwanted screenChanged signals after moving screens - but always
230  //times out. This just delays startup by 500ms - so ignore on startup as it isn't needed.
231  if (!m_firstScreenChange)
233  m_firstScreenChange = false;
235  return;
236  }
237 }
238 
240 {
241  return QGuiApplication::screens().size();
242 }
243 
245 {
246  if (m_physicalSize.isEmpty() || m_resolution.isEmpty())
247  return 1.0;
248 
249  return (m_physicalSize.width() / static_cast<double>(m_resolution.width())) /
250  (m_physicalSize.height() / static_cast<double>(m_resolution.height()));
251 }
252 
254 {
255  return m_guiMode.Resolution();
256 }
257 
259 {
260  return m_screenBounds;
261 }
262 
276 {
277  return m_screen;
278 }
279 
281 {
282  QScreen* newscreen = nullptr;
283 
284  // If geometry is overriden at the command line level, try and determine
285  // which screen that applies to (if any).
286  // N.B. So many potential issues here e.g. should the geometry override be
287  // ignored after first use? (as it will continue to override the screen
288  // regardless of changes to screen preference).
290  {
291  // this matches the check in MythMainWindow
292  bool windowed = GetMythDB()->GetBoolSetting("RunFrontendInWindow", false) &&
294  QRect override = MythMainWindow::GetGeometryOverride();
295  // When windowed, we use topleft as a best guess as to which screen we belong in.
296  // When fullscreen, Qt appears to use the reverse - though this may be
297  // the window manager rather than Qt. So could be wrong.
298  QPoint point = windowed ? override.topLeft() : override.bottomRight();
299  QList screens = QGuiApplication::screens();
300  for (QScreen *screen : qAsConst(screens))
301  {
302  if (screen->geometry().contains(point))
303  {
304  newscreen = screen;
305  LOG(VB_GENERAL, LOG_INFO, LOC + QString(
306  "Geometry override places window in screen '%1'").arg(newscreen->name()));
307  break;
308  }
309  }
310  }
311 
312  // If spanning all screens, then always use the primary display
313  if (!newscreen && MythDisplay::SpanAllScreens())
314  {
315  LOG(VB_GENERAL, LOG_INFO, LOC + "Using primary screen for multiscreen");
316  newscreen = QGuiApplication::primaryScreen();
317  }
318 
319  QString name = gCoreContext->GetSetting("XineramaScreen", nullptr);
320  // Lookup by name
321  if (!newscreen)
322  {
323  QList screens = QGuiApplication::screens();
324  for (QScreen *screen : qAsConst(screens))
325  {
326  if (!name.isEmpty() && name == screen->name())
327  {
328  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Found screen '%1'").arg(name));
329  newscreen = screen;
330  }
331  }
332  }
333 
334  // No name match. These were previously numbers.
335  if (!newscreen)
336  {
337  bool ok = false;
338  int screen_num = name.toInt(&ok);
339  QList<QScreen *>screens = QGuiApplication::screens();
340  if (ok && (screen_num >= 0) && (screen_num < screens.size()))
341  {
342  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Found screen number %1 (%2)")
343  .arg(name).arg(screens[screen_num]->name()));
344  newscreen = screens[screen_num];
345  }
346  }
347 
348  // For anything else, return the primary screen.
349  if (!newscreen)
350  {
351  QScreen *primary = QGuiApplication::primaryScreen();
352  if (name.isEmpty() && primary)
353  {
354  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Defaulting to primary screen (%1)")
355  .arg(primary->name()));
356  }
357  else if (name != "-1" && primary)
358  {
359  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Screen '%1' not found, defaulting to primary screen (%2)")
360  .arg(name).arg(primary->name()));
361  }
362  newscreen = primary;
363  }
364 
365  return newscreen;
366 }
367 
370 void MythDisplay::ScreenChanged(QScreen *qScreen)
371 {
372  if (qScreen == m_screen)
373  return;
374  if (m_screen)
375  disconnect(m_screen, nullptr, this, nullptr);
376  DebugScreen(qScreen, "Changed to");
377  m_screen = qScreen;
378  connect(m_screen, &QScreen::geometryChanged, this, &MythDisplay::GeometryChanged);
379  connect(m_screen, &QScreen::physicalDotsPerInchChanged, this, &MythDisplay::PhysicalDPIChanged);
380  Initialise();
381  emit CurrentScreenChanged(qScreen);
382 }
383 
385 {
386  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Qt screen pixel ratio changed to %1")
387  .arg(DPI, 2, 'f', 2, '0'));
388  emit CurrentDPIChanged(DPI);
389 }
390 
391 void MythDisplay::PrimaryScreenChanged(QScreen* qScreen)
392 {
393  DebugScreen(qScreen, "New primary");
394 }
395 
396 void MythDisplay::ScreenAdded(QScreen* qScreen)
397 {
398  DebugScreen(qScreen, "New");
399  emit ScreenCountChanged(QGuiApplication::screens().size());
400 }
401 
402 void MythDisplay::ScreenRemoved(QScreen* qScreen)
403 {
404  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Screen '%1' removed").arg(qScreen->name()));
405  emit ScreenCountChanged(QGuiApplication::screens().size());
406 }
407 
408 void MythDisplay::GeometryChanged(const QRect &Geo)
409 {
410  LOG(VB_GENERAL, LOG_INFO, LOC + QString("New screen geometry: %1x%2+%3+%4")
411  .arg(Geo.width()).arg(Geo.height()).arg(Geo.left()).arg(Geo.top()));
412 }
413 
421 {
422  // Certain platform implementations do not have a window to access at startup
423  // and hence use this implementation. Flag the status as incomplete to ensure
424  // we try to retrieve the full details at the first opportunity.
425  m_modeComplete = false;
426  m_edid = MythEDID();
427  QScreen *screen = GetCurrentScreen();
428  if (!screen)
429  {
430  m_refreshRate = 60.0;
431  m_physicalSize = QSize(0, 0);
432  m_resolution = QSize(1920, 1080);
433  return;
434  }
435  m_refreshRate = screen->refreshRate();
436  m_resolution = screen->size();
437  m_physicalSize = QSize(static_cast<int>(screen->physicalSize().width()),
438  static_cast<int>(screen->physicalSize().height()));
439 }
440 
443 {
444  return gCoreContext->GetSetting("XineramaScreen", nullptr) == "-1";
445 }
446 
447 QString MythDisplay::GetExtraScreenInfo(QScreen *qScreen)
448 {
449  QString mfg = qScreen->manufacturer();
450  if (mfg.isEmpty())
451  mfg = "Unknown";
452  QString model = qScreen->model();
453  if (model.isEmpty())
454  model = "Unknown";
455  return QString("(Make: %1 Model: %2)").arg(mfg).arg(model);
456 }
457 
458 void MythDisplay::DebugScreen(QScreen *qScreen, const QString &Message)
459 {
460  if (!qScreen)
461  return;
462 
463  QRect geom = qScreen->geometry();
464  QString extra = GetExtraScreenInfo(qScreen);
465 
466  LOG(VB_GENERAL, LOG_INFO, LOC + QString("%1 screen '%2' %3")
467  .arg(Message).arg(qScreen->name()).arg(extra));
468  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Qt screen pixel ratio: %1")
469  .arg(qScreen->devicePixelRatio(), 2, 'f', 2, '0'));
470  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Geometry: %1x%2+%3+%4 Size(Qt): %5mmx%6mm")
471  .arg(geom.width()).arg(geom.height()).arg(geom.left()).arg(geom.top())
472  .arg(qScreen->physicalSize().width()).arg(qScreen->physicalSize().height()));
473 
474  if (qScreen->virtualGeometry() != geom)
475  {
476  geom = qScreen->virtualGeometry();
477  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Total virtual geometry: %1x%2+%3+%4")
478  .arg(geom.width()).arg(geom.height()).arg(geom.left()).arg(geom.top()));
479  }
480 }
481 
483 {
484  m_videoModes.clear();
485  m_overrideVideoModes.clear();
488 
489  // Set the desktop mode - which is the mode at startup. We must always return
490  // the screen to this mode.
491  if (!m_initialised)
492  {
493  // Only ever set this once or after a screen change
494  m_initialised = true;
496  LOG(VB_GENERAL, LOG_NOTICE, LOC + QString("Desktop video mode: %1x%2 %3Hz")
497  .arg(m_resolution.width()).arg(m_resolution.height()).arg(m_refreshRate, 0, 'f', 3));
498  if (m_edid.Valid())
499  {
500  if (m_edid.IsSRGB())
501  LOG(VB_GENERAL, LOG_NOTICE, LOC + "Display is using sRGB colourspace");
502  else
503  LOG(VB_GENERAL, LOG_NOTICE, LOC + "Display has custom colourspace");
504  }
505  }
506 
507  // Set the gui mode from database settings
508  int pixelwidth = m_resolution.width();
509  int pixelheight = m_resolution.height();
510  int mmwidth = m_physicalSize.width();
511  int mmheight = m_physicalSize.height();
512  double refreshrate = m_refreshRate;
513  double aspectratio = 0.0;
514  GetMythDB()->GetResolutionSetting("GuiVidMode", pixelwidth, pixelheight, aspectratio, refreshrate);
515  GetMythDB()->GetResolutionSetting("DisplaySize", mmwidth, mmheight);
516  m_guiMode = MythDisplayMode(pixelwidth, pixelheight, mmwidth, mmheight, -1.0, refreshrate);
517 
518  // Set default video mode
519  pixelwidth = pixelheight = 0;
520  GetMythDB()->GetResolutionSetting("TVVidMode", pixelwidth, pixelheight, aspectratio, refreshrate);
521  m_videoMode = MythDisplayMode(pixelwidth, pixelheight, mmwidth, mmheight, aspectratio, refreshrate);
522 
523  // Initialise video override modes
524  for (int i = 0; true; ++i)
525  {
526  int iw = 0;
527  int ih = 0;
528  int ow = 0;
529  int oh = 0;
530  double iaspect = 0.0;
531  double oaspect = 0.0;
532  double irate = 0.0;
533  double orate = 0.0;
534 
535  GetMythDB()->GetResolutionSetting("VidMode", iw, ih, iaspect, irate, i);
536  GetMythDB()->GetResolutionSetting("TVVidMode", ow, oh, oaspect, orate, i);
537 
538  if (!(iw || ih || !qFuzzyIsNull(irate)) || !(ih && ow && oh))
539  break;
540 
541  uint64_t key = MythDisplayMode::CalcKey(QSize(iw, ih), irate);
542  MythDisplayMode scr(QSize(ow, oh), QSize(mmwidth, mmheight), oaspect, orate);
543  m_overrideVideoModes[key] = scr;
544  }
545 }
546 
547 
556 {
557  QList<QScreen*> screens = QGuiApplication::screens();
558  for (auto *screen : screens)
559  {
560  QRect dim = screen->geometry();
561  QString extra = MythDisplay::GetExtraScreenInfo(screen);
562  LOG(VB_GUI, LOG_INFO, LOC + QString("Screen %1: %2x%3 %4")
563  .arg(screen->name()).arg(dim.width()).arg(dim.height()).arg(extra));
564  }
565 
566  QScreen *primary = QGuiApplication::primaryScreen();
567  LOG(VB_GUI, LOG_INFO, LOC +QString("Primary screen: %1.").arg(primary->name()));
568 
569  int numScreens = MythDisplay::GetScreenCount();
570  QSize dim = primary->virtualSize();
571  LOG(VB_GUI, LOG_INFO, LOC + QString("Total desktop dim: %1x%2, over %3 screen[s].")
572  .arg(dim.width()).arg(dim.height()).arg(numScreens));
573 
575  {
576  LOG(VB_GUI, LOG_INFO, LOC + QString("Using entire desktop."));
577  m_screenBounds = primary->virtualGeometry();
578  return;
579  }
580 
581  if (GetMythDB()->GetBoolSetting("RunFrontendInWindow", false))
582  {
583  LOG(VB_GUI, LOG_INFO, LOC + "Running in a window");
584  // This doesn't include the area occupied by the
585  // Windows taskbar, or the Mac OS X menu bar and Dock
586  m_screenBounds = m_screen->availableGeometry();
587  }
588  else
589  {
590  m_screenBounds = m_screen->geometry();
591  }
592 
593  LOG(VB_GUI, LOG_INFO, LOC + QString("Using screen %1: %2x%3 at %4+%5")
594  .arg(m_screen->name()).arg(m_screenBounds.width()).arg(m_screenBounds.height())
595  .arg(m_screenBounds.left()).arg(m_screenBounds.top()));
596 }
597 
605 {
606  return Size.width() > m_resolution.width() || Size.height() > m_resolution.height();
607 }
608 
614 {
616  if (current == m_desktopMode)
617  return;
619 }
620 
624 bool MythDisplay::SwitchToVideo(QSize Size, double Rate)
625 {
626  if (!m_modeComplete)
628 
631  double targetrate = 0.0;
632  double aspectoverride = 0.0;
633 
634  // try to find video override mode
636  Size.width(), Size.height(), Rate);
637 
638  if (key != 0)
639  {
640  next = m_overrideVideoModes[key];
641  if (next.AspectRatio() > 0.0)
642  aspectoverride = next.AspectRatio();
643  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Found custom screen override %1x%2 Aspect %3")
644  .arg(next.Width()).arg(next.Height()).arg(aspectoverride));
645  }
646 
647  // If requested refresh rate is 0, attempt to match video fps
648  if (qFuzzyIsNull(next.RefreshRate()))
649  {
650  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Trying to match best refresh rate %1Hz")
651  .arg(Rate, 0, 'f', 3));
652  next.SetRefreshRate(Rate);
653  }
654 
655  // need to change video mode?
656  MythDisplayMode::FindBestMatch(GetVideoModes(), next, targetrate);
657  if ((next == current) && (MythDisplayMode::CompareRates(current.RefreshRate(), targetrate)))
658  {
659  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Using current mode %1x%2@%3Hz")
660  .arg(m_resolution.width()).arg(m_resolution.height()).arg(m_refreshRate));
661  return true;
662  }
663 
664  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Trying mode %1x%2@%3Hz")
665  .arg(next.Width()).arg(next.Height()).arg(next.RefreshRate(), 0, 'f', 3));
666 
667  if (!SwitchToVideoMode(next.Resolution(), targetrate))
668  {
669  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to change mode to %1x%2@%3Hz")
670  .arg(next.Width()).arg(next.Height()).arg(next.RefreshRate(), 0, 'f', 3));
671  return false;
672  }
673 
674  if (next.Resolution() != m_resolution)
676 
677  // N.B. We used a computed aspect ratio unless overridden
678  m_aspectRatioOverride = aspectoverride > 0.0 ? aspectoverride : 0.0;
680  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Switched to %1x%2@%3Hz for video %4x%5")
681  .arg(m_resolution.width()).arg(m_resolution.height())
682  .arg(m_refreshRate, 0, 'f', 3).arg(Size.width()).arg(Size.height()));
684  return true;
685 }
686 
690 {
691  if (!m_modeComplete)
693 
694  // If the current resolution is the same as the GUI resolution then do nothing
695  // as refresh rate should not be critical for the GUI.
697  {
698  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Using %1x%2@%3Hz for GUI")
699  .arg(m_resolution.width()).arg(m_resolution.height()).arg(m_refreshRate));
700  return true;
701  }
702 
704  {
705  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to change mode to %1x%2@%3Hz")
706  .arg(m_guiMode.Width()).arg(m_guiMode.Height()).arg(m_guiMode.RefreshRate(), 0, 'f', 3));
707  return false;
708  }
709 
710  if (Wait && (m_resolution != m_guiMode.Resolution()))
712 
714  m_aspectRatioOverride = 0.0;
715  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Switched to %1x%2@%3Hz")
716  .arg(m_resolution.width()).arg(m_resolution.height()).arg(m_refreshRate, 0, 'f', 3));
717  return true;
718 }
719 
721 {
722  return m_refreshRate;
723 }
724 
725 int MythDisplay::GetRefreshInterval(int Fallback) const
726 {
727  if (m_refreshRate > 20.0 && m_refreshRate < 200.0)
728  return static_cast<int>(lround(1000000.0 / m_refreshRate));
729  if (Fallback > 33000) // ~30Hz
730  Fallback /= 2;
731  return Fallback;
732 }
733 
734 std::vector<double> MythDisplay::GetRefreshRates(QSize Size)
735 {
736  auto targetrate = static_cast<double>(NAN);
737  const MythDisplayMode mode(Size, QSize(0, 0), -1.0, 0.0);
738  const std::vector<MythDisplayMode>& modes = GetVideoModes();
739  int match = MythDisplayMode::FindBestMatch(modes, mode, targetrate);
740  if (match < 0)
741  return std::vector<double>();
742  return modes[static_cast<size_t>(match)].RefreshRates();
743 }
744 
745 bool MythDisplay::SwitchToVideoMode(QSize /*Size*/, double /*Framerate*/)
746 {
747  return false;
748 }
749 
750 const std::vector<MythDisplayMode> &MythDisplay::GetVideoModes()
751 {
752  return m_videoModes;
753 }
754 
773 double MythDisplay::GetAspectRatio(QString &Source, bool IgnoreModeOverride)
774 {
775  auto valid = [](double Aspect) { return (Aspect > 0.1 && Aspect < 10.0); };
776 
777  // Override for this video mode
778  // Is this behaviour still needed?
779  if (!IgnoreModeOverride && valid(m_aspectRatioOverride))
780  {
781  Source = tr("Video mode override");
782  return m_aspectRatioOverride;
783  }
784 
785  // General override for invalid/misleading EDIDs or multiscreen setups
786  // New default of -1.0 equates to square pixels for modern displays
787  bool multiscreen = MythDisplay::SpanAllScreens() && GetScreenCount() > 1;
788  double override = gCoreContext->GetFloatSettingOnHost("XineramaMonitorAspectRatio",
789  gCoreContext->GetHostName(), -1.0);
790 
791  // Zero (not valid) indicates auto
792  if (valid(override))
793  {
794  Source = tr("Override");
795  return override;
796  }
797 
798  // Auto for multiscreen is a best guess
799  if (multiscreen)
800  {
801  double aspect = EstimateVirtualAspectRatio();
802  if (valid(aspect))
803  {
804  Source = tr("Multiscreen estimate");
805  return aspect;
806  }
807  }
808 
809  double calculated = m_resolution.isEmpty() ? 0.0 :
810  static_cast<double>(m_resolution.width()) / m_resolution.height();
811  double detected = m_physicalSize.isEmpty() ? 0.0 :
812  static_cast<double>(m_physicalSize.width()) / m_physicalSize.height();
813 
814  // Assume pixel aspect ratio is 1 (square pixels)
815  if (valid(calculated))
816  {
817  if ((override < 0.0) || !valid(detected))
818  {
819  Source = tr("Square pixels");
820  return calculated;
821  }
822  }
823 
824  // Based on actual physical size if available
825  if (valid(detected))
826  {
827  Source = tr("Detected");
828  return detected;
829  }
830 
831  // the aspect ratio of last resort
832  Source = tr("Guessed");
833  return 16.0 / 9.0;
834 }
835 
837 {
838  return m_edid;
839 }
840 
851 {
852  auto sortscreens = [](const QScreen* First, const QScreen* Second)
853  {
854  if (First->geometry().left() < Second->geometry().left())
855  return true;
856  if (First->geometry().top() < Second->geometry().top())
857  return true;
858  return false;
859  };
860 
861  // default
862  double result = 16.0 / 9.0;
863 
864  QList<QScreen*> screens;
865  if (m_screen)
866  screens = m_screen->virtualSiblings();
867  if (screens.empty())
868  return result;
869 
870  // N.B. This sorting may not be needed
871  std::sort(screens.begin(), screens.end(), sortscreens);
872  QList<double> aspectratios;
873  QSize totalresolution;
874  int lasttop = 0;
875  int lastleft = 0;
876  int rows = 1;
877  int columns = 1;
878  for (auto it = screens.constBegin() ; it != screens.constEnd(); ++it)
879  {
880  QRect geom = (*it)->geometry();
881  totalresolution += geom.size();
882  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("%1x%2+%3+%4 %5")
883  .arg(geom.width()).arg(geom.height()).arg(geom.left()).arg(geom.top())
884  .arg((*it)->physicalSize().width() / (*it)->physicalSize().height()));
885  if (lastleft < geom.left())
886  {
887  columns++;
888  lastleft = geom.left();
889  }
890  if (lasttop < geom.top())
891  {
892  rows++;
893  lasttop = geom.top();
894  lastleft = 0;
895  }
896  aspectratios << (*it)->physicalSize().width() / (*it)->physicalSize().height();
897  }
898 
899  // If all else fails, use the total resolution and assume pixel aspect ratio
900  // equals display aspect ratio
901  if (!totalresolution.isEmpty())
902  result = static_cast<double>(totalresolution.width()) / totalresolution.height();
903 
904  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Screen layout: %1x%2").arg(rows).arg(columns));
905  if (rows == columns)
906  {
907  LOG(VB_GENERAL, LOG_DEBUG, LOC + "Grid layout");
908  }
909  else if (rows == 1 && columns > 1)
910  {
911  LOG(VB_GENERAL, LOG_DEBUG, LOC + "Horizontal layout");
912  }
913  else if (columns == 1 && rows > 1)
914  {
915  LOG(VB_GENERAL, LOG_DEBUG, LOC + "Vertical layout");
916  }
917  else
918  {
919  LOG(VB_GENERAL, LOG_INFO,
920  LOC + QString("Unsupported layout - defaulting to %1 (%2/%3)")
921  .arg(result).arg(totalresolution.width()).arg(totalresolution.height()));
922  return result;
923  }
924 
925  // validate aspect ratios - with a little fuzzyness
926  double aspectratio = 0.0;
927  double average = 0.0;
928  int count = 1;
929  for (auto it2 = aspectratios.constBegin() ; it2 != aspectratios.constEnd(); ++it2, ++count)
930  {
931  aspectratio += *it2;
932  average = aspectratio / count;
933  if (qAbs(*it2 - average) > 0.1)
934  {
935  LOG(VB_GENERAL, LOG_INFO, LOC +
936  QString("Inconsistent aspect ratios - defaulting to %1 (%2/%3)")
937  .arg(result).arg(totalresolution.width()).arg(totalresolution.height()));
938  return result;
939  }
940  }
941 
942  aspectratio = (average * columns) / rows;
943  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Estimated aspect ratio: %1")
944  .arg(aspectratio));
945  return aspectratio;
946 }
947 
949 {
950  return m_resolution;
951 }
952 
954 {
955  return m_physicalSize;
956 }
957 
959 {
960  // Some implementations may have their own mechanism for ensuring the mode
961  // is updated before continuing
963  return;
964 
965  LOG(VB_GENERAL, LOG_INFO, LOC + "Waiting for resolution change");
966  QEventLoop loop;
967  QTimer timer;
968  timer.setSingleShot(true);
969  connect(&timer, &QTimer::timeout, [](){ LOG(VB_GENERAL, LOG_WARNING, LOC + "Timed out wating for screen change"); });
970  QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
971  QObject::connect(m_screen, &QScreen::geometryChanged, &loop, &QEventLoop::quit);
972  // 500ms maximum wait
973  timer.start(500);
974  loop.exec();
975 }
976 
978 {
979  // N.B. This isn't working as intended as it always times out rather than
980  // exiting deliberately. It does however somehow filter out unwanted screenChanged
981  // events that otherwise often put the widget in the wrong screen.
982  // Needs more investigation - but for now it works:)
983  if (!m_widget || (m_widget && !m_widget->windowHandle()))
984  return;
985  LOG(VB_GENERAL, LOG_INFO, LOC + "Waiting for new screen");
986  QEventLoop loop;
987  QTimer timer;
988  timer.setSingleShot(true);
989  connect(&timer, &QTimer::timeout, [](){ LOG(VB_GENERAL, LOG_WARNING, LOC + "Timed out waiting for new screen"); });
990  QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
991  QObject::connect(m_widget->windowHandle(), &QWindow::screenChanged, &loop, &QEventLoop::quit);
992  // 500ms maximum wait
993  timer.start(500);
994  loop.exec();
995 }
996 
998 {
999  int pauselengthinms = gCoreContext->GetNumSetting("VideoModeChangePauseMS", 0);
1000  if (pauselengthinms)
1001  {
1002  LOG(VB_GENERAL, LOG_INFO, LOC +
1003  QString("Pausing %1ms for video mode switch").arg(pauselengthinms));
1004  QEventLoop loop;
1005  QTimer timer;
1006  timer.setSingleShot(true);
1007  QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
1008  // 500ms maximum wait
1009  timer.start(pauselengthinms);
1010  loop.exec();
1011  }
1012 }
1013 
1015 {
1016  // This is intentionally formatted to match the output of xrandr for comparison
1017  if (VERBOSE_LEVEL_CHECK(VB_PLAYBACK, LOG_INFO))
1018  {
1019  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Available modes:");
1020  for (auto it = m_videoModes.crbegin(); it != m_videoModes.crend(); ++it)
1021  {
1022  auto rates = (*it).RefreshRates();
1023  QStringList rateslist;
1024  for (auto it2 = rates.crbegin(); it2 != rates.crend(); ++it2)
1025  rateslist.append(QString("%1").arg(*it2, 2, 'f', 2, '0'));
1026  if (rateslist.empty())
1027  rateslist.append("Variable rate?");
1028  LOG(VB_PLAYBACK, LOG_INFO, QString("%1x%2\t%3")
1029  .arg((*it).Width()).arg((*it).Height()).arg(rateslist.join("\t")));
1030  }
1031  }
1032 }
1033 
1039 void MythDisplay::ConfigureQtGUI(int SwapInterval, const QString& _Display)
1040 {
1041  // Set the default surface format. Explicitly required on some platforms.
1042  QSurfaceFormat format;
1043  format.setAlphaBufferSize(0);
1044  format.setDepthBufferSize(0);
1045  format.setStencilBufferSize(0);
1046  format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
1047  format.setProfile(QSurfaceFormat::CompatibilityProfile);
1048  format.setSwapInterval(SwapInterval);
1049  QSurfaceFormat::setDefaultFormat(format);
1050 
1051 #ifdef Q_OS_MAC
1052  // Without this, we can't set focus to any of the CheckBoxSetting, and most
1053  // of the MythPushButton widgets, and they don't use the themed background.
1054  QApplication::setDesktopSettingsAware(false);
1055 #endif
1056 
1057  // If Wayland decorations are enabled, the default framebuffer format is forced
1058  // to use alpha. This framebuffer is rendered with alpha blending by the wayland
1059  // compositor - so any translucent areas of our UI will allow the underlying
1060  // window to bleed through.
1061  // N.B. this is probably not the most performant solution as compositors MAY
1062  // still render hidden windows. A better solution is probably to call
1063  // wl_surface_set_opaque_region on the wayland surface. This is confirmed to work
1064  // and should allow the compositor to optimise rendering for opaque areas. It does
1065  // however require linking to libwayland-client AND including private Qt headers
1066  // to retrieve the surface and compositor structures (the latter being a significant issue).
1067  // see also setAlphaBufferSize above
1068  setenv("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1", 0);
1069 
1070 #if defined (Q_OS_LINUX) && defined (USING_EGL) && defined (USING_X11)
1071  // We want to use EGL for VAAPI/MMAL/DRMPRIME rendering to ensure we
1072  // can use zero copy video buffers for the best performance (N.B. not tested
1073  // on AMD desktops). To force Qt to use EGL we must set 'QT_XCB_GL_INTEGRATION'
1074  // to 'xcb_egl' and this must be done before any GUI is created. If the platform
1075  // plugin is not xcb then this should have no effect.
1076  // This does however break when using NVIDIA drivers - which do not support
1077  // EGL like other drivers so we try to check the EGL vendor - and we currently
1078  // have no need for EGL with NVIDIA (that may change however).
1079  // NOTE force using EGL by setting MYTHTV_FORCE_EGL
1080  // NOTE disable using EGL by setting MYTHTV_NO_EGL
1081  // NOTE We have no Qt platform information, window/surface or logging when this is called.
1082  QString soft = qgetenv("LIBGL_ALWAYS_SOFTWARE");
1083  bool ignore = soft == "1" || soft.compare("true", Qt::CaseInsensitive) == 0;
1084  bool allow = qEnvironmentVariableIsEmpty("MYTHTV_NO_EGL") && !ignore;
1085  bool force = !qEnvironmentVariableIsEmpty("MYTHTV_FORCE_EGL");
1086  if ((force || allow) && MythDisplayX11::IsAvailable())
1087  {
1088  // N.B. By default, ignore EGL if vendor string is not returned
1089  QString vendor = MythEGL::GetEGLVendor();
1090  if (vendor.contains("nvidia", Qt::CaseInsensitive) && !force)
1091  {
1092  qInfo() << LOC + QString("Not requesting EGL for vendor '%1'").arg(vendor);
1093  }
1094  else if (!vendor.isEmpty() || force)
1095  {
1096  qInfo() << LOC + QString("Requesting EGL for '%1'").arg(vendor);
1097  setenv("QT_XCB_GL_INTEGRATION", "xcb_egl", 0);
1098  }
1099  }
1100 #endif
1101 #ifdef Q_OS_ANDROID
1102  //QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
1103 #endif
1104 
1105  // Ignore desktop scaling
1106  QApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
1107 
1108 #ifdef USING_X11
1110 #else
1111  (void)_Display;
1112 #endif
1113 }
MythDB::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval)
Definition: mythdb.cpp:562
force
bool force
Definition: mythtv/programs/mythcommflag/main.cpp:74
MythDisplay::m_physicalSize
QSize m_physicalSize
Definition: mythdisplay.h:86
mythdisplaymutter.h
MythDisplay::GetRefreshRates
std::vector< double > GetRefreshRates(QSize Size)
Definition: mythdisplay.cpp:734
MythDisplay::GetRefreshRate
double GetRefreshRate() const
Definition: mythdisplay.cpp:720
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:103
MythDisplay::GetScreenBounds
QRect GetScreenBounds()
Definition: mythdisplay.cpp:258
MythDisplay::GetEDID
MythEDID & GetEDID()
Definition: mythdisplay.cpp:836
MythDisplay::SwitchToDesktop
void SwitchToDesktop()
Return the screen to the original desktop video mode.
Definition: mythdisplay.cpp:613
MythDisplay::m_screenBounds
QRect m_screenBounds
Definition: mythdisplay.h:99
MythDisplayMode::FindBestScreen
static uint64_t FindBestScreen(const DisplayModeMap &Map, int Width, int Height, double Rate)
Definition: mythdisplaymode.cpp:222
MythDisplay::DebugScreen
static void DebugScreen(QScreen *qScreen, const QString &Message)
Definition: mythdisplay.cpp:458
mythdisplaywindows.h
MythDisplay::m_resolution
QSize m_resolution
Definition: mythdisplay.h:85
MythDisplay::ScreenChanged
virtual void ScreenChanged(QScreen *qScreen)
The actual screen in use has changed. We must use it.
Definition: mythdisplay.cpp:370
MythDisplayDRM
Definition: mythdisplaydrm.h:12
MythDisplay::Create
static MythDisplay * Create()
Create a MythDisplay object appropriate for the current platform.
Definition: mythdisplay.cpp:75
MythDisplay::m_videoMode
MythDisplayMode m_videoMode
Definition: mythdisplay.h:102
MythXDisplay::SetQtX11Display
static void SetQtX11Display(const QString &Display)
Definition: mythxdisplay.cpp:56
MythDisplayMode::CalcKey
static uint64_t CalcKey(QSize Size, double Rate)
Definition: mythdisplaymode.cpp:126
setenv
#define setenv(x, y, z)
Definition: compat.h:157
arg
arg(title).arg(filename).arg(doDelete))
MythDisplay::GetAspectRatio
double GetAspectRatio(QString &Source, bool IgnoreModeOverride=false)
Returns current screen aspect ratio.
Definition: mythdisplay.cpp:773
LOC
#define LOC
Definition: mythdisplay.cpp:39
MythDisplay::SpanAllScreens
static bool SpanAllScreens()
Return true if the MythTV windows should span all screens.
Definition: mythdisplay.cpp:442
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythDisplayMode::Width
int Width(void) const
Definition: mythdisplaymode.cpp:58
MythDisplayRPI
Definition: mythdisplayrpi.h:17
MythDisplayMode::Resolution
QSize Resolution(void) const
Definition: mythdisplaymode.cpp:53
MythDisplay::GetCurrentScreen
QScreen * GetCurrentScreen()
Return a pointer to the screen to use.
Definition: mythdisplay.cpp:275
GetMythDB
MythDB * GetMythDB(void)
Definition: mythdb.cpp:45
MythDisplay::ScreenRemoved
void ScreenRemoved(QScreen *qScreen)
Definition: mythdisplay.cpp:402
MythEDID::Valid
bool Valid(void) const
Definition: mythedid.cpp:32
MythDisplay::GetPixelAspectRatio
double GetPixelAspectRatio()
Definition: mythdisplay.cpp:244
MythDisplay::PhysicalDPIChanged
void PhysicalDPIChanged(qreal DPI)
Definition: mythdisplay.cpp:384
MythDisplay::UpdateCurrentMode
virtual void UpdateCurrentMode()
Retrieve screen details.
Definition: mythdisplay.cpp:420
MythDisplay::InitScreenBounds
void InitScreenBounds()
Get screen size from Qt while respecting the user's multiscreen settings.
Definition: mythdisplay.cpp:555
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
MythDisplay::m_modeComplete
bool m_modeComplete
Definition: mythdisplay.h:82
MythDisplay::CurrentScreenChanged
void CurrentScreenChanged(QScreen *qScreen)
MythDisplay::m_guiMode
MythDisplayMode m_guiMode
Definition: mythdisplay.h:101
mythdisplayosx.h
MythDisplay::DebugModes
void DebugModes() const
Definition: mythdisplay.cpp:1014
MythDisplay::GetGUIResolution
QSize GetGUIResolution()
Definition: mythdisplay.cpp:253
quit
@ quit
Definition: lirc_client.h:30
MythDisplayAndroid
Definition: mythdisplayandroid.h:8
MythEGL::GetEGLVendor
static QString GetEGLVendor(void)
Definition: mythegl.cpp:85
MythDisplay::PauseForModeSwitch
static void PauseForModeSwitch()
Definition: mythdisplay.cpp:997
MythDisplay::m_aspectRatioOverride
double m_aspectRatioOverride
Definition: mythdisplay.h:84
mythdisplay.h
MythDisplay::GetResolution
QSize GetResolution()
Definition: mythdisplay.cpp:948
MythDisplay::EstimateVirtualAspectRatio
double EstimateVirtualAspectRatio()
Estimate the overall display aspect ratio for multi screen setups.
Definition: mythdisplay.cpp:850
mythlogging.h
MythDisplayMode::AspectRatio
double AspectRatio(void) const
Definition: mythdisplaymode.cpp:83
mythdisplayrpi.h
MythDisplay::WaitForNewScreen
void WaitForNewScreen()
Definition: mythdisplay.cpp:977
Source
Definition: channelsettings.cpp:69
MythDisplay::~MythDisplay
~MythDisplay() override
Definition: mythdisplay.cpp:180
MythDisplay::m_overrideVideoModes
DisplayModeMap m_overrideVideoModes
Definition: mythdisplay.h:103
mythdisplaydrm.h
MythDisplay::GetScreenCount
static int GetScreenCount()
Definition: mythdisplay.cpp:239
MythDisplay::GetExtraScreenInfo
static QString GetExtraScreenInfo(QScreen *qScreen)
Definition: mythdisplay.cpp:447
MythDisplayWindows
Definition: mythdisplaywindows.h:8
compat.h
MythDisplay::m_edid
MythEDID m_edid
Definition: mythdisplay.h:87
MythDisplay::m_window
QWindow * m_window
Definition: mythdisplay.h:89
MythDisplayMode::Height
int Height(void) const
Definition: mythdisplaymode.cpp:63
MythDisplayMode::FindBestMatch
static int FindBestMatch(const std::vector< MythDisplayMode > &Modes, const MythDisplayMode &Mode, double &TargetRate)
Definition: mythdisplaymode.cpp:139
MythDisplay::SetWidget
void SetWidget(QWidget *MainWindow)
Set the QWidget and QWindow in use.
Definition: mythdisplay.cpp:198
MythDisplay::m_videoModes
std::vector< MythDisplayMode > m_videoModes
Definition: mythdisplay.h:91
MythDisplay::SwitchToVideoMode
virtual bool SwitchToVideoMode(QSize Size, double Framerate)
Definition: mythdisplay.cpp:745
MythDisplayX11
Definition: mythdisplayx11.h:15
MythDisplay::SwitchToVideo
bool SwitchToVideo(QSize Size, double Rate=0.0)
Switches to the resolution and refresh rate defined in the database for the specified video resolutio...
Definition: mythdisplay.cpp:624
MythDisplay::GetPhysicalSize
QSize GetPhysicalSize()
Definition: mythdisplay.cpp:953
MythDisplay::m_waitForModeChanges
bool m_waitForModeChanges
Definition: mythdisplay.h:81
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:56
MythDisplay
Definition: mythdisplay.h:19
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:929
MythDisplayMode
Definition: mythdisplaymode.h:21
MythDisplay::GetVideoModes
virtual const std::vector< MythDisplayMode > & GetVideoModes()
Definition: mythdisplay.cpp:750
MythDisplay::ScreenAdded
void ScreenAdded(QScreen *qScreen)
Definition: mythdisplay.cpp:396
MythDB::GetResolutionSetting
void GetResolutionSetting(const QString &type, int &width, int &height, double &forced_aspect, double &refresh_rate, int index=-1)
Definition: mythdb.cpp:723
mythuihelper.h
MythDisplay::m_refreshRate
double m_refreshRate
Definition: mythdisplay.h:83
MythDisplayX11::IsAvailable
static bool IsAvailable(void)
Definition: mythdisplayx11.cpp:17
setAttribute
channel setAttribute("chanid", chanID)
VERBOSE_LEVEL_CHECK
#define VERBOSE_LEVEL_CHECK(_MASK_, _LEVEL_)
Definition: mythlogging.h:14
MythDisplay::Initialise
void Initialise()
Definition: mythdisplay.cpp:482
MythDisplay::NextModeIsLarger
bool NextModeIsLarger(QSize Size)
Check whether the next mode is larger in size than the current mode.
Definition: mythdisplay.cpp:604
MythUIScreenBounds::WindowIsAlwaysFullscreen
static bool WindowIsAlwaysFullscreen()
Return true if the current platform only supports fullscreen windows.
Definition: mythuiscreenbounds.cpp:111
MythDisplay::m_widget
QWidget * m_widget
Definition: mythdisplay.h:88
mythcorecontext.h
MythDisplay::SwitchToGUI
bool SwitchToGUI(bool Wait=false)
Switches to the GUI resolution.
Definition: mythdisplay.cpp:689
MythDisplay::ScreenCountChanged
void ScreenCountChanged(int Screens)
MythDisplay::GetRefreshInterval
int GetRefreshInterval(int Fallback) const
Definition: mythdisplay.cpp:725
MythDisplayOSX
Definition: mythdisplayosx.h:11
MythDisplayMode::SetRefreshRate
void SetRefreshRate(double Rate)
Definition: mythdisplaymode.cpp:120
MythUIScreenBounds::GetGeometryOverride
static QRect GetGeometryOverride()
Definition: mythuiscreenbounds.cpp:23
MythDisplayMode::RefreshRate
double RefreshRate(void) const
Definition: mythdisplaymode.cpp:94
MythDisplay::WaitForScreenChange
void WaitForScreenChange()
Definition: mythdisplay.cpp:958
MythDisplay::ConfigureQtGUI
static void ConfigureQtGUI(int SwapInterval=1, const QString &Display=QString())
Shared static initialistaion code for all MythTV GUI applications.
Definition: mythdisplay.cpp:1039
MythDisplayMode::CompareRates
static bool CompareRates(double First, double Second, double Precision=0.01)
Determine whether two rates are considered equal with the given precision.
Definition: mythdisplaymode.cpp:134
MythEDID::IsSRGB
bool IsSRGB(void) const
Definition: mythedid.cpp:67
MythDisplay::m_initialised
bool m_initialised
Definition: mythdisplay.h:97
MythDisplay::m_screen
QScreen * m_screen
Definition: mythdisplay.h:90
mythegl.h
MythDisplay::m_desktopMode
MythDisplayMode m_desktopMode
Definition: mythdisplay.h:100
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:855
MythDisplay::GeometryChanged
static void GeometryChanged(const QRect &Geometry)
Definition: mythdisplay.cpp:408
mythdisplayandroid.h
MythDisplay::GetDescription
QStringList GetDescription()
Definition: mythdisplay.cpp:114
MythDisplay::GetDesiredScreen
static QScreen * GetDesiredScreen()
Definition: mythdisplay.cpp:280
MythDisplay::PrimaryScreenChanged
static void PrimaryScreenChanged(QScreen *qScreen)
Definition: mythdisplay.cpp:391
mythdisplayx11.h
mythmainwindow.h
MythDisplay::MythDisplay
MythDisplay()
Definition: mythdisplay.cpp:160
MythCoreContext::GetFloatSettingOnHost
double GetFloatSettingOnHost(const QString &key, const QString &host, double defaultval=0.0)
Definition: mythcorecontext.cpp:969
ReferenceCounter
General purpose reference counter.
Definition: referencecounter.h:27
MythUIScreenBounds::GeometryIsOverridden
static bool GeometryIsOverridden()
Definition: mythuiscreenbounds.cpp:18
MythEDID
Definition: mythedid.h:18
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:915
MythDisplay::CurrentDPIChanged
void CurrentDPIChanged(qreal DPI)
MythDisplay::m_firstScreenChange
bool m_firstScreenChange
Definition: mythdisplay.h:98