KonvergoWindow.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. #include "KonvergoWindow.h"
  2. #include <QTimer>
  3. #include <QJsonObject>
  4. #include <QScreen>
  5. #include <QQuickItem>
  6. #include <QGuiApplication>
  7. #include <QMessageBox>
  8. #include <QPushButton>
  9. #include "core/Version.h"
  10. #include "system/UpdaterComponent.h"
  11. #include "input/InputKeyboard.h"
  12. #include "settings/SettingsComponent.h"
  13. #include "settings/SettingsSection.h"
  14. #include "system/SystemComponent.h"
  15. #include "player/PlayerComponent.h"
  16. #include "player/PlayerQuickItem.h"
  17. #include "display/DisplayComponent.h"
  18. #include "QsLog.h"
  19. #include "utils/Utils.h"
  20. #include "Globals.h"
  21. #include "EventFilter.h"
  22. ///////////////////////////////////////////////////////////////////////////////////////////////////
  23. KonvergoWindow::KonvergoWindow(QWindow* parent) :
  24. QQuickWindow(parent),
  25. m_debugLayer(false),
  26. m_lastScale(1.0),
  27. m_ignoreFullscreenSettingsChange(0),
  28. m_showedUpdateDialog(false),
  29. m_osxPresentationOptions(0)
  30. {
  31. // NSWindowCollectionBehaviorFullScreenPrimary is only set on OSX if Qt::WindowFullscreenButtonHint is set on the window.
  32. setFlags(flags() | Qt::WindowFullscreenButtonHint);
  33. m_infoTimer = new QTimer(this);
  34. m_infoTimer->setInterval(1000);
  35. m_webDesktopMode = (SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "webMode").toString() == "desktop");
  36. installEventFilter(new EventFilter(this));
  37. connect(m_infoTimer, &QTimer::timeout, this, &KonvergoWindow::updateDebugInfo);
  38. InputComponent::Get().registerHostCommand("close", this, "close");
  39. InputComponent::Get().registerHostCommand("toggleDebug", this, "toggleDebug");
  40. InputComponent::Get().registerHostCommand("reload", this, "reloadWeb");
  41. InputComponent::Get().registerHostCommand("fullscreen", this, "toggleFullscreen");
  42. InputComponent::Get().registerHostCommand("minimize", this, "minimizeWindow");
  43. InputComponent::Get().registerHostCommand("fullscreenCurrentMode", this, "toggleFullscreenNoSwitch");
  44. #ifdef TARGET_RPI
  45. // On RPI, we use dispmanx layering - the video is on a layer below Konvergo,
  46. // and during playback the Konvergo window is partially transparent. The OSD
  47. // will be visible on top of the video as part of the Konvergo window.
  48. setColor(QColor("transparent"));
  49. #else
  50. setColor(QColor("#111111"));
  51. #endif
  52. QRect loadedGeo = loadGeometry();
  53. notifyScale(loadedGeo.size());
  54. connect(SettingsComponent::Get().getSection(SETTINGS_SECTION_MAIN), &SettingsSection::valuesUpdated,
  55. this, &KonvergoWindow::updateMainSectionSettings);
  56. connect(this, &KonvergoWindow::visibilityChanged,
  57. this, &KonvergoWindow::onVisibilityChanged);
  58. connect(this, &KonvergoWindow::enableVideoWindowSignal,
  59. this, &KonvergoWindow::enableVideoWindow, Qt::QueuedConnection);
  60. connect(&PlayerComponent::Get(), &PlayerComponent::windowVisible,
  61. this, &KonvergoWindow::playerWindowVisible);
  62. // this is using old syntax because ... reasons. QQuickCloseEvent is not public class
  63. connect(this, SIGNAL(closing(QQuickCloseEvent*)), this, SLOT(closingWindow()));
  64. connect(qApp, &QCoreApplication::aboutToQuit, this, &KonvergoWindow::closingWindow);
  65. connect(&UpdaterComponent::Get(), &UpdaterComponent::downloadComplete,
  66. this, &KonvergoWindow::showUpdateDialog);
  67. #ifdef Q_OS_MAC
  68. m_osxPresentationOptions = 0;
  69. #endif
  70. #ifdef KONVERGO_OPENELEC
  71. setVisibility(QWindow::FullScreen);
  72. #else
  73. updateWindowState(false);
  74. #endif
  75. emit enableVideoWindowSignal();
  76. }
  77. /////////////////////////////////////////////////////////////////////////////////////////
  78. void KonvergoWindow::showUpdateDialog()
  79. {
  80. if (m_webDesktopMode && !m_showedUpdateDialog)
  81. {
  82. QVariantHash updateInfo = UpdaterComponent::Get().updateInfo();
  83. QString currentVersion = Version::GetCanonicalVersionString().split("-")[0];
  84. QString newVersion = updateInfo["version"].toString().split("-")[0];
  85. QMessageBox* message = new QMessageBox(nullptr);
  86. message->setIcon(QMessageBox::Information);
  87. message->setWindowModality(Qt::ApplicationModal);
  88. message->setWindowTitle("Update found!");
  89. message->setText("An update to Plex Media Player was found");
  90. auto infoText = QString("You are currently running version %0\nDo you wish to install version %1 now?")
  91. .arg(currentVersion)
  92. .arg(newVersion);
  93. message->setInformativeText(infoText);
  94. auto details = QString("ChangeLog for version %0\n\nNew:\n%1\n\nFixed:\n%2")
  95. .arg(newVersion)
  96. .arg(updateInfo["new"].toString())
  97. .arg(updateInfo["fixed"].toString());
  98. message->setDetailedText(details);
  99. auto updateNow = message->addButton("Install Now", QMessageBox::AcceptRole);
  100. auto updateLater = message->addButton("Install on Next Restart", QMessageBox::RejectRole);
  101. message->setDefaultButton(updateNow);
  102. m_showedUpdateDialog = true;
  103. connect(message, &QMessageBox::buttonClicked, [=](QAbstractButton* button)
  104. {
  105. if (button == updateNow)
  106. UpdaterComponent::Get().doUpdate();
  107. else if (button == updateLater)
  108. message->close();
  109. message->deleteLater();
  110. });
  111. message->show();
  112. }
  113. }
  114. /////////////////////////////////////////////////////////////////////////////////////////
  115. void KonvergoWindow::closingWindow()
  116. {
  117. if (!SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "fullscreen").toBool())
  118. saveGeometry();
  119. qApp->quit();
  120. }
  121. ///////////////////////////////////////////////////////////////////////////////////////////////////
  122. KonvergoWindow::~KonvergoWindow()
  123. {
  124. DisplayComponent::Get().setApplicationWindow(nullptr);
  125. }
  126. ///////////////////////////////////////////////////////////////////////////////////////////////////
  127. bool KonvergoWindow::fitsInScreens(const QRect& rc)
  128. {
  129. for(QScreen *screen : QGuiApplication::screens())
  130. {
  131. if (screen->virtualGeometry().isValid() && screen->virtualGeometry().contains(rc))
  132. return true;
  133. }
  134. return false;
  135. }
  136. ///////////////////////////////////////////////////////////////////////////////////////////////////
  137. void KonvergoWindow::saveGeometry()
  138. {
  139. QLOG_DEBUG() << "Window state when saving geometry:" << visibility();
  140. QRect rc = geometry();
  141. // lets make sure we are not saving something craycray
  142. if (rc.size().width() < windowMinSize().width() || rc.size().height() < windowMinSize().height())
  143. return;
  144. if (!fitsInScreens(rc))
  145. return;
  146. QLOG_DEBUG() << "Saving window geometry:" << rc;
  147. QVariantMap map = {{"x", rc.x()}, {"y", rc.y()},
  148. {"width", rc.width()}, {"height", rc.height()}};
  149. SettingsComponent::Get().setValue(SETTINGS_SECTION_STATE, "geometry", map);
  150. SettingsComponent::Get().setValue(SETTINGS_SECTION_STATE, "lastUsedScreen", screen()->name());
  151. }
  152. ///////////////////////////////////////////////////////////////////////////////////////////////////
  153. QRect KonvergoWindow::loadGeometry()
  154. {
  155. QRect rc = loadGeometryRect();
  156. QScreen* myScreen = loadLastScreen();
  157. if (!myScreen)
  158. myScreen = screen();
  159. QRect nsize = rc;
  160. if (SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "fullscreen").toBool())
  161. {
  162. QLOG_DEBUG() << "Load FullScreen geo...";
  163. // On OSX we need to set the geometry to the size we want when we
  164. // return from fullscreen otherwise when we exit fullscreen it
  165. // will stay small or big. On Windows we need to set it to max
  166. // resolution for the screen (i.e. fullscreen) otherwise it will
  167. // just scale the webcontent to the minimum size we have defined
  168. //
  169. #ifndef Q_OS_MAC
  170. nsize = myScreen->geometry();
  171. #endif
  172. setGeometry(nsize);
  173. setScreen(myScreen);
  174. }
  175. else
  176. {
  177. setGeometry(nsize);
  178. saveGeometry();
  179. }
  180. return nsize;
  181. }
  182. ///////////////////////////////////////////////////////////////////////////////////////////////////
  183. QRect KonvergoWindow::loadGeometryRect()
  184. {
  185. // if we dont have anything, default to 720p in the middle of the screen
  186. QRect defaultRect = QRect((screen()->geometry().width() - WEBUI_SIZE.width()) / 2,
  187. (screen()->geometry().height() - WEBUI_SIZE.height()) / 2,
  188. WEBUI_SIZE.width(), WEBUI_SIZE.height());
  189. QVariantMap map = SettingsComponent::Get().value(SETTINGS_SECTION_STATE, "geometry").toMap();
  190. if (map.isEmpty())
  191. return defaultRect;
  192. QRect rc(map["x"].toInt(), map["y"].toInt(), map["width"].toInt(), map["height"].toInt());
  193. QLOG_DEBUG() << "Restoring geo:" << rc;
  194. if (!rc.isValid() || rc.isEmpty())
  195. {
  196. QLOG_DEBUG() << "Geo bad, going for defaults";
  197. return defaultRect;
  198. }
  199. QSize minsz = windowMinSize();
  200. // Clamp to min size if we have really small values in there
  201. if (rc.size().width() < minsz.width())
  202. rc.setWidth(minsz.width());
  203. if (rc.size().height() < minsz.height())
  204. rc.setHeight(minsz.height());
  205. // also make sure we are not putting windows outside the screen somewhere
  206. if (!fitsInScreens(rc))
  207. {
  208. QLOG_DEBUG() << "Could not fit stored geo into current screens";
  209. return defaultRect;
  210. }
  211. return rc;
  212. }
  213. ///////////////////////////////////////////////////////////////////////////////////////////////////
  214. void KonvergoWindow::enableVideoWindow()
  215. {
  216. PlayerComponent::Get().setWindow(this);
  217. DisplayComponent::Get().setApplicationWindow(this);
  218. }
  219. ///////////////////////////////////////////////////////////////////////////////////////////////////
  220. void KonvergoWindow::setFullScreen(bool enable)
  221. {
  222. QLOG_DEBUG() << "setting fullscreen = " << enable;
  223. SettingsComponent::Get().setValue(SETTINGS_SECTION_MAIN, "fullscreen", enable);
  224. }
  225. ///////////////////////////////////////////////////////////////////////////////////////////////////
  226. void KonvergoWindow::setAlwaysOnTop(bool enable)
  227. {
  228. QLOG_DEBUG() << "setting always on top = " << enable;
  229. // Update the settings value.
  230. SettingsComponent::Get().setValue(SETTINGS_SECTION_MAIN, "alwaysOnTop", enable);
  231. }
  232. ///////////////////////////////////////////////////////////////////////////////////////////////////
  233. void KonvergoWindow::playerWindowVisible(bool visible)
  234. {
  235. // adjust webengineview transparecy depending on player visibility
  236. QQuickItem *web = findChild<QQuickItem *>("web");
  237. if (web)
  238. web->setProperty("backgroundColor", visible ? "transparent" : "#111111");
  239. #ifdef Q_OS_MAC
  240. // On OSX, initializing VideoTooolbox (hardware decoder API) will mysteriously
  241. // show the hidden mouse pointer again. The VTDecompressionSessionCreate API
  242. // function does this, and we have no influence over its behavior.
  243. if (visible && !SystemComponent::Get().cursorVisible())
  244. {
  245. // "Refresh" it. (There doesn't seem to be a nicer way, and we have to do
  246. // this on the Cocoa level too.)
  247. SystemComponent::Get().setCursorVisibility(true);
  248. SystemComponent::Get().setCursorVisibility(false);
  249. }
  250. #endif
  251. }
  252. ///////////////////////////////////////////////////////////////////////////////////////////////////
  253. void KonvergoWindow::updateMainSectionSettings(const QVariantMap& values)
  254. {
  255. // update mouse visibility if needed
  256. if (values.find("disablemouse") != values.end())
  257. {
  258. SystemComponent::Get().setCursorVisibility(!SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "disablemouse").toBool());
  259. }
  260. if (values.contains("alwaysOnTop"))
  261. updateWindowState();
  262. if (values.contains("fullscreen") && !m_ignoreFullscreenSettingsChange)
  263. {
  264. InputComponent::Get().cancelAutoRepeat();
  265. updateWindowState();
  266. }
  267. if (values.contains("webMode"))
  268. {
  269. InputComponent::Get().cancelAutoRepeat();
  270. bool oldDesktopMode = m_webDesktopMode;
  271. bool newDesktopMode = (SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "webMode").toString() == "desktop");
  272. if (SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "layout").toString() != "auto")
  273. {
  274. m_webDesktopMode = newDesktopMode;
  275. emit webDesktopModeChanged();
  276. emit webUrlChanged();
  277. updateWindowState();
  278. notifyScale(size());
  279. }
  280. else
  281. {
  282. bool fullscreen = SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "fullscreen").toBool();
  283. if (oldDesktopMode && !newDesktopMode)
  284. fullscreen = true;
  285. else if (!oldDesktopMode && newDesktopMode)
  286. fullscreen = false;
  287. PlayerComponent::Get().stop();
  288. SettingsComponent::Get().setValue(SETTINGS_SECTION_MAIN, "fullscreen", fullscreen);
  289. QTimer::singleShot(0, [=]
  290. {
  291. m_webDesktopMode = newDesktopMode;
  292. emit webDesktopModeChanged();
  293. emit webUrlChanged();
  294. SystemComponent::Get().setCursorVisibility(true);
  295. updateWindowState();
  296. notifyScale(size());
  297. });
  298. }
  299. }
  300. if (values.contains("startupurl"))
  301. emit webUrlChanged();
  302. }
  303. ///////////////////////////////////////////////////////////////////////////////////////////////////
  304. void KonvergoWindow::updateWindowState(bool saveGeo)
  305. {
  306. if (SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "fullscreen").toBool() || SystemComponent::Get().isOpenELEC())
  307. {
  308. // if we were go from windowed to fullscreen
  309. // we want to store our current windowed position
  310. if (!isFullScreen() && saveGeo)
  311. saveGeometry();
  312. setVisibility(QWindow::FullScreen);
  313. }
  314. else
  315. {
  316. setVisibility(QWindow::Windowed);
  317. loadGeometry();
  318. Qt::WindowFlags forceOnTopFlags = Qt::WindowStaysOnTopHint;
  319. #ifdef Q_WS_X11
  320. forceOnTopFlags = forceOnTopFlags | Qt::X11BypassWindowManagerHint;
  321. #endif
  322. if (SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "alwaysOnTop").toBool())
  323. setFlags(flags() | forceOnTopFlags);
  324. else
  325. setFlags(flags() &~ forceOnTopFlags);
  326. }
  327. }
  328. ///////////////////////////////////////////////////////////////////////////////////////////////////
  329. class ScopedDecrementer
  330. {
  331. Q_DISABLE_COPY(ScopedDecrementer)
  332. int* m_value;
  333. public:
  334. ScopedDecrementer(int* value) : m_value(value) {}
  335. ~ScopedDecrementer() { (*m_value)--; }
  336. };
  337. ///////////////////////////////////////////////////////////////////////////////////////////////////
  338. void KonvergoWindow::onVisibilityChanged(QWindow::Visibility visibility)
  339. {
  340. QLOG_DEBUG() << "QWindow visibility set to" << visibility;
  341. if (visibility == QWindow::FullScreen || visibility == QWindow::Windowed)
  342. {
  343. m_ignoreFullscreenSettingsChange++;
  344. ScopedDecrementer decrement(&m_ignoreFullscreenSettingsChange);
  345. bool fs = visibility == QWindow::FullScreen;
  346. SettingsComponent::Get().setValue(SETTINGS_SECTION_MAIN, "fullscreen", fs);
  347. SystemComponent::Get().setCursorVisibility(false);
  348. }
  349. if (visibility == QWindow::Windowed)
  350. {
  351. #ifdef Q_OS_MAC
  352. QTimer::singleShot(1 * 1000, [&] { OSXUtils::SetPresentationOptions(m_osxPresentationOptions); });
  353. #endif
  354. }
  355. else if (visibility == QWindow::FullScreen)
  356. {
  357. #ifdef Q_OS_MAC
  358. QTimer::singleShot(1 * 1000, [&] {
  359. OSXUtils::SetPresentationOptions(m_osxPresentationOptions | OSXUtils::GetPresentationOptionsForFullscreen(!m_webDesktopMode));
  360. });
  361. #endif
  362. }
  363. if (visibility == QWindow::Minimized)
  364. InputComponent::Get().cancelAutoRepeat();
  365. notifyScale(size());
  366. }
  367. /////////////////////////////////////////////////////////////////////////////////////////
  368. void KonvergoWindow::focusOutEvent(QFocusEvent * ev)
  369. {
  370. #ifdef Q_OS_WIN32
  371. // Do this to workaround DWM compositor bugs with fullscreened OpenGL applications.
  372. // The compositor will not properly redraw anything when focusing other windows.
  373. if (visibility() == QWindow::FullScreen && SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "minimizeOnDefocus").toBool())
  374. {
  375. QLOG_DEBUG() << "minimizing window";
  376. showMinimized();
  377. }
  378. #endif
  379. }
  380. /////////////////////////////////////////////////////////////////////////////////////////
  381. void KonvergoWindow::RegisterClass()
  382. {
  383. qmlRegisterType<KonvergoWindow>("Konvergo", 1, 0, "KonvergoWindow");
  384. }
  385. /////////////////////////////////////////////////////////////////////////////////////////
  386. void KonvergoWindow::onScreenCountChanged(int newCount)
  387. {
  388. updateWindowState(false);
  389. }
  390. /////////////////////////////////////////////////////////////////////////////////////////
  391. void KonvergoWindow::updateDebugInfo()
  392. {
  393. if (m_systemDebugInfo.size() == 0)
  394. m_systemDebugInfo = SystemComponent::Get().debugInformation();
  395. m_debugInfo = m_systemDebugInfo;
  396. m_debugInfo += DisplayComponent::Get().debugInformation();
  397. PlayerQuickItem* video = findChild<PlayerQuickItem*>("video");
  398. if (video)
  399. m_debugInfo += video->debugInfo();
  400. QString infoString;
  401. QDebug info(&infoString);
  402. info << "Qt windowing info:\n";
  403. info << " FS: " << visibility() << "\n";
  404. info << " Geo: " << geometry() << "\n";
  405. for (QScreen* scr : QGuiApplication::screens())
  406. {
  407. info << " Screen" << scr->name() << scr->geometry() << "\n";
  408. }
  409. info << "\n";
  410. m_debugInfo += infoString;
  411. m_videoInfo = PlayerComponent::Get().videoInformation();
  412. emit debugInfoChanged();
  413. }
  414. /////////////////////////////////////////////////////////////////////////////////////////
  415. void KonvergoWindow::toggleDebug()
  416. {
  417. if (property("showDebugLayer").toBool())
  418. {
  419. m_infoTimer->stop();
  420. setProperty("showDebugLayer", false);
  421. }
  422. else
  423. {
  424. m_infoTimer->start();
  425. updateDebugInfo();
  426. setProperty("showDebugLayer", true);
  427. }
  428. }
  429. /////////////////////////////////////////////////////////////////////////////////////////
  430. void KonvergoWindow::notifyScale(const QSize& size)
  431. {
  432. qreal scale = CalculateScale(size);
  433. if (scale != m_lastScale)
  434. {
  435. QLOG_DEBUG() << "windowScale updated to:" << scale << "webscale:" << CalculateWebScale(size, devicePixelRatio());
  436. m_lastScale = scale;
  437. emit SystemComponent::Get().scaleChanged(CalculateWebScale(size, devicePixelRatio()));
  438. }
  439. emit webScaleChanged();
  440. }
  441. /////////////////////////////////////////////////////////////////////////////////////////
  442. void KonvergoWindow::resizeEvent(QResizeEvent* event)
  443. {
  444. QLOG_DEBUG() << "resize event:" << event->size();
  445. // This next block was added at some point to workaround a problem with
  446. // resizing on windows. Unfortunately it broke the desktop client behavior
  447. // and when retried on Windows 10 with Qt5.7 the original bug seems to be
  448. // gone. I'll keep this code around until such a time that we dont get any
  449. // complaints about it.
  450. //
  451. #if 0
  452. // This next block should never really be needed in a prefect world...
  453. // Unfortunatly this is an imperfect world and on windows sometimes what
  454. // would happen on startup is that we got a resize event that would make
  455. // the window much smaller than fullscreen.
  456. //
  457. if (isFullScreen())
  458. {
  459. QSize fsSize = screen()->size();
  460. if (event->size().width() < fsSize.width() || event->size().height() < fsSize.height())
  461. {
  462. QLOG_DEBUG() << "Ignoring resize event when in fullscreen...";
  463. return;
  464. }
  465. }
  466. #endif
  467. notifyScale(event->size());
  468. QQuickWindow::resizeEvent(event);
  469. }
  470. /////////////////////////////////////////////////////////////////////////////////////////
  471. #define ROUND(x) (qRound(x * 1000) / 1000.0)
  472. /////////////////////////////////////////////////////////////////////////////////////////
  473. qreal KonvergoWindow::CalculateScale(const QSize& size)
  474. {
  475. qreal horizontalScale = (qreal)size.width() / (qreal)WEBUI_SIZE.width();
  476. qreal verticalScale = (qreal)size.height() / (qreal)WEBUI_SIZE.height();
  477. return ROUND(qMin(horizontalScale, verticalScale));
  478. }
  479. /////////////////////////////////////////////////////////////////////////////////////////
  480. qreal KonvergoWindow::CalculateWebScale(const QSize& size, qreal devicePixelRatio)
  481. {
  482. qreal horizontalScale = (qreal)size.width() / (qreal)WEBUI_SIZE.width();
  483. qreal verticalScale = (qreal)size.height() / (qreal)WEBUI_SIZE.height();
  484. qreal minScale = qMin(horizontalScale, qMin(verticalScale, (qreal)(WEBUI_MAX_HEIGHT / devicePixelRatio) / (qreal)WEBUI_SIZE.height()));
  485. qreal minWinScale = 240.0 / (qreal)WEBUI_SIZE.height();
  486. return ROUND(qMax(minWinScale, minScale));
  487. }
  488. /////////////////////////////////////////////////////////////////////////////////////////
  489. QScreen* KonvergoWindow::loadLastScreen()
  490. {
  491. QString screenName = SettingsComponent::Get().value(SETTINGS_SECTION_STATE, "lastUsedScreen").toString();
  492. if (screenName.isEmpty())
  493. return nullptr;
  494. for (QScreen* scr : QGuiApplication::screens())
  495. {
  496. if (scr->name() == screenName)
  497. return scr;
  498. }
  499. QLOG_DEBUG() << "Tried to find screen:" << screenName << "but it was not present";
  500. return nullptr;
  501. }
  502. /////////////////////////////////////////////////////////////////////////////////////////
  503. QString KonvergoWindow::webUrl()
  504. {
  505. auto url = SettingsComponent::Get().getWebClientUrl(m_webDesktopMode);
  506. if (m_webDesktopMode)
  507. return url;
  508. return url + QString("?initialScale=%0").arg(webScale());
  509. }