Browse Source

KonvergoWindow: fix QML change notifications

The old code probably didn't miss any change notifications, but it sent
too many of them. QML won't figure out property changes on its own, and
might recompute property bindings on every change notification. I
suspect this caused "binding loops" and crashes. (I wasn't able to
reproduce them. There is no doubt binding loops happen, and they are
most likely responsible for crashes we are seeing.)

Make change notifications fine-grained for every relevant property. Most
of these are for the web scaling nightmare, and thus are size-dependent.
Some also depend on the web mode (TV vs. desktop), but the commit moves
this dependency into the .qml, which makes this much easier.

The webUrl property remains a bit "dangerous", because the initialScale
parameter takes a snapshot value. Re-reading the webUrl property might
return a different value at runtime, but we do _not_ want to have a
proper change notification, as that would make the WebEngine element
reload the URL. We don't want to reload web-client only because it's
resized. I'm hoping to get rid of the initialScale URL parameter
completely. Currently it's definitely needed.
Vincent Lang 8 years ago
parent
commit
a655e7735e
3 changed files with 72 additions and 51 deletions
  1. 56 34
      src/ui/KonvergoWindow.cpp
  2. 14 15
      src/ui/KonvergoWindow.h
  3. 2 2
      src/ui/webview.qml

+ 56 - 34
src/ui/KonvergoWindow.cpp

@@ -25,7 +25,7 @@
 KonvergoWindow::KonvergoWindow(QWindow* parent) :
 KonvergoWindow::KonvergoWindow(QWindow* parent) :
   QQuickWindow(parent),
   QQuickWindow(parent),
   m_debugLayer(false),
   m_debugLayer(false),
-  m_lastWindowScale(-1), m_lastWebScale(-1),
+  m_lastWindowScale(-1), m_lastWebScale(-1), m_tvUIw(-1), m_tvUIh(-1),
   m_ignoreFullscreenSettingsChange(0),
   m_ignoreFullscreenSettingsChange(0),
   m_showedUpdateDialog(false),
   m_showedUpdateDialog(false),
   m_osxPresentationOptions(0)
   m_osxPresentationOptions(0)
@@ -58,8 +58,7 @@ KonvergoWindow::KonvergoWindow(QWindow* parent) :
 #endif
 #endif
 
 
   QRect loadedGeo = loadGeometry();
   QRect loadedGeo = loadGeometry();
-  notifyScale(loadedGeo.size());
-  emit webScaleChanged();
+  updateSizeDependendProperties(loadedGeo.size());
 
 
   connect(SettingsComponent::Get().getSection(SETTINGS_SECTION_MAIN), &SettingsSection::valuesUpdated,
   connect(SettingsComponent::Get().getSection(SETTINGS_SECTION_MAIN), &SettingsSection::valuesUpdated,
           this, &KonvergoWindow::updateMainSectionSettings);
           this, &KonvergoWindow::updateMainSectionSettings);
@@ -363,37 +362,44 @@ void KonvergoWindow::updateMainSectionSettings(const QVariantMap& values)
 
 
     if (SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "layout").toString() != "auto")
     if (SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "layout").toString() != "auto")
     {
     {
-      m_webDesktopMode = newDesktopMode;
-      emit webDesktopModeChanged();
-      emit webUrlChanged();
-      emit webScaleChanged();
+      if (oldDesktopMode != newDesktopMode)
+      {
+        PlayerComponent::Get().stop();
+        m_webDesktopMode = newDesktopMode;
+        emit webDesktopModeChanged();
+        emit webUrlChanged();
+      }
     }
     }
     else
     else
     {
     {
-      bool fullscreen = SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "fullscreen").toBool();
+      bool oldFullscreen = SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "fullscreen").toBool();
+      bool newFullscreen = oldFullscreen;
 
 
       if (oldDesktopMode && !newDesktopMode)
       if (oldDesktopMode && !newDesktopMode)
-        fullscreen = true;
+        newFullscreen = true;
       else if (!oldDesktopMode && newDesktopMode)
       else if (!oldDesktopMode && newDesktopMode)
-        fullscreen = false;
+        newFullscreen = false;
 
 
-      PlayerComponent::Get().stop();
+      if (oldFullscreen != newFullscreen)
+        SettingsComponent::Get().setValue(SETTINGS_SECTION_MAIN, "fullscreen", newFullscreen);
 
 
-      SettingsComponent::Get().setValue(SETTINGS_SECTION_MAIN, "fullscreen", fullscreen);
-      QTimer::singleShot(0, [=]
+      if (oldDesktopMode != newDesktopMode)
       {
       {
-        m_webDesktopMode = newDesktopMode;
-        auto s = size();
-        QLOG_DEBUG() << "compute scale for mode switch" << s;
-        notifyScale(s);
-        emit webDesktopModeChanged();
-        emit webUrlChanged();
-        emit webScaleChanged();
-
-        if (m_webDesktopMode)
-          SystemComponent::Get().setCursorVisibility(true);
-        updateWindowState();
-      });
+        QTimer::singleShot(0, [=]
+        {
+          PlayerComponent::Get().stop();
+          m_webDesktopMode = newDesktopMode;
+          auto s = size();
+          QLOG_DEBUG() << "compute scale for mode switch" << s;
+          updateSizeDependendProperties(s);
+          emit webDesktopModeChanged();
+          emit webUrlChanged();
+
+          if (m_webDesktopMode)
+            SystemComponent::Get().setCursorVisibility(true);
+          updateWindowState();
+        });
+      }
     }
     }
   }
   }
 
 
@@ -546,8 +552,7 @@ void KonvergoWindow::onVisibilityChanged(QWindow::Visibility visibility)
 #endif
 #endif
 
 
   InputComponent::Get().cancelAutoRepeat();
   InputComponent::Get().cancelAutoRepeat();
-  notifyScale(size());
-  emit webScaleChanged();
+  updateSizeDependendProperties(size());
 }
 }
 
 
 /////////////////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////////////////
@@ -625,17 +630,35 @@ void KonvergoWindow::toggleDebug()
 }
 }
 
 
 /////////////////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////////////////
-void KonvergoWindow::notifyScale(const QSize& size)
+void KonvergoWindow::updateSizeDependendProperties(const QSize& size)
 {
 {
   qreal windowScale = CalculateScale(size);
   qreal windowScale = CalculateScale(size);
-  qreal webScale = CalculateWebScale(size, devicePixelRatio());
-  if (windowScale != m_lastWindowScale || webScale != m_lastWebScale)
+  if (windowScale != m_lastWindowScale)
   {
   {
-    QLOG_DEBUG() << "windowScale updated to:" << windowScale << "webscale:" << webScale;
-
     m_lastWindowScale = windowScale;
     m_lastWindowScale = windowScale;
+    emit windowScaleChanged();
+  }
+
+  qreal webScale = CalculateWebScale(size, devicePixelRatio());
+  if (webScale != m_lastWebScale)
+  {
     m_lastWebScale = webScale;
     m_lastWebScale = webScale;
     emit SystemComponent::Get().updateScale(webScale);
     emit SystemComponent::Get().updateScale(webScale);
+    emit webScaleChanged();
+  }
+
+  qreal tvW = qRound64(qMin((qreal)(size.height() * 16) / 9, (qreal)size.width()));
+  if (tvW != m_tvUIw)
+  {
+    m_tvUIw = tvW;
+    emit tvUIWidthChanged();
+  }
+
+  qreal tvH = qRound64(qMin((qreal)(size.width() * 9) / 16, (qreal)size.height()));
+  if (tvH != m_tvUIh)
+  {
+    m_tvUIh = tvH;
+    emit tvUIHeightChanged();
   }
   }
 }
 }
 
 
@@ -668,8 +691,7 @@ void KonvergoWindow::resizeEvent(QResizeEvent* event)
   }
   }
   #endif
   #endif
 
 
-  notifyScale(event->size());
-  emit webScaleChanged();
+  updateSizeDependendProperties(event->size());
   QQuickWindow::resizeEvent(event);
   QQuickWindow::resizeEvent(event);
 }
 }
 
 

+ 14 - 15
src/ui/KonvergoWindow.h

@@ -30,14 +30,14 @@ class KonvergoWindow : public QQuickWindow
   Q_PROPERTY(QString debugInfo MEMBER m_debugInfo NOTIFY debugInfoChanged)
   Q_PROPERTY(QString debugInfo MEMBER m_debugInfo NOTIFY debugInfoChanged)
   Q_PROPERTY(QString videoInfo MEMBER m_videoInfo NOTIFY debugInfoChanged)
   Q_PROPERTY(QString videoInfo MEMBER m_videoInfo NOTIFY debugInfoChanged)
   Q_PROPERTY(qreal webScale READ webScale NOTIFY webScaleChanged)
   Q_PROPERTY(qreal webScale READ webScale NOTIFY webScaleChanged)
-  Q_PROPERTY(qreal webHeightMax READ webHeightMax NOTIFY webScaleChanged)
-  Q_PROPERTY(qreal windowScale READ windowScale NOTIFY webScaleChanged)
-  Q_PROPERTY(QSize windowMinSize READ windowMinSize NOTIFY webScaleChanged)
+  Q_PROPERTY(qreal webHeightMax READ webHeightMax)
+  Q_PROPERTY(qreal windowScale READ windowScale NOTIFY windowScaleChanged)
+  Q_PROPERTY(QSize windowMinSize READ windowMinSize)
   Q_PROPERTY(bool alwaysOnTop READ isAlwaysOnTop WRITE setAlwaysOnTop)
   Q_PROPERTY(bool alwaysOnTop READ isAlwaysOnTop WRITE setAlwaysOnTop)
   Q_PROPERTY(bool webDesktopMode MEMBER m_webDesktopMode NOTIFY webDesktopModeChanged)
   Q_PROPERTY(bool webDesktopMode MEMBER m_webDesktopMode NOTIFY webDesktopModeChanged)
   Q_PROPERTY(QString webUrl READ webUrl NOTIFY webUrlChanged)
   Q_PROPERTY(QString webUrl READ webUrl NOTIFY webUrlChanged)
-  Q_PROPERTY(qreal webUIWidth READ webUIWidth NOTIFY webScaleChanged)
-  Q_PROPERTY(qreal webUIHeight READ webUIHeight NOTIFY webScaleChanged)
+  Q_PROPERTY(qreal tvUIWidth READ tvUIWidth NOTIFY tvUIWidthChanged)
+  Q_PROPERTY(qreal tvUIHeight READ tvUIHeight NOTIFY tvUIHeightChanged)
 
 
 public:
 public:
   static void RegisterClass();
   static void RegisterClass();
@@ -97,29 +97,28 @@ public:
   QSize windowMinSize() { return WINDOWW_MIN_SIZE; }
   QSize windowMinSize() { return WINDOWW_MIN_SIZE; }
   QString webUrl();
   QString webUrl();
 
 
-  qreal webUIWidth()
+  qreal tvUIWidth()
   {
   {
-    if (!m_webDesktopMode)
-      return qRound64(qMin((qreal)(height() * 16) / 9, (qreal)width()));
-    return width();
+    return m_tvUIw;
   }
   }
 
 
-  qreal webUIHeight()
+  qreal tvUIHeight()
   {
   {
-    if (!m_webDesktopMode)
-      return qRound64(qMin((qreal)(width() * 9) / 16, (qreal)height()));
-    return height();
+    return m_tvUIh;
   }
   }
 
 
 Q_SIGNALS:
 Q_SIGNALS:
   void fullScreenSwitched();
   void fullScreenSwitched();
   void webScaleChanged();
   void webScaleChanged();
+  void windowScaleChanged();
   void enableVideoWindowSignal();
   void enableVideoWindowSignal();
   void debugLayerChanged();
   void debugLayerChanged();
   void debugInfoChanged();
   void debugInfoChanged();
   void reloadWebClient();
   void reloadWebClient();
   void webDesktopModeChanged();
   void webDesktopModeChanged();
   void webUrlChanged();
   void webUrlChanged();
+  void tvUIWidthChanged();
+  void tvUIHeightChanged();
 
 
 protected:
 protected:
   void focusOutEvent(QFocusEvent* ev) override;
   void focusOutEvent(QFocusEvent* ev) override;
@@ -139,7 +138,7 @@ private slots:
   void updateCurrentScreen();
   void updateCurrentScreen();
 
 
 private:
 private:
-  void notifyScale(const QSize& size);
+  void updateSizeDependendProperties(const QSize& size);
   void saveGeometry();
   void saveGeometry();
   QRect loadGeometry();
   QRect loadGeometry();
   QRect loadGeometryRect();
   QRect loadGeometryRect();
@@ -150,7 +149,7 @@ private:
   QScreen* findCurrentScreen();
   QScreen* findCurrentScreen();
 
 
   bool m_debugLayer;
   bool m_debugLayer;
-  qreal m_lastWindowScale, m_lastWebScale;
+  qreal m_lastWindowScale, m_lastWebScale, m_tvUIw, m_tvUIh;
   QTimer* m_infoTimer;
   QTimer* m_infoTimer;
   QString m_debugInfo, m_systemDebugInfo, m_videoInfo;
   QString m_debugInfo, m_systemDebugInfo, m_videoInfo;
   int m_ignoreFullscreenSettingsChange;
   int m_ignoreFullscreenSettingsChange;

+ 2 - 2
src/ui/webview.qml

@@ -153,8 +153,8 @@ KonvergoWindow
     focus: true
     focus: true
     property string currentHoveredUrl: ""
     property string currentHoveredUrl: ""
     onLinkHovered: web.currentHoveredUrl = hoveredUrl
     onLinkHovered: web.currentHoveredUrl = hoveredUrl
-    width: mainWindow.webUIWidth
-    height: mainWindow.webUIHeight
+    width: mainWindow.webDesktopMode ? mainWindow.width : mainWindow.tvUIWidth
+    height: mainWindow.webDesktopMode ? mainWindow.height : mainWindow.tvUIHeight
 
 
     scale:
     scale:
     {
     {