3 #ifdef WITH_XF86VIDMODE
4 #include <X11/extensions/xf86vmode.h>
6 #include <msp/io/print.h>
7 #include <msp/strings/format.h>
8 #include <msp/strings/lexicalcast.h>
10 #include "display_private.h"
16 bool error_flag = false;
17 std::string error_msg;
19 int x_error_handler(Display *display, XErrorEvent *event)
22 XGetErrorText(display, event->error_code, err, sizeof(err));
24 string request_code = Msp::lexical_cast<string, int>(event->request_code);
26 XGetErrorDatabaseText(display, "XRequest", request_code.c_str(), request_code.c_str(), req, sizeof(req));
28 string msg = Msp::format("Request %s failed with %s [%08X]", req, err, event->resourceid);
30 Msp::IO::print(Msp::IO::cerr, "Discarding error: %s\n", msg);
33 Msp::IO::print(Msp::IO::cerr, "%s\n", msg);
47 Display::Display(const string &disp_name):
52 priv->display = XOpenDisplay(0);
54 priv->display = XOpenDisplay(disp_name.c_str());
56 throw runtime_error("XOpenDisplay");
58 XSetErrorHandler(x_error_handler);
60 #ifdef WITH_XF86VIDMODE
61 int screen = DefaultScreen(priv->display);
63 monitors.push_back(Monitor());
64 Monitor &monitor = monitors.back();
65 primary_monitor = &monitor;
68 XF86VidModeModeInfo **infos;
69 XF86VidModeGetAllModeLines(priv->display, screen, &nmodes, &infos);
71 XF86VidModeModeLine modeline;
73 XF86VidModeGetModeLine(priv->display, screen, &dotclock, &modeline);
75 for(int i=0; i<nmodes; ++i)
77 XF86VidModeModeInfo &info = *infos[i];
79 VideoMode mode(info.hdisplay, info.vdisplay);
80 mode.monitor = &monitor;
81 if(info.htotal && info.vtotal)
82 mode.rate = info.dotclock/(info.htotal*info.vtotal);
83 modes.push_back(mode);
84 monitor.video_modes.push_back(&modes.back());
86 if(info.htotal==modeline.htotal && info.vtotal==modeline.vtotal && info.dotclock==static_cast<unsigned>(dotclock))
87 monitor.desktop_mode = &modes.back();
96 XCloseDisplay(priv->display);
100 void Display::set_mode(const VideoMode &mode, bool)
102 #ifdef WITH_XF86VIDMODE
103 int screen = DefaultScreen(priv->display);
106 XF86VidModeModeInfo **infos;
107 XF86VidModeGetAllModeLines(priv->display, screen, &nmodes, &infos);
108 for(int i=0; i<nmodes; ++i)
110 XF86VidModeModeInfo &info = *infos[i];
113 if(info.htotal && info.vtotal)
114 rate = info.dotclock/(info.htotal*info.vtotal);
115 if(info.hdisplay==mode.width && info.vdisplay==mode.height && (mode.rate==0 || rate==mode.rate))
117 XF86VidModeSwitchToMode(priv->display, screen, &info);
118 XF86VidModeSetViewPort(priv->display, screen, 0, 0);
123 throw unsupported_video_mode(mode);
126 throw runtime_error("no xf86vidmode support");
130 bool Display::process_events()
132 int pending = XPending(priv->display);
139 XNextEvent(priv->display, &event.xevent);
143 map<WindowHandle, Window *>::iterator j = priv->windows.find(event.xevent.xany.window);
144 if(j!=priv->windows.end())
146 /* Filter keyboard autorepeat. If this packet is a KeyRelease and
147 the next one is a KeyPress with the exact same parameters, they
148 indicate autorepeat and must be dropped. */
149 if(event.xevent.type==KeyRelease && !j->second->get_keyboard_autorepeat() && pending>0)
151 XKeyEvent &kev = event.xevent.xkey;
153 XPeekEvent(priv->display, &ev2);
154 if(ev2.type==KeyPress)
156 XKeyEvent &kev2 = ev2.xkey;
157 if(kev2.window==kev.window && kev2.time==kev.time && kev2.keycode==kev.keycode)
159 XNextEvent(priv->display, &ev2);
166 j->second->event(event);
173 void Display::check_error()
178 throw runtime_error(error_msg);
183 } // namespace Graphics