00001
00002 #include <map>
00003 #include <vector>
00004 using namespace std;
00005
00006 #include "config.h"
00007 #include "mythcontext.h"
00008
00009 QMutex x11_lock;
00010
00011 #ifdef USING_X11
00012 #include "util-x11.h"
00013 extern "C" {
00014 #include <X11/extensions/Xinerama.h>
00015 }
00016 typedef int (*XErrorCallbackType)(Display *, XErrorEvent *);
00017 typedef vector<XErrorEvent> XErrorVectorType;
00018 #else
00019 #include <qapplication.h>
00020 #endif // USING_X11
00021
00022 #ifdef USING_X11
00023 map<Display*, XErrorVectorType> error_map;
00024 map<Display*, XErrorCallbackType> error_handler_map;
00025 #endif // USING_X11
00026
00031 int GetNumberOfXineramaScreens(void)
00032 {
00033 int nr_xinerama_screens = 0;
00034
00035 #ifdef USING_X11
00036 Display *d = MythXOpenDisplay();
00037 X11L;
00038 int event_base = 0, error_base = 0;
00039 if (XineramaQueryExtension(d, &event_base, &error_base) &&
00040 XineramaIsActive(d))
00041 XFree(XineramaQueryScreens(d, &nr_xinerama_screens));
00042 XCloseDisplay(d);
00043 X11U;
00044 #else // if !USING_X11
00045 #if CONFIG_DARWIN
00046
00047 nr_xinerama_screens = QApplication::desktop()->numScreens();
00048 #endif // CONFIG_DARWIN
00049 #endif // !USING_X11
00050 return nr_xinerama_screens;
00051 }
00052
00053
00054
00055 #ifdef USING_X11
00056 Display *MythXOpenDisplay(void)
00057 {
00058 QString dispStr = MythContext::GetX11Display();
00059 const char *dispCStr = NULL;
00060 if (!dispStr.isEmpty())
00061 dispCStr = dispStr.ascii();
00062
00063 X11L;
00064 Display *disp = XOpenDisplay(dispCStr);
00065 X11U;
00066
00067 if (!disp)
00068 VERBOSE(VB_IMPORTANT, "MythXOpenDisplay() failed");
00069
00070 return disp;
00071 }
00072
00073 int ErrorCatcher(Display * d, XErrorEvent * xeev)
00074 {
00075 error_map[d].push_back(*xeev);
00076 return 0;
00077 }
00078
00079 void InstallXErrorHandler(Display *d)
00080 {
00081 XErrorVectorType empty;
00082 error_map[d] = empty;
00083 X11L;
00084 XSync(d, 0);
00085 error_handler_map[d] = XSetErrorHandler(ErrorCatcher);
00086 X11U;
00087 }
00088
00089 void PrintXErrors(Display *d, const vector<XErrorEvent>& events)
00090 {
00091 for (int i = events.size() -1; i>=0; --i)
00092 {
00093 char buf[200];
00094 X11S(XGetErrorText(d, events[i].error_code, buf, sizeof(buf)));
00095 VERBOSE(VB_IMPORTANT, endl
00096 <<"XError type: "<<events[i].type<<endl
00097 <<" display: "<<events[i].display<<endl
00098 <<" serial no: "<<events[i].serial<<endl
00099 <<" err code: "<<events[i].error_code<<" ("<<buf<<")"<<endl
00100 <<" req code: "<<events[i].request_code<<endl
00101 <<" minor code: "<<events[i].minor_code<<endl
00102 <<"resource id: "<<events[i].resourceid);
00103 }
00104 }
00105
00106 vector<XErrorEvent> UninstallXErrorHandler(Display *d, bool printErrors)
00107 {
00108 vector<XErrorEvent> events;
00109 X11L;
00110 XErrorCallbackType old_handler = error_handler_map[d];
00111 XSync(d, 0);
00112 X11U;
00113 if (old_handler)
00114 {
00115 error_handler_map[d] = NULL;
00116 X11S(XSetErrorHandler(old_handler));
00117 events = error_map[d];
00118 error_map[d].clear();
00119 if (printErrors)
00120 PrintXErrors(d, events);
00121 }
00122 else
00123 {
00124 VERBOSE(VB_IMPORTANT,
00125 "ErrorHandler uninstalled more often than installed");
00126 }
00127 return events;
00128 }
00129
00130 QSize MythXGetDisplaySize(Display *d, int screen)
00131 {
00132 Display *display = d;
00133 if (!display)
00134 display = MythXOpenDisplay();
00135 if (!display)
00136 {
00137 VERBOSE(VB_IMPORTANT, "GetXDisplaySize: "
00138 "MythXOpenDisplay call failed");
00139 return QSize(0,0);
00140 }
00141
00142 X11L;
00143
00144 int scr = screen;
00145 if (scr < 0)
00146 scr = DefaultScreen(display);
00147
00148 int displayWidthPixel = DisplayWidth( display, scr);
00149 int displayHeightPixel = DisplayHeight(display, scr);
00150
00151 if (display != d)
00152 XCloseDisplay(display);
00153
00154 X11U;
00155
00156 return QSize(displayWidthPixel, displayHeightPixel);
00157 }
00158
00159 QSize MythXGetDisplayDimensions(Display *d, int screen)
00160 {
00161 Display *display = d;
00162 if (!display)
00163 display = MythXOpenDisplay();
00164 if (!display)
00165 {
00166 VERBOSE(VB_IMPORTANT, "GetXDisplayDimensions: "
00167 "MythXOpenDisplay call failed");
00168 return QSize(0,0);
00169 }
00170
00171 X11L;
00172
00173 int scr = screen;
00174 if (scr < 0)
00175 scr = DefaultScreen(display);
00176
00177 int displayWidthMM = DisplayWidthMM( display, scr);
00178 int displayHeightMM = DisplayHeightMM(display, scr);
00179
00180 if (display != d)
00181 XCloseDisplay(display);
00182
00183 X11U;
00184
00185 return QSize(displayWidthMM, displayHeightMM);
00186 }
00187
00188 double MythXGetPixelAspectRatio(Display *d, int screen)
00189 {
00190 Display *display = d;
00191 if (!display)
00192 display = MythXOpenDisplay();
00193 if (!display)
00194 {
00195 VERBOSE(VB_IMPORTANT, "GetXPixelAspectRatio: "
00196 "MythXOpenDisplay call failed");
00197 return 1.0;
00198 }
00199
00200 X11L;
00201 int scr = screen;
00202 if (scr < 0)
00203 scr = DefaultScreen(display);
00204 X11U;
00205
00206 double pixelAspect = 1.0;
00207 QSize dim = MythXGetDisplayDimensions(display, screen);
00208 QSize sz = MythXGetDisplaySize(display, screen);
00209
00210 if ((dim.width() > 0) && (dim.height() > 0) &&
00211 (sz.width() > 0) && (sz.height() > 0))
00212 {
00213 pixelAspect =
00214 ((double)dim.width() / (double)sz.width()) /
00215 ((double)dim.height() / (double)sz.height());
00216 }
00217
00218 X11L;
00219 if (display != d)
00220 XCloseDisplay(display);
00221 X11U;
00222
00223 return pixelAspect;
00224 }
00225
00226 #endif // USING_X11