4 #ifdef WITH_XF86VIDMODE
5 #include <X11/extensions/xf86vmode.h>
8 #include <msp/strings/format.h>
9 #include <msp/strings/lexicalcast.h>
12 #include "display_priv.h"
18 bool error_flag = false;
19 std::string error_msg;
22 int x_error_handler(Display *display, XErrorEvent *event)
25 XGetErrorText(display, event->error_code, err, sizeof(err));
27 string request_code = Msp::lexical_cast(static_cast<int>(event->request_code));
29 XGetErrorDatabaseText(display, "XRequest", request_code.c_str(), request_code.c_str(), req, sizeof(req));
31 string msg = Msp::format("Request %s failed with %s [%08X]", req, err, event->resourceid);
33 cerr<<"Discarding error: "<<msg<<'\n';
50 unsupported_video_mode::unsupported_video_mode(const VideoMode &mode):
51 runtime_error(format("%dx%d", mode.width, mode.height))
55 Display::Display(const string &disp_name):
61 for(unsigned i=0;; ++i)
64 if(!EnumDisplaySettings(0, i, &info))
67 VideoMode mode(info.dmPelsWidth, info.dmPelsHeight);
68 mode.rate = info.dmDisplayFrequency;
69 modes.push_back(mode);
73 if(EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &info))
75 orig_mode = VideoMode(info.dmPelsWidth, info.dmPelsHeight);
76 orig_mode.rate = info.dmDisplayFrequency;
80 priv->display = XOpenDisplay(0);
82 priv->display = XOpenDisplay(disp_name.c_str());
84 throw runtime_error("XOpenDisplay");
86 XSetErrorHandler(x_error_handler);
88 #ifdef WITH_XF86VIDMODE
89 int screen = DefaultScreen(priv->display);
92 XF86VidModeModeInfo **infos;
93 XF86VidModeGetAllModeLines(priv->display, screen, &nmodes, &infos);
94 for(int i=0; i<nmodes; ++i)
96 XF86VidModeModeInfo &info = *infos[i];
98 VideoMode mode(info.hdisplay, info.vdisplay);
99 if(info.htotal && info.vtotal)
100 mode.rate = info.dotclock/(info.htotal*info.vtotal);
101 modes.push_back(mode);
106 XF86VidModeModeLine modeline;
108 XF86VidModeGetModeLine(priv->display, screen, &dotclock, &modeline);
109 orig_mode = VideoMode(modeline.hdisplay, modeline.vdisplay);
110 if(modeline.htotal && modeline.vtotal)
111 orig_mode.rate = dotclock/(modeline.htotal*modeline.vtotal);
119 XCloseDisplay(priv->display);
124 void Display::add_window(Window &wnd)
126 priv->windows[wnd.get_private().window] = &wnd;
129 void Display::remove_window(Window &wnd)
131 priv->windows.erase(wnd.get_private().window);
134 void Display::set_mode(const VideoMode &mode)
138 info.dmSize = sizeof(DEVMODE);
139 info.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT;
140 info.dmPelsWidth = mode.width;
141 info.dmPelsHeight = mode.height;
144 info.dmFields |= DM_DISPLAYFREQUENCY;
145 info.dmDisplayFrequency = mode.rate;
148 LONG ret = ChangeDisplaySettings(&info, CDS_FULLSCREEN);
149 if(ret!=DISP_CHANGE_SUCCESSFUL)
150 throw unsupported_video_mode(mode);
151 #elif defined(WITH_XF86VIDMODE)
152 int screen = DefaultScreen(priv->display);
155 XF86VidModeModeInfo **infos;
156 XF86VidModeGetAllModeLines(priv->display, screen, &nmodes, &infos);
157 for(int i=0; i<nmodes; ++i)
159 XF86VidModeModeInfo &info = *infos[i];
162 if(info.htotal && info.vtotal)
163 rate = info.dotclock/(info.htotal*info.vtotal);
164 if(info.hdisplay==mode.width && info.vdisplay==mode.height && (mode.rate==0 || rate==mode.rate))
166 XF86VidModeSwitchToMode(priv->display, screen, &info);
167 XF86VidModeSetViewPort(priv->display, screen, 0, 0);
172 throw unsupported_video_mode(mode);
175 throw runtime_error("no xf86vidmode support");
187 if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
188 DispatchMessage(&msg);
192 int pending = XPending(priv->display);
199 XNextEvent(priv->display, &event.xevent);
203 map<WindowHandle, Window *>::iterator j = priv->windows.find(event.xevent.xany.window);
204 if(j!=priv->windows.end())
206 /* Filter keyboard autorepeat. If this packet is a KeyRelease and
207 the next one is a KeyPress with the exact same parameters, they
208 indicate autorepeat and must be dropped. */
209 if(event.xevent.type==KeyRelease && !j->second->get_keyboard_autorepeat() && pending>0)
211 XKeyEvent &kev = event.xevent.xkey;
213 XPeekEvent(priv->display, &ev2);
214 if(ev2.type==KeyPress)
216 XKeyEvent &kev2 = ev2.xkey;
217 if(kev2.window==kev.window && kev2.time==kev.time && kev2.keycode==kev.keycode)
219 XNextEvent(priv->display, &ev2);
226 j->second->event(event);
233 void Display::check_error()
238 throw runtime_error(error_msg);
242 } // namespace Graphics