#include "display.h"
+#include <cmath>
+#include <sigc++/bind.h>
#include "display_private.h"
#include "window.h"
void Display::add_window(Window &wnd)
{
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));
}
void Display::remove_window(Window &wnd)
{
priv->windows.erase(wnd.get_private().window);
+ if(&wnd==focus_window)
+ focus_window = nullptr;
+}
+
+const VideoMode &Display::get_desktop_mode() const
+{
+ if(!primary_monitor || !primary_monitor->desktop_settings.mode)
+ throw logic_error("no desktop mode");
+ return *primary_monitor->desktop_settings.mode;
+}
+
+void Display::restore_mode()
+{
+ for(const Monitor &m: monitors)
+ if(m.desktop_settings.mode)
+ set_mode(*m.desktop_settings.mode, false);
+}
+
+const VideoMode *Display::find_mode(const VideoMode &mode, float rate_tolerance) const
+{
+ const VideoMode *closest = nullptr;
+ float rate_diff = 0.0f;
+
+ float target_rate = mode.rate;
+ if(!target_rate && mode.monitor)
+ if(const VideoMode *current_mode = mode.monitor->current_settings.mode)
+ target_rate = current_mode->rate;
+
+ for(const VideoMode &m: modes)
+ {
+ if(mode.monitor && m.monitor!=mode.monitor)
+ continue;
+ // Only check rate tolerance against an explicitly requested rate
+ if(mode.rate && (m.rate<mode.rate-rate_tolerance || m.rate>mode.rate+rate_tolerance))
+ continue;
+ if(m.width!=mode.width || m.height!=mode.height)
+ continue;
+
+ float ref_rate = target_rate;
+ if(!ref_rate)
+ if(const VideoMode *current_mode = m.monitor->current_settings.mode)
+ ref_rate = current_mode->rate;
+
+ float d = abs(m.rate-ref_rate);
+ if(!closest || d<rate_diff)
+ {
+ closest = &m;
+ rate_diff = d;
+ }
+ }
+
+ return closest;
+}
+
+const VideoMode *Display::find_mode(unsigned width, unsigned height) const
+{
+ return find_mode(VideoMode(width, height));
+}
+
+void Display::window_got_focus(Window &w)
+{
+ focus_window = &w;
+}
+
+void Display::window_lost_focus()
+{
+ focus_window = nullptr;
}
void Display::tick()
{
check_error();
+ Window *old_focus = focus_window;
+
while(process_events()) ;
+
+ if(old_focus && !focus_window)
+ signal_lost_focus.emit();
+ else if(!old_focus && focus_window)
+ signal_got_focus.emit();
}
} // namespace Graphics