Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 49 additions & 20 deletions src/lib/app/RvCommon/RvApplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -766,19 +766,50 @@ namespace Rv

auto isVirtualDesktop = [&screens, primaryScreen]() -> bool
{
// Not a virtual desktop if there is only one screen.
if (screens.size() <= 1)
// Not a virtual desktop if there is only one screen, or if
// we have no primary screen to compare against.
if (screens.size() <= 1 || primaryScreen == nullptr)
return false;

QRect totalGeometry;
for (const auto& screen : screens)
{
if (screen == nullptr)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add curly braces? That style is not followed everywhere, but we are trying to add curly braces whenever we can.

continue;
totalGeometry = totalGeometry.united(screen->geometry());
}

return totalGeometry != primaryScreen->geometry();
};

//
// Find the screen index for a given global point. Prefer Qt's
// QGuiApplication::screenAt() which handles edge cases (such as
// monitors whose top edges are not aligned, leaving gaps in the
// virtual desktop bounding box) more robustly than a manual
// QRect::contains() check.
//
auto getScreenFromPoint = [&screens](const QPoint& point) -> int
{
QScreen* s = QGuiApplication::screenAt(point);
if (s != nullptr)
{
const int idx = screens.indexOf(s);
if (idx >= 0)
return idx;
}

for (int i = 0; i < screens.size(); ++i)
{
if (screens[i] != nullptr && screens[i]->geometry().contains(point))
{
return i;
}
}

return -1;
};

//
// Allow command line placement
//
Expand All @@ -787,7 +818,7 @@ namespace Rv
{
if (opts.screen != -1 && isVirtualDesktop())
{
if (opts.screen < screens.size())
if (opts.screen >= 0 && opts.screen < screens.size() && screens[opts.screen] != nullptr)
{
QRect r = screens[opts.screen]->geometry();
opts.x += r.x();
Expand All @@ -805,39 +836,37 @@ namespace Rv
}
}

auto getScreenFromPoint = [&screens](const QPoint& point) -> int
{
for (int i = 0; i < screens.size(); ++i)
{
if (screens[i]->geometry().contains(point))
{
return i;
}
}

return -1;
};

int screen = getScreenFromPoint(QCursor::pos());
if (opts.screen != -1)
{
screen = opts.screen;
//
// Honor the user/preference-supplied screen index only when
// it refers to an actual screen. A stale preference (or a
// command-line value larger than the current monitor count)
// must not be propagated as an out-of-bounds index.
//
if (opts.screen >= 0 && opts.screen < screens.size())
{
screen = opts.screen;
}
}

int oldX = doc->pos().x();
int oldY = doc->pos().y();

int oldScreen = getScreenFromPoint(QPoint(oldX, oldY));

if (screen != -1 && oldScreen != -1 && isVirtualDesktop() && screen != oldScreen)
if (screen >= 0 && screen < screens.size() && oldScreen >= 0 && oldScreen < screens.size()
&& screens[screen] != nullptr && screens[oldScreen] != nullptr && isVirtualDesktop()
&& screen != oldScreen)
//
// The application is going to come up on the wrong screen, so figure
// out our our relative position on the current screen, and move to the
// same relative position on the correct screen.
//
{
QRect rnew = QGuiApplication::screens().at(screen)->geometry();
QRect rold = QGuiApplication::screens().at(oldScreen)->geometry();
QRect rnew = screens[screen]->geometry();
QRect rold = screens[oldScreen]->geometry();

int xoff = oldX - rold.x();
int yoff = oldY - rold.y();
Expand Down
Loading