Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 0859a7b

Browse files
committedJul 21, 2024··
[x11] [multimon] feature: find the screen a window is on
Introduce parity to X11 from Windows. Respect per-monitor bounds.
1 parent 8f4af69 commit 0859a7b

File tree

5 files changed

+60
-7
lines changed

5 files changed

+60
-7
lines changed
 

‎os/x11/monitor.cpp

+44-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1-
#include "monitor.h"
1+
#include "os/x11/monitor.h"
2+
#include "gfx/rect.h"
3+
#include "os/ref.h"
4+
#include "os/screen.h"
25
#include "os/x11/x11.h"
6+
#include "os/x11/screen.h"
37

8+
#include <climits>
9+
#include <algorithm>
410
#include <X11/extensions/Xrandr.h>
511

612
namespace os {
@@ -18,7 +24,43 @@ MonitorsX11::MonitorsX11()
1824

1925
int MonitorsX11::numMonitors() const { return m_numMonitors; }
2026

21-
const XRRMonitorInfo& MonitorsX11::monitor(int monitorNum) const { return m_monitors.get()[monitorNum]; }
27+
const XRRMonitorInfo& MonitorsX11::monitorInfo(int monitorNum) const { return m_monitors.get()[monitorNum]; }
28+
29+
// searches for the monitor containing the most area of the window
30+
ScreenRef MonitorsX11::nearestMonitorOf(const gfx::Rect& frame) const
31+
{
32+
ScreenRef candidate = nullptr;
33+
int most_area = INT_MIN;
34+
35+
for (int nmonitor=0; nmonitor<m_numMonitors; nmonitor++) {
36+
ScreenRef monitor = os::make_ref<ScreenX11>(nmonitor);
37+
38+
const gfx::Rect& bounds = monitor->bounds();
39+
gfx::Rect segment(frame);
40+
if (segment.x < bounds.x) {
41+
segment.w = std::max(0, segment.w - (bounds.x-segment.x));
42+
segment.x = bounds.x;
43+
}
44+
if (segment.x2() > bounds.x2()) {
45+
segment.w = std::max(0, segment.w - (segment.x2()-bounds.x2()));
46+
}
47+
if (segment.y < bounds.y) {
48+
segment.h = std::max(0, segment.h - (bounds.y-segment.y));
49+
segment.y = bounds.y;
50+
}
51+
if (segment.y2() > bounds.y2()) {
52+
segment.h = std::max(0, segment.h - (segment.y2()-bounds.y2()));
53+
}
54+
55+
int area = segment.w*segment.h;
56+
if (area > most_area) {
57+
candidate = monitor;
58+
most_area = area;
59+
}
60+
}
61+
62+
return candidate;
63+
}
2264

2365
} // namespace os
2466

‎os/x11/monitor.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22
#define MONITOR_H
33
#pragma once
44

5-
#include <memory>
5+
#include "gfx/fwd.h"
6+
#include "os/screen.h"
7+
68
#include <X11/extensions/Xrandr.h>
9+
#include <memory>
710

811
namespace os {
912

@@ -16,8 +19,11 @@ typedef std::unique_ptr<XRRMonitorInfo, MonitorCloser> unique_monitors_ptr;
1619
class MonitorsX11 {
1720
public:
1821
MonitorsX11();
22+
1923
int numMonitors() const;
20-
const XRRMonitorInfo& monitor(int monitorNum) const;
24+
const XRRMonitorInfo& monitorInfo(int monitorNum) const;
25+
26+
ScreenRef nearestMonitorOf(const gfx::Rect& frame) const;
2127

2228
private:
2329
int m_numMonitors;

‎os/x11/screen.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "os/screen.h"
1212
#include "os/x11/monitor.h"
1313
#include "os/x11/x11.h"
14+
#include "os/system.h"
1415

1516
#include <X11/extensions/Xrandr.h>
1617

@@ -20,7 +21,7 @@ class ScreenX11 : public Screen {
2021
public:
2122
ScreenX11(int monitorNum) : m_monitorNum(monitorNum) {
2223
MonitorsX11* monitors = X11::instance()->monitors();
23-
const XRRMonitorInfo& monitor = monitors->monitor(monitorNum);
24+
const XRRMonitorInfo& monitor = monitors->monitorInfo(monitorNum);
2425

2526
m_bounds.x = monitor.x;
2627
m_bounds.y = monitor.y;

‎os/x11/system.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class SystemX11 : public CommonSystem {
8989

9090
// we have to search for the primary monitor
9191
for (int monitor=0; monitor<numMonitors; monitor++) {
92-
if (monitors->monitor(monitor).primary) {
92+
if (monitors->monitorInfo(monitor).primary) {
9393
return make_ref<ScreenX11>(monitor);
9494
}
9595
}

‎os/x11/window.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,11 @@ WindowX11::~WindowX11()
447447

448448
os::ScreenRef WindowX11::screen() const
449449
{
450-
return os::instance()->mainScreen();
450+
ScreenRef nearestMonitor = X11::instance()->monitors()->nearestMonitorOf(frame());
451+
if (nearestMonitor)
452+
return nearestMonitor;
453+
else
454+
return os::instance()->mainScreen();
451455
}
452456

453457
os::ColorSpaceRef WindowX11::colorSpace() const

0 commit comments

Comments
 (0)
Please sign in to comment.