00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "Core/precomp.h"
00016
00017 #ifdef USE_X11
00018 #include "API/Core/System/cl_assert.h"
00019 #include "x11_resolution.h"
00020
00021 CL_X11Resolution::CL_X11Resolution(Display *dpy, int scr)
00022 {
00023 this->dpy = dpy;
00024 this->scr = scr;
00025 mode_set = false;
00026 has_vidmode_extension = false;
00027
00028 #ifdef USE_VIDMODE
00029 int dummy;
00030 has_vidmode_extension =
00031 XF86VidModeQueryExtension(dpy, &dummy, &dummy) == True ? true : false;
00032 #endif
00033
00034 cur_width = DisplayWidth(dpy, scr);
00035 cur_height = DisplayHeight(dpy, scr);
00036 }
00037
00038 CL_X11Resolution::~CL_X11Resolution()
00039 {
00040 restore_mode();
00041 }
00042
00043 void CL_X11Resolution::set_mode(int width, int height)
00044 {
00045 #ifdef USE_VIDMODE
00046 if (!has_vidmode_extension) return;
00047
00048 if (!mode_set)
00049 {
00050 memset(&orig_mode, 0, sizeof(orig_mode));
00051 memset(&orig_view, 0, sizeof(orig_view));
00052
00053
00054 XF86VidModeModeLine *l = (XF86VidModeModeLine*)((char*) &orig_mode + sizeof orig_mode.dotclock);
00055 cl_assert(XF86VidModeGetModeLine(dpy, scr, (int*) &orig_mode.dotclock, l) == True);
00056
00057
00058 cl_assert(XF86VidModeGetViewPort(dpy, scr, &orig_view.x, &orig_view.y) == True);
00059 }
00060
00061 XF86VidModeModeInfo mode = get_best_mode(width, height);
00062
00063 if ((mode.vdisplay != 0) && (mode.hdisplay != 0))
00064 {
00065
00066 XWarpPointer(dpy, None, RootWindow(dpy, scr), 0, 0, 0, 0, 0, 0);
00067 cl_assert(XF86VidModeSwitchToMode(dpy, scr, &mode) == True);
00068 XWarpPointer(dpy, None, RootWindow(dpy, scr), 0, 0, 0, 0, 0, 0);
00069
00070
00071 cur_width = mode.hdisplay;
00072 cur_height = mode.vdisplay;
00073 mode_set = true;
00074 XSync(dpy, True);
00075 }
00076 #endif
00077 }
00078
00079 void CL_X11Resolution::restore_mode()
00080 {
00081 #ifdef USE_VIDMODE
00082 if (!has_vidmode_extension) return;
00083 if (!mode_set) return;
00084
00085 if (cur_width != orig_mode.hdisplay || cur_height != orig_mode.vdisplay)
00086 {
00087 cl_assert(XF86VidModeSwitchToMode(dpy, scr, &orig_mode) == True);
00088 }
00089 if (orig_view.x != 0 || orig_view.y != 0)
00090 {
00091 #ifdef DEBUG
00092 std::cout << "setting viewport" << std::endl;
00093 #endif
00094 cl_assert(XF86VidModeSetViewPort(dpy, scr, orig_view.x, orig_view.y) == True);
00095 }
00096 cur_width = DisplayWidth(dpy, scr);
00097 cur_height = DisplayHeight(dpy, scr);
00098
00099 mode_set = false;
00100 XSync(dpy, True);
00101 #endif
00102 }
00103
00104 int CL_X11Resolution::get_width() const
00105 {
00106 return cur_width;
00107 }
00108
00109 int CL_X11Resolution::get_height() const
00110 {
00111 return cur_height;
00112 }
00113
00114 #ifdef USE_VIDMODE
00115
00116
00117 static int cmpmodes(const void *va, const void *vb)
00118 {
00119 XF86VidModeModeInfo *a = *(XF86VidModeModeInfo**)va;
00120 XF86VidModeModeInfo *b = *(XF86VidModeModeInfo**)vb;
00121 if(a->hdisplay > b->hdisplay)
00122 return -1;
00123 return b->vdisplay - a->vdisplay;
00124 }
00125
00126 XF86VidModeModeInfo CL_X11Resolution::get_best_mode(int width, int height)
00127 {
00128 XF86VidModeModeInfo **modes;
00129 XF86VidModeModeLine mode;
00130 int nmodes;
00131 int i;
00132
00133 if ( XF86VidModeGetModeLine(dpy, scr, &i, &mode) &&
00134 XF86VidModeGetAllModeLines(dpy, scr, &nmodes, &modes))
00135 {
00136 qsort(modes, nmodes, sizeof *modes, cmpmodes);
00137 #ifdef DEBUG
00138 cout << "Available modes:" << endl;
00139 for (i=0; i<nmodes; ++i)
00140 {
00141 cout << "Mode " << i << " : " << modes[i]->hdisplay << "x" << modes[i]->vdisplay << endl;
00142 }
00143 #endif
00144 for (i=nmodes-1; i>= 0; --i)
00145 {
00146 if ( (modes[i]->hdisplay >= width) &&
00147 (modes[i]->vdisplay >= height) )
00148 break;
00149 }
00150 if (i>=0)
00151 {
00152 if ( (modes[i]->hdisplay != mode.hdisplay) ||
00153 (modes[i]->vdisplay != mode.vdisplay) )
00154 {
00155 return *modes[i];
00156 }
00157 XFree(modes);
00158 }
00159 }
00160
00161 XF86VidModeModeInfo dummy_mode;
00162 memset(&dummy_mode, 0, sizeof(dummy_mode));
00163 return dummy_mode;
00164 }
00165 #endif
00166
00167 #endif