diff --git a/os/x11/monitor.cpp b/os/x11/monitor.cpp index 2b18bb95a..48a2bc593 100644 --- a/os/x11/monitor.cpp +++ b/os/x11/monitor.cpp @@ -1,6 +1,12 @@ -#include "monitor.h" +#include "os/x11/monitor.h" +#include "gfx/rect.h" +#include "os/ref.h" +#include "os/screen.h" #include "os/x11/x11.h" +#include "os/x11/screen.h" +#include +#include #include namespace os { @@ -18,7 +24,43 @@ MonitorsX11::MonitorsX11() int MonitorsX11::numMonitors() const { return m_numMonitors; } -const XRRMonitorInfo& MonitorsX11::monitor(int monitorNum) const { return m_monitors.get()[monitorNum]; } +const XRRMonitorInfo& MonitorsX11::monitorInfo(int monitorNum) const { return m_monitors.get()[monitorNum]; } + +// searches for the monitor containing the most area of the window +ScreenRef MonitorsX11::nearestMonitorOf(const gfx::Rect& frame) const +{ + ScreenRef candidate = nullptr; + int most_area = INT_MIN; + + for (int nmonitor=0; nmonitor(nmonitor); + + const gfx::Rect& bounds = monitor->bounds(); + gfx::Rect segment(frame); + if (segment.x < bounds.x) { + segment.w = std::max(0, segment.w - (bounds.x-segment.x)); + segment.x = bounds.x; + } + if (segment.x2() > bounds.x2()) { + segment.w = std::max(0, segment.w - (segment.x2()-bounds.x2())); + } + if (segment.y < bounds.y) { + segment.h = std::max(0, segment.h - (bounds.y-segment.y)); + segment.y = bounds.y; + } + if (segment.y2() > bounds.y2()) { + segment.h = std::max(0, segment.h - (segment.y2()-bounds.y2())); + } + + int area = segment.w*segment.h; + if (area > most_area) { + candidate = monitor; + most_area = area; + } + } + + return candidate; +} } // namespace os diff --git a/os/x11/monitor.h b/os/x11/monitor.h index 19d2a7d84..d95a3988a 100644 --- a/os/x11/monitor.h +++ b/os/x11/monitor.h @@ -2,8 +2,11 @@ #define MONITOR_H #pragma once -#include +#include "gfx/fwd.h" +#include "os/screen.h" + #include +#include namespace os { @@ -16,8 +19,11 @@ typedef std::unique_ptr unique_monitors_ptr; class MonitorsX11 { public: MonitorsX11(); + int numMonitors() const; - const XRRMonitorInfo& monitor(int monitorNum) const; + const XRRMonitorInfo& monitorInfo(int monitorNum) const; + + ScreenRef nearestMonitorOf(const gfx::Rect& frame) const; private: int m_numMonitors; diff --git a/os/x11/screen.h b/os/x11/screen.h index 515b176af..55636b290 100644 --- a/os/x11/screen.h +++ b/os/x11/screen.h @@ -11,6 +11,7 @@ #include "os/screen.h" #include "os/x11/monitor.h" #include "os/x11/x11.h" +#include "os/system.h" #include @@ -20,7 +21,7 @@ class ScreenX11 : public Screen { public: ScreenX11(int monitorNum) : m_monitorNum(monitorNum) { MonitorsX11* monitors = X11::instance()->monitors(); - const XRRMonitorInfo& monitor = monitors->monitor(monitorNum); + const XRRMonitorInfo& monitor = monitors->monitorInfo(monitorNum); m_bounds.x = monitor.x; m_bounds.y = monitor.y; diff --git a/os/x11/system.h b/os/x11/system.h index c974dfeca..3eeff5333 100644 --- a/os/x11/system.h +++ b/os/x11/system.h @@ -89,7 +89,7 @@ class SystemX11 : public CommonSystem { // we have to search for the primary monitor for (int monitor=0; monitormonitor(monitor).primary) { + if (monitors->monitorInfo(monitor).primary) { return make_ref(monitor); } } diff --git a/os/x11/window.cpp b/os/x11/window.cpp index dd9f68676..88b48e7bb 100644 --- a/os/x11/window.cpp +++ b/os/x11/window.cpp @@ -447,7 +447,11 @@ WindowX11::~WindowX11() os::ScreenRef WindowX11::screen() const { - return os::instance()->mainScreen(); + ScreenRef nearestMonitor = X11::instance()->monitors()->nearestMonitorOf(frame()); + if (nearestMonitor) + return nearestMonitor; + else + return os::instance()->mainScreen(); } os::ColorSpaceRef WindowX11::colorSpace() const