X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fgraphics%2Fdisplay.cpp;h=1c7b639a06d8f993b72ef92fb19d9d211271ed5b;hb=e15959a69551c2027029470e65a17ea5a305545b;hp=da036a1baa9a4174049f40920fd0575e42fc0ceb;hpb=1023b38fa278cea71fba3d2881e1bfde930cd025;p=libs%2Fgui.git diff --git a/source/graphics/display.cpp b/source/graphics/display.cpp index da036a1..1c7b639 100644 --- a/source/graphics/display.cpp +++ b/source/graphics/display.cpp @@ -1,242 +1,98 @@ -#include -#ifndef WIN32 -#include -#ifdef WITH_XF86VIDMODE -#include -#endif -#endif -#include -#include +#include +#include #include "display.h" +#include "display_private.h" #include "window.h" -#include "display_priv.h" using namespace std; -namespace { - -bool error_flag = false; -std::string error_msg; - -#ifndef WIN32 -int x_error_handler(Display *display, XErrorEvent *event) -{ - char err[128]; - XGetErrorText(display, event->error_code, err, sizeof(err)); - - string request_code = Msp::lexical_cast(static_cast(event->request_code)); - char req[128]; - XGetErrorDatabaseText(display, "XRequest", request_code.c_str(), request_code.c_str(), req, sizeof(req)); - - string msg = Msp::format("Request %s failed with %s [%08X]", req, err, event->resourceid); - if(error_flag) - cerr<<"Discarding error: "<display = XOpenDisplay(0); - else - priv->display = XOpenDisplay(disp_name.c_str()); - if(!priv->display) - throw runtime_error("XOpenDisplay"); - - XSetErrorHandler(x_error_handler); - -#ifdef WITH_XF86VIDMODE - int screen = DefaultScreen(priv->display); - - int nmodes; - XF86VidModeModeInfo **infos; - XF86VidModeGetAllModeLines(priv->display, screen, &nmodes, &infos); - for(int i=0; idisplay, screen, &dotclock, &modeline); - orig_mode = VideoMode(modeline.hdisplay, modeline.vdisplay); - if(modeline.htotal && modeline.vtotal) - orig_mode.rate = dotclock/(modeline.htotal*modeline.vtotal); -#endif -#endif + priv->windows[wnd.get_private().window] = &wnd; + wnd.signal_got_focus.connect(sigc::bind(sigc::mem_fun(this, &Display::window_got_focus), sigc::ref(wnd))); + wnd.signal_lost_focus.connect(sigc::mem_fun(this, &Display::window_lost_focus)); } -Display::~Display() +void Display::remove_window(Window &wnd) { -#ifndef WIN32 - XCloseDisplay(priv->display); - delete priv; -#endif + priv->windows.erase(wnd.get_private().window); + if(&wnd==focus_window) + focus_window = 0; } -void Display::add_window(Window &wnd) +const VideoMode &Display::get_desktop_mode() const { - priv->windows[wnd.get_private().window] = &wnd; + if(!primary_monitor || !primary_monitor->desktop_mode) + throw logic_error("no desktop mode"); + return *primary_monitor->desktop_mode; } -void Display::remove_window(Window &wnd) +void Display::restore_mode() { - priv->windows.erase(wnd.get_private().window); + for(list::const_iterator i=monitors.begin(); i!=monitors.end(); ++i) + if(i->desktop_mode) + set_mode(*i->desktop_mode, false); } -void Display::set_mode(const VideoMode &mode) +const VideoMode *Display::find_mode(const VideoMode &mode, float rate_tolerance) const { -#if defined(WIN32) - DEVMODE info; - info.dmSize = sizeof(DEVMODE); - info.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT; - info.dmPelsWidth = mode.width; - info.dmPelsHeight = mode.height; - if(mode.rate) + const VideoMode *closest = 0; + float rate_diff = mode.rate; + for(list::const_iterator i=modes.begin(); i!=modes.end(); ++i) { - info.dmFields |= DM_DISPLAYFREQUENCY; - info.dmDisplayFrequency = mode.rate; + if(mode.monitor && i->monitor!=mode.monitor) + continue; + if(mode.rate && (i->raterate>mode.rate+rate_tolerance)) + continue; + if(i->width!=mode.width || i->height!=mode.height) + continue; + + if(mode.rate) + { + float d = abs(i->rate-mode.rate); + if(ddisplay); + return closest; +} - int nmodes; - XF86VidModeModeInfo **infos; - XF86VidModeGetAllModeLines(priv->display, screen, &nmodes, &infos); - for(int i=0; idisplay, screen, &info); - XF86VidModeSetViewPort(priv->display, screen, 0, 0); - return; - } - } +void Display::window_got_focus(Window &w) +{ + focus_window = &w; +} - throw unsupported_video_mode(mode); -#else - (void)mode; - throw runtime_error("no xf86vidmode support"); -#endif +void Display::window_lost_focus() +{ + focus_window = 0; } void Display::tick() { check_error(); - while(1) - { -#ifdef WIN32 - MSG msg; - if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) - DispatchMessage(&msg); - else - break; -#else - int pending = XPending(priv->display); - if(pending==0) - break; - - for(; pending--;) - { - Window::Event event; - XNextEvent(priv->display, &event.xevent); + Window *old_focus = focus_window; - check_error(); + while(process_events()) ; - map::iterator j = priv->windows.find(event.xevent.xany.window); - if(j!=priv->windows.end()) - { - /* Filter keyboard autorepeat. If this packet is a KeyRelease and - the next one is a KeyPress with the exact same parameters, they - indicate autorepeat and must be dropped. */ - if(event.xevent.type==KeyRelease && !j->second->get_keyboard_autorepeat() && pending>0) - { - XKeyEvent &kev = event.xevent.xkey; - XEvent ev2; - XPeekEvent(priv->display, &ev2); - if(ev2.type==KeyPress) - { - XKeyEvent &kev2 = ev2.xkey; - if(kev2.window==kev.window && kev2.time==kev.time && kev2.keycode==kev.keycode) - { - XNextEvent(priv->display, &ev2); - --pending; - continue; - } - } - } - - j->second->event(event); - } - } -#endif - } -} - -void Display::check_error() -{ - if(error_flag) - { - error_flag = false; - throw runtime_error(error_msg); - } + if(old_focus && !focus_window) + signal_lost_focus.emit(); + else if(!old_focus && focus_window) + signal_got_focus.emit(); } } // namespace Graphics