x11: If XRandR isn't available, add a generic display. We can get _some_ of the info we need out of standard Xlib and report a single display (which might actually be multiple physical displays mushed into a single desktop). This is better than nothing, but you should really just build with XRandR support and get a better X server. :)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
diff --git a/src/video/x11/SDL_x11modes.c b/src/video/x11/SDL_x11modes.c
index 354baa3..87d9954 100644
--- a/src/video/x11/SDL_x11modes.c
+++ b/src/video/x11/SDL_x11modes.c
@@ -148,6 +148,30 @@ X11_GetPixelFormatFromVisualInfo(Display * display, XVisualInfo * vinfo)
return SDL_PIXELFORMAT_UNKNOWN;
}
+static int
+GetXftDPI(Display* dpy)
+{
+ char* xdefault_resource;
+ int xft_dpi, err;
+
+ xdefault_resource = X11_XGetDefault(dpy, "Xft", "dpi");
+
+ if(!xdefault_resource) {
+ return 0;
+ }
+
+ /*
+ * It's possible for SDL_atoi to call SDL_strtol, if it fails due to a
+ * overflow or an underflow, it will return LONG_MAX or LONG_MIN and set
+ * errno to ERANGE. So we need to check for this so we dont get crazy dpi
+ * values
+ */
+ xft_dpi = SDL_atoi(xdefault_resource);
+ err = errno;
+
+ return err == ERANGE ? 0 : xft_dpi;
+}
+
#if SDL_VIDEO_DRIVER_X11_XRANDR
static SDL_bool
CheckXRandR(Display * display, int *major, int *minor)
@@ -290,30 +314,6 @@ SetXRandRDisplayName(Display *dpy, Atom EDID, char *name, const size_t namelen,
}
static int
-GetXftDPI(Display* dpy)
-{
- char* xdefault_resource;
- int xft_dpi, err;
-
- xdefault_resource = X11_XGetDefault(dpy, "Xft", "dpi");
-
- if(!xdefault_resource) {
- return 0;
- }
-
- /*
- * It's possible for SDL_atoi to call SDL_strtol, if it fails due to a
- * overflow or an underflow, it will return LONG_MAX or LONG_MIN and set
- * errno to ERANGE. So we need to check for this so we dont get crazy dpi
- * values
- */
- xft_dpi = SDL_atoi(xdefault_resource);
- err = errno;
-
- return err == ERANGE ? 0 : xft_dpi;
-}
-
-static int
X11_InitModes_XRandR(_THIS)
{
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
@@ -478,16 +478,107 @@ X11_InitModes_XRandR(_THIS)
}
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
-int
-X11_InitModes(_THIS)
+/* This is used if there's no better functionality--like XRandR--to use.
+ It won't attempt to supply different display modes at all, but it can
+ enumerate the current displays and their current sizes. */
+static int X11_InitModes_StdXlib(_THIS)
{
+ /* !!! FIXME: a lot of copy/paste from X11_InitModes_XRandR in this function. */
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ Display *dpy = data->display;
+ const int default_screen = DefaultScreen(dpy);
+ Screen *screen = ScreenOfDisplay(dpy, default_screen);
+ int display_mm_width, display_mm_height, xft_dpi, scanline_pad, n, i;
+ SDL_DisplayModeData *modedata;
+ SDL_DisplayData *displaydata;
+ SDL_DisplayMode mode;
+ XPixmapFormatValues *pixmapformats;
+ Uint32 pixelformat;
+ XVisualInfo vinfo;
+ SDL_VideoDisplay display;
+
+ /* note that generally even if you have a multiple physical monitors, ScreenCount(dpy) still only reports ONE screen. */
+
+ if (get_visualinfo(dpy, default_screen, &vinfo) < 0) {
+ return SDL_SetError("Failed to find an X11 visual for the primary display");
+ }
+
+ pixelformat = X11_GetPixelFormatFromVisualInfo(dpy, &vinfo);
+ if (SDL_ISPIXELFORMAT_INDEXED(pixelformat)) {
+ return SDL_SetError("Palettized video modes are no longer supported");
+ }
-/* XRandR is the One True Modern Way to do this on X11. If this
- fails, we just won't report any display modes except the current
- desktop size. */
+ SDL_zero(mode);
+ mode.w = WidthOfScreen(screen);
+ mode.h = HeightOfScreen(screen);
+ mode.format = pixelformat;
+ mode.refresh_rate = 0; /* don't know it, sorry. */
+
+ displaydata = (SDL_DisplayData *) SDL_calloc(1, sizeof(*displaydata));
+ if (!displaydata) {
+ return SDL_OutOfMemory();
+ }
+
+ modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
+ if (!modedata) {
+ SDL_free(displaydata);
+ return SDL_OutOfMemory();
+ }
+ mode.driverdata = modedata;
+
+ display_mm_width = WidthMMOfScreen(screen);
+ display_mm_height = HeightMMOfScreen(screen);
+
+ displaydata->screen = default_screen;
+ displaydata->visual = vinfo.visual;
+ displaydata->depth = vinfo.depth;
+ displaydata->hdpi = display_mm_width ? (((float) mode.w) * 25.4f / display_mm_width) : 0.0f;
+ displaydata->vdpi = display_mm_height ? (((float) mode.h) * 25.4f / display_mm_height) : 0.0f;
+ displaydata->ddpi = SDL_ComputeDiagonalDPI(mode.w, mode.h, ((float) display_mm_width) / 25.4f,((float) display_mm_height) / 25.4f);
+
+ xft_dpi = GetXftDPI(dpy);
+ if(xft_dpi > 0) {
+ displaydata->hdpi = (float)xft_dpi;
+ displaydata->vdpi = (float)xft_dpi;
+ }
+
+ scanline_pad = SDL_BYTESPERPIXEL(pixelformat) * 8;
+ pixmapformats = X11_XListPixmapFormats(dpy, &n);
+ if (pixmapformats) {
+ for (i = 0; i < n; ++i) {
+ if (pixmapformats[i].depth == vinfo.depth) {
+ scanline_pad = pixmapformats[i].scanline_pad;
+ break;
+ }
+ }
+ X11_XFree(pixmapformats);
+ }
+
+ displaydata->scanline_pad = scanline_pad;
+ displaydata->x = 0;
+ displaydata->y = 0;
+ displaydata->use_xrandr = SDL_FALSE;
+
+ SDL_zero(display);
+ display.name = (char *) "Generic X11 Display"; /* this is just copied and thrown away, it's safe to cast to char* here. */
+ display.desktop_mode = mode;
+ display.current_mode = mode;
+ display.driverdata = displaydata;
+ SDL_AddVideoDisplay(&display, SDL_FALSE);
+
+ return 0;
+}
+
+
+int
+X11_InitModes(_THIS)
+{
+ /* XRandR is the One True Modern Way to do this on X11. If this
+ fails, we just won't report any display modes except the current
+ desktop size. */
#if SDL_VIDEO_DRIVER_X11_XRANDR
{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
int xrandr_major, xrandr_minor;
/* require at least XRandR v1.3 */
if (CheckXRandR(data->display, &xrandr_major, &xrandr_minor) &&
@@ -497,7 +588,8 @@ X11_InitModes(_THIS)
}
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
- return 0;
+ /* still here? Just set up an extremely basic display. */
+ return X11_InitModes_StdXlib(_this);
}
void