X11: remove polling for connected outputs, use xrr events
authorRainer Hochecker <fernetmenta@online.de>
Tue, 29 Oct 2013 19:57:59 +0000 (20:57 +0100)
committerRainer Hochecker <fernetmenta@online.de>
Tue, 29 Apr 2014 10:31:42 +0000 (12:31 +0200)
xbmc/windowing/WinEventsX11.cpp
xbmc/windowing/WinEventsX11.h
xbmc/windowing/X11/WinSystemX11.cpp
xbmc/windowing/X11/WinSystemX11.h

index 3a775fc..0b8bba5 100644 (file)
@@ -213,7 +213,6 @@ bool CWinEventsX11Imp::Init(Display *dpy, Window win)
   WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
   WinEvents->m_structureChanged = false;
   WinEvents->m_xrrEventPending = false;
-  WinEvents->m_xrrPollTimer.Set(3000);
 
   // open input method
   char *old_locale = NULL, *old_modifiers = NULL;
@@ -280,7 +279,11 @@ bool CWinEventsX11Imp::Init(Display *dpy, Window win)
 #if defined(HAS_XRANDR)
   int iReturn;
   XRRQueryExtension(WinEvents->m_display, &WinEvents->m_RREventBase, &iReturn);
-  XRRSelectInput(WinEvents->m_display, WinEvents->m_window, RRScreenChangeNotifyMask);
+  int numScreens = XScreenCount(WinEvents->m_display);
+  for (int i = 0; i < numScreens; i++)
+  {
+    XRRSelectInput(WinEvents->m_display, RootWindow(WinEvents->m_display, i), RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask | RROutputChangeNotifyMask | RROutputPropertyNotifyMask);
+  }
 #endif
 
   return true;
@@ -328,6 +331,26 @@ bool CWinEventsX11Imp::MessagePump()
     memset(&xevent, 0, sizeof (XEvent));
     XNextEvent(WinEvents->m_display, &xevent);
 
+#if defined(HAS_XRANDR)
+    if (WinEvents && (xevent.type == WinEvents->m_RREventBase + RRScreenChangeNotify))
+    {
+      XRRUpdateConfiguration(&xevent);
+      if (xevent.xgeneric.serial != serial)
+        g_Windowing.NotifyXRREvent();
+      WinEvents->m_xrrEventPending = false;
+      serial = xevent.xgeneric.serial;
+      continue;
+    }
+    else if (WinEvents && (xevent.type == WinEvents->m_RREventBase + RRNotify))
+    {
+      if (xevent.xgeneric.serial != serial)
+        g_Windowing.NotifyXRREvent();
+      WinEvents->m_xrrEventPending = false;
+      serial = xevent.xgeneric.serial;
+      continue;
+    }
+#endif
+
     if (XFilterEvent(&xevent, WinEvents->m_window))
       continue;
 
@@ -575,18 +598,6 @@ bool CWinEventsX11Imp::MessagePump()
         break;
       }
     }// switch event.type
-
-#if defined(HAS_XRANDR)
-    if (WinEvents && (xevent.type == WinEvents->m_RREventBase + RRScreenChangeNotify))
-    {
-      XRRUpdateConfiguration(&xevent);
-      if (xevent.xgeneric.serial != serial)
-        g_Windowing.NotifyXRREvent();
-      WinEvents->m_xrrEventPending = false;
-      serial = xevent.xgeneric.serial;
-    }
-#endif
-
   }// while
 
 #if defined(HAS_XRANDR)
@@ -596,11 +607,6 @@ bool CWinEventsX11Imp::MessagePump()
     g_Windowing.NotifyXRREvent();
     WinEvents->m_xrrEventPending = false;
   }
-  else if (!g_application.m_pPlayer->IsPlaying() && WinEvents && WinEvents->m_xrrPollTimer.IsTimePast())
-  {
-    g_Windowing.NotifyXRREvent(true);
-    WinEvents->m_xrrPollTimer.Set(3000);
-  }
 #endif
 
 #ifdef HAS_SDL_JOYSTICK
index 91a604f..6429291 100644 (file)
@@ -62,6 +62,5 @@ protected:
   bool m_structureChanged;
   int m_RREventBase;
   XbmcThreads::EndTime m_xrrFailSafeTimer;
-  XbmcThreads::EndTime m_xrrPollTimer;
   bool m_xrrEventPending;
 };
index a247733..f806ac2 100644 (file)
@@ -168,8 +168,21 @@ bool CWinSystemX11::DestroyWindow()
 
 bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop)
 {
+  m_userOutput = CSettings::Get().GetString("videoscreen.monitor");
+  if (m_userOutput.compare("Default") == 0)
+  {
+    std::vector<XOutput> outputs = g_xrandr.GetModes();
+    if (outputs.size() > 0)
+    {
+      m_userOutput = outputs[0].name;
+    }
+  }
+
+  m_userOutput = g_xrandr.GetModes()[0].name;
+
   if(m_nWidth  == newWidth
-  && m_nHeight == newHeight)
+  && m_nHeight == newHeight
+  && m_userOutput.compare(m_currentOutput) == 0)
     return true;
 
   if (!SetWindow(newWidth, newHeight, false, m_userOutput))
@@ -255,33 +268,23 @@ void CWinSystemX11::UpdateResolutions()
 
   bool switchOnOff = CSettings::Get().GetBool("videoscreen.blankdisplays");
   m_userOutput = CSettings::Get().GetString("videoscreen.monitor");
-  if (m_userOutput.Equals("Default"))
+  if (m_userOutput.compare("Default") == 0)
     switchOnOff = false;
 
   if(g_xrandr.Query(true, !switchOnOff))
   {
-    // check if the monitor is connected
-    // might take a while when connected to a receiver
-    XbmcThreads::EndTime timeout(3000);
     XOutput *out = NULL;
-    while (!m_userOutput.Equals("Default") && !timeout.IsTimePast())
+    if (m_userOutput.compare("Default") != 0)
     {
       out = g_xrandr.GetOutput(m_userOutput);
       if (out)
       {
         XMode mode = g_xrandr.GetCurrentMode(m_userOutput);
-        if (mode.isCurrent || switchOnOff)
-          break;
-        else
+        if (!mode.isCurrent && !switchOnOff)
         {
           out = NULL;
-          break;
         }
       }
-
-      Sleep(500);
-      if (!g_xrandr.Query(true, !switchOnOff))
-        break;
     }
     if (!out)
     {
@@ -289,17 +292,16 @@ void CWinSystemX11::UpdateResolutions()
       out = g_xrandr.GetOutput(m_userOutput);
     }
 
-    // switch on output
-    if(switchOnOff)
-      g_xrandr.TurnOnOutput(m_userOutput);
-
-    // switch off other outputs if desired
     if (switchOnOff)
     {
+      // switch on output
+      g_xrandr.TurnOnOutput(m_userOutput);
+
+      // switch off other outputs
       std::vector<XOutput> outputs = g_xrandr.GetModes();
       for (int i=0; i<outputs.size(); i++)
       {
-        if (outputs[i].name.Equals(m_userOutput))
+        if (outputs[i].name.Equals(m_userOutput.c_str()))
           continue;
         g_xrandr.TurnOffOutput(outputs[i].name);
       }
@@ -437,7 +439,7 @@ void CWinSystemX11::GetConnectedOutputs(std::vector<CStdString> *outputs)
 
 bool CWinSystemX11::IsCurrentOutput(CStdString output)
 {
-  return output.Equals("Default") || m_currentOutput.Equals(output);
+  return (output.Equals("Default")) || (m_currentOutput.compare(output) == 0);
 }
 
 bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo)
@@ -715,34 +717,14 @@ void CWinSystemX11::CheckDisplayEvents()
 #endif
 }
 
-void CWinSystemX11::NotifyXRREvent(bool poll)
+void CWinSystemX11::NotifyXRREvent()
 {
-  // we may not get an event if desired monitor becomes available
-  // hence we need to poll
-  if (poll)
-  {
-    CStdString output = CSettings::Get().GetString("videoscreen.monitor");
-    if (output.Equals(m_currentOutput) || output.Equals("Default"))
-      return;
-
-    int numScreens = XScreenCount(m_dpy);
-    g_xrandr.SetNumScreens(numScreens);
-    g_xrandr.Query(true);
-    if (!g_xrandr.IsOutputConnected(output))
-      return;
-
-    // if output is turned off by user, respect it
-    XMode mode = g_xrandr.GetCurrentMode(output);
-    if (!mode.isCurrent)
-      return;
-  }
-
-  CLog::Log(LOGDEBUG, "%s - notify display reset event, poll: %d", __FUNCTION__, poll);
+  CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__);
   m_windowDirty = true;
 
   CSingleLock lock(g_graphicsContext);
 
-  if (!g_xrandr.Query(!poll))
+  if (!g_xrandr.Query(true))
   {
     CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr");
     return;
@@ -839,14 +821,14 @@ bool CWinSystemX11::EnableFrameLimiter()
   return m_minimized;
 }
 
-bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStdString &output)
+bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const std::string &output)
 {
   bool changeWindow = false;
   bool changeSize = false;
   bool mouseActive = false;
   float mouseX, mouseY;
 
-  if (m_mainWindow && ((m_bFullScreen != fullscreen) || !m_currentOutput.Equals(output) || m_windowDirty))
+  if (m_mainWindow && ((m_bFullScreen != fullscreen) || m_currentOutput.compare(output) != 0 || m_windowDirty))
   {
     mouseActive = g_Mouse.IsActive();
     if (mouseActive)
@@ -1035,7 +1017,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
       m_bIsGrabbed = false;
 
     CDirtyRegionList dr;
-    RefreshGlxContext(!m_currentOutput.Equals(output));
+    RefreshGlxContext(m_currentOutput.compare(output) != 0);
     XSync(m_dpy, FALSE);
     g_graphicsContext.Clear(0);
     g_graphicsContext.Flip(dr);
index 7777453..dcec946 100644 (file)
@@ -69,7 +69,7 @@ public:
   Display*  GetDisplay() { return m_dpy; }
   GLXWindow GetWindow() { return m_glWindow; }
   GLXContext GetGlxContext() { return m_glContext; }
-  void NotifyXRREvent(bool poll = false);
+  void NotifyXRREvent();
   void GetConnectedOutputs(std::vector<CStdString> *outputs);
   bool IsCurrentOutput(CStdString output);
   void NotifyMouseCoverage(bool covered);
@@ -78,7 +78,7 @@ protected:
   bool RefreshGlxContext(bool force);
   void CheckDisplayEvents();
   void OnLostDevice();
-  bool SetWindow(int width, int height, bool fullscreen, const CStdString &output);
+  bool SetWindow(int width, int height, bool fullscreen, const std::string &output);
 
   Window       m_glWindow, m_mainWindow;
   GLXContext   m_glContext;
@@ -94,8 +94,8 @@ protected:
   CCriticalSection             m_resourceSection;
   std::vector<IDispResource*>  m_resources;
   uint64_t                     m_dpyLostTime;
-  CStdString                   m_currentOutput;
-  CStdString                   m_userOutput;
+  std::string                  m_currentOutput;
+  std::string                  m_userOutput;
   bool                         m_windowDirty;
   bool                         m_bIsInternalXrr;
   bool                         m_newGlContext;