3 This file is part of libmspgbase
4 Copyright © 2007 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
11 #include <X11/extensions/xf86vmode.h>
13 #include <msp/core/except.h>
14 #include <msp/strings/formatter.h>
15 #include <msp/strings/lexicalcast.h>
23 bool error_flag=false;
24 std::string error_msg;
27 int x_error_handler(Display *display, XErrorEvent *event)
30 XGetErrorText(display, event->error_code, err, sizeof(err));
32 string request_code=Msp::lexical_cast(static_cast<int>(event->request_code));
34 XGetErrorDatabaseText(display, "XRequest", request_code.c_str(), request_code.c_str(), req, sizeof(req));
36 string msg=Msp::format("Request %s failed with %s [%08X]", req, err, event->resourceid);
38 cerr<<"Discarding error: "<<msg<<'\n';
55 Display::Display(const string &disp_name)
60 for(unsigned i=0;; ++i)
63 if(!EnumDisplaySettings(0, i, &info))
66 VideoMode mode(info.dmPelsWidth, info.dmPelsHeight);
67 mode.rate=info.dmDisplayFrequency;
68 modes.push_back(mode);
72 if(EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &info))
74 orig_mode=VideoMode(info.dmPelsWidth, info.dmPelsHeight);
75 orig_mode.rate=info.dmDisplayFrequency;
79 display=XOpenDisplay(0);
81 display=XOpenDisplay(disp_name.c_str());
83 throw Exception("Couldn't open X display");
85 XSetErrorHandler(x_error_handler);
87 int screen=DefaultScreen(display);
90 XF86VidModeModeInfo **infos;
91 XF86VidModeGetAllModeLines(display, screen, &nmodes, &infos);
92 for(int i=0; i<nmodes; ++i)
94 XF86VidModeModeInfo &info=*infos[i];
96 VideoMode mode(info.hdisplay, info.vdisplay);
97 if(info.htotal && info.vtotal)
98 mode.rate=info.dotclock/(info.htotal*info.vtotal);
99 modes.push_back(mode);
104 XF86VidModeModeLine modeline;
106 XF86VidModeGetModeLine(display, screen, &dotclock, &modeline);
107 orig_mode=VideoMode(modeline.hdisplay, modeline.vdisplay);
108 if(modeline.htotal && modeline.vtotal)
109 orig_mode.rate=dotclock/(modeline.htotal*modeline.vtotal);
116 XCloseDisplay(display);
121 void Display::add_window(Window *wnd)
123 windows[wnd->get_handle()]=wnd;
126 void Display::remove_window(Window *wnd)
128 windows.erase(wnd->get_handle());
131 void Display::set_mode(const VideoMode &mode)
135 info.dmSize=sizeof(DEVMODE);
136 info.dmFields=DM_PELSWIDTH|DM_PELSHEIGHT;
137 info.dmPelsWidth=mode.width;
138 info.dmPelsHeight=mode.height;
141 info.dmFields|=DM_DISPLAYFREQUENCY;
142 info.dmDisplayFrequency=mode.rate;
145 ChangeDisplaySettings(&info, CDS_FULLSCREEN);
147 int screen=DefaultScreen(display);
150 XF86VidModeModeInfo **infos;
151 XF86VidModeGetAllModeLines(display, screen, &nmodes, &infos);
152 for(int i=0; i<nmodes; ++i)
154 XF86VidModeModeInfo &info=*infos[i];
157 if(info.htotal && info.vtotal)
158 rate=info.dotclock/(info.htotal*info.vtotal);
159 if(info.hdisplay==mode.width && info.vdisplay==mode.height && (mode.rate==0 || rate==mode.rate))
161 XF86VidModeSwitchToMode(display, screen, &info);
162 XF86VidModeSetViewPort(display, screen, 0, 0);
167 throw InvalidParameterValue("Requested mode not supported");
179 if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
180 DispatchMessage(&msg);
184 int pending=XPending(display);
188 for(int i=0; i<pending; ++i)
191 XNextEvent(display, &event);
195 map<WindowHandle, Window *>::iterator j=windows.find(event.xany.window);
197 j->second->event(event);
203 void Display::check_error()
208 throw Exception(error_msg);
212 } // namespace Graphics