MythTV  master
mythxdisplay.cpp
Go to the documentation of this file.
1 // MythTV
2 #include "config.h"
3 #include "mythlogging.h"
4 #include "mythuihelper.h"
5 #include "mythxdisplay.h"
6 
7 // Std
8 #include <map>
9 #include <vector>
10 
11 using XErrorCallbackType = int (*)(Display *, XErrorEvent *);
12 using XErrorVectorType = std::vector<XErrorEvent>;
13 static std::map<Display*, XErrorVectorType> xerrors;
14 static std::map<Display*, XErrorCallbackType> xerror_handlers;
15 
17 
18 static int ErrorHandler(Display *d, XErrorEvent *xeev)
19 {
20  xerrors[d].push_back(*xeev);
21  return 0;
22 }
23 
25 {
26  public:
27  explicit MythXLocker(MythXDisplay* Disp)
28  : m_disp(Disp)
29  {
30  if (m_disp)
31  m_disp->Lock();
32  }
33 
35  {
36  if (m_disp)
37  m_disp->Unlock();
38  }
39 
40  private:
41  MythXDisplay *m_disp { nullptr };
42 };
43 
45 {
46  auto *disp = new MythXDisplay();
47  if (disp && disp->Open())
48  return disp;
49 
50  if (Warn)
51  LOG(VB_GENERAL, LOG_CRIT, "MythXOpenDisplay() failed");
52  delete disp;
53  return nullptr;
54 }
55 
56 void MythXDisplay::SetQtX11Display(const QString &_Display)
57 {
58  s_QtX11Display = _Display;
59 }
60 
63 {
64  bool result = false;
65  auto * display = MythXDisplay::OpenMythXDisplay(false);
66 
67  if (display)
68  {
69  QString displayname(DisplayString(display->GetDisplay()));
70 
71  // DISPLAY=:x or DISPLAY=unix:x are local
72  // DISPLAY=hostname:x is remote
73  // DISPLAY=/xxx/xxx/.../org.macosforge.xquartz:x is local OS X
74  // x can be numbers n or n.n
75  // Anything else including DISPLAY not set is assumed local,
76  // in that case we are probably not running under X11
77  if (!displayname.isEmpty() && !displayname.startsWith(":") &&
78  !displayname.startsWith("unix:") && !displayname.startsWith("/") &&
79  displayname.contains(':'))
80  {
81  result = true;
82  }
83 
84  delete display;
85  }
86 
87  return result;
88 }
89 
91 {
92  MythXLocker locker(this);
93  if (m_disp)
94  {
95  StopLog();
96  XCloseDisplay(m_disp);
97  m_disp = nullptr;
98  }
99 }
100 
114 {
115  MythXLocker locker(this);
116 
118  const char *dispCStr = nullptr;
119  if (!m_displayName.isEmpty())
120  dispCStr = m_displayName.toLatin1().constData();
121 
122  m_disp = XOpenDisplay(dispCStr);
123  if (!m_disp)
124  return false;
125 
126  m_screenNum = DefaultScreen(m_disp);
127  m_screen = DefaultScreenOfDisplay(m_disp);
128  m_depth = DefaultDepthOfScreen(m_screen);
129  m_root = DefaultRootWindow(m_disp);
130 
131  return true;
132 }
133 
140 {
141  MythXLocker locker(this);
142  int displayWidthMM = DisplayWidthMM( m_disp, m_screenNum);
143  int displayHeightMM = DisplayHeightMM(m_disp, m_screenNum);
144  return { displayWidthMM, displayHeightMM };
145 }
146 
147 void MythXDisplay::Sync(bool Flush)
148 {
149  XLOCK(this, XSync(m_disp, Flush));
150 }
151 
153 {
154  if (!m_disp || xerror_handlers.count(m_disp))
155  return;
156 
157  Sync();
158  XLOCK(this, xerror_handlers[m_disp] = XSetErrorHandler(ErrorHandler));
159 }
160 
162 {
163  if (!(m_disp && xerror_handlers.count(m_disp)))
164  return false;
165 
166  Sync();
168  XLOCK(this, XSetErrorHandler(old_handler));
169  xerror_handlers.erase(m_disp);
170  return CheckErrors();
171 }
172 
173 bool MythXDisplay::CheckErrors(Display *Disp)
174 {
175  if (!Disp)
177 
178  Display *d = Disp ? Disp : m_disp;
179  if (!d)
180  return false;
181 
182  if (!xerrors.count(d))
183  return true;
184 
185  MythXLocker locker(this);
186  Sync();
187  const std::vector<XErrorEvent>& events = xerrors[d];
188 
189  if (events.empty())
190  return true;
191 
192  for (const auto & event : events)
193  {
194  std::string buf(200,'\0');
195  XGetErrorText(d, event.error_code, buf.data(), buf.size());
196  LOG(VB_GENERAL, LOG_ERR,
197  QString("XError type: %1\nSerial no: %2\nErr code: %3 (%4)\n"
198  "Req code: %5\nmMinor code: %6\nResource id: %7\n")
199  .arg(event.type).arg(event.serial)
200  .arg(event.error_code).arg(buf.data())
201  .arg(event.request_code).arg(event.minor_code)
202  .arg(event.resourceid));
203  }
204  xerrors.erase(d);
205  return false;
206 }
207 
209 {
210  if (xerrors.empty())
211  return;
212 
213  for (auto & xerror : xerrors)
214  if (!xerror_handlers.count(xerror.first))
215  CheckErrors(xerror.first);
216 }
MythXDisplay::StopLog
bool StopLog(void)
Definition: mythxdisplay.cpp:161
MythXLocker
Definition: mythxdisplay.cpp:25
MythXLocker::MythXLocker
MythXLocker(MythXDisplay *Disp)
Definition: mythxdisplay.cpp:27
MythXDisplay::~MythXDisplay
~MythXDisplay()
Definition: mythxdisplay.cpp:90
MythXDisplay::Open
bool Open(void)
Open the display.
Definition: mythxdisplay.cpp:113
MythXDisplay::m_screen
Screen * m_screen
Definition: mythxdisplay.h:52
xerrors
static std::map< Display *, XErrorVectorType > xerrors
Definition: mythxdisplay.cpp:13
MythXDisplay::m_displayName
QString m_displayName
Definition: mythxdisplay.h:56
MythXDisplay::SetQtX11Display
static void SetQtX11Display(const QString &Display)
Definition: mythxdisplay.cpp:56
MythXDisplay::m_disp
Display * m_disp
Definition: mythxdisplay.h:50
arg
arg(title).arg(filename).arg(doDelete))
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythXLocker::m_disp
MythXDisplay * m_disp
Definition: mythxdisplay.cpp:41
MythXDisplay::MythXDisplay
MythXDisplay()=default
MythXDisplay::OpenMythXDisplay
static MythXDisplay * OpenMythXDisplay(bool Warn=true)
Definition: mythxdisplay.cpp:44
MythXDisplay::m_root
Window m_root
Definition: mythxdisplay.h:54
mythlogging.h
MythXDisplay::StartLog
void StartLog(void)
Definition: mythxdisplay.cpp:152
MythXDisplay::CheckOrphanedErrors
void CheckOrphanedErrors(void)
Definition: mythxdisplay.cpp:208
MythXDisplay::m_depth
int m_depth
Definition: mythxdisplay.h:53
MythXDisplay::Unlock
void Unlock(void)
Definition: mythxdisplay.h:35
ErrorHandler
static int ErrorHandler(Display *d, XErrorEvent *xeev)
Definition: mythxdisplay.cpp:18
MythXDisplay::s_QtX11Display
static QString s_QtX11Display
Definition: mythxdisplay.h:48
MythXDisplay::CheckErrors
bool CheckErrors(Display *Disp=nullptr)
Definition: mythxdisplay.cpp:173
XErrorCallbackType
int(*)(Display *, XErrorEvent *) XErrorCallbackType
Definition: mythxdisplay.cpp:11
mythxdisplay.h
xerror_handlers
static std::map< Display *, XErrorCallbackType > xerror_handlers
Definition: mythxdisplay.cpp:14
mythuihelper.h
MythXDisplay::Sync
void Sync(bool Flush=false)
Definition: mythxdisplay.cpp:147
MythXLocker::~MythXLocker
~MythXLocker()
Definition: mythxdisplay.cpp:34
MythXDisplay::m_screenNum
int m_screenNum
Definition: mythxdisplay.h:51
MythXDisplay::DisplayIsRemote
static bool DisplayIsRemote(void)
Determine if we are running a remote X11 session.
Definition: mythxdisplay.cpp:62
XErrorVectorType
std::vector< XErrorEvent > XErrorVectorType
Definition: mythxdisplay.cpp:12
MythXDisplay
Definition: mythxdisplay.h:22
MythXDisplay::Lock
void Lock(void)
Definition: mythxdisplay.h:34
MythXDisplay::GetDisplayDimensions
QSize GetDisplayDimensions(void)
Return the size of the X Display in millimeters.
Definition: mythxdisplay.cpp:139
d
static const iso6937table * d
Definition: iso6937tables.cpp:1025
XLOCK
#define XLOCK(dpy, arg)
Definition: mythxdisplay.h:19