-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscreenlayout.h
More file actions
76 lines (69 loc) · 3.04 KB
/
Copy pathscreenlayout.h
File metadata and controls
76 lines (69 loc) · 3.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#pragma once
#include <QList>
#include <QPoint>
#include <QRect>
#include <QtGlobal>
#include "appsettings.h" // EdgeLock
// Which monitor is a window on?
//
// Pure geometry, deliberately free of QScreen and QGuiApplication: every
// function takes the list of screens' *available* rectangles, so the awkward
// multi-monitor arrangements this code exists to handle can be unit-tested on a
// single-monitor build machine with no display at all. mainwindow.cpp supplies
// the real list from QGuiApplication::screens() — see the thin wrappers there,
// which also own the "fall back to the primary screen" half of the decision.
//
// Index conventions: functions return an index into `screens`, or -1 for "no
// screen qualifies". -1 is a real answer, not an error — a window whose monitor
// was just unplugged is on no screen — and the caller decides what to do about it.
namespace screenlayout {
// Index of the screen a window rect mostly occupies, or -1 if it touches none.
// Used where there is no docked edge to anchor to.
inline int indexOfLargestOverlap(const QList<QRect>& screens, const QRect& windowRect)
{
int best = -1;
qint64 bestArea = 0;
for (int i = 0; i < screens.size(); ++i) {
const QRect r = screens.at(i).intersected(windowRect);
const qint64 area = qint64(r.width()) * r.height();
if (area > bestArea) { bestArea = area; best = i; }
}
return best;
}
// Index of the screen containing a global point, or -1.
inline int indexAt(const QList<QRect>& screens, QPoint p)
{
for (int i = 0; i < screens.size(); ++i)
if (screens.at(i).contains(p))
return i;
return -1;
}
// Index of the screen an edge-locked window is docked to, or -1.
//
// The anchor is the window edge *opposite* the locked one, because that is the
// only point guaranteed to sit on the docked screen in both the shown and the
// slid-away states: a right-docked window that has slid away hangs off the right
// of its screen, so its own right edge is outside it.
//
// Neither the centre point nor the largest overlap works here once a second
// monitor sits next to the docked one. A left-docked window that has slid away
// extends past its screen's left edge, so it overlaps the monitor to its left far
// more than the few pixels it still shows on its own — pick by overlap and the
// window jumps to the neighbouring screen the moment it hides.
inline int dockedIndex(const QList<QRect>& screens, const QRect& windowRect, EdgeLock lock)
{
const QPoint anchor = (lock == EdgeLock::Left)
? QPoint(windowRect.right(), windowRect.center().y())
: QPoint(windowRect.left(), windowRect.center().y());
const int i = indexAt(screens, anchor);
return (i >= 0) ? i : indexOfLargestOverlap(screens, windowRect);
}
// Whether any part of a window rect is on a screen that still exists.
inline bool onSomeScreen(const QList<QRect>& screens, const QRect& windowRect)
{
for (const QRect& s : screens)
if (s.intersects(windowRect))
return true;
return false;
}
} // namespace screenlayout