From 66371457fd81430648c2e9302286de60194ef21e Mon Sep 17 00:00:00 2001 From: Megamouse Date: Wed, 21 Jul 2021 00:06:48 +0200 Subject: [PATCH] Qt: fix game window positions if the window is bigger than the screen If the screen was smaller than the game window, then the window would pop up top right offscreen. The fix itself was really simple and obvious from the beginning, just some missing clamping. But I figured it might be less confusing if I add some prosa. Especially because it took me a couple of hours to figure out why I made it so complex in the first place. Btw, there might still be some offset to the left occasionally, but that seems to be an upstream issue --- rpcs3/rpcs3qt/gs_frame.cpp | 43 +++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/rpcs3/rpcs3qt/gs_frame.cpp b/rpcs3/rpcs3qt/gs_frame.cpp index 1fccc00fb8..3601a14274 100644 --- a/rpcs3/rpcs3qt/gs_frame.cpp +++ b/rpcs3/rpcs3qt/gs_frame.cpp @@ -135,13 +135,42 @@ void gs_frame::paintEvent(QPaintEvent *event) void gs_frame::showEvent(QShowEvent *event) { - // We have to calculate new window positions, since the frame is only known once the window was created - const QRect available_geometry = screen()->availableGeometry(); - QPoint pos = m_initial_geometry.topLeft(); - pos.setX(std::min(std::max(pos.x() - ((frameGeometry().width() - width()) / 2), available_geometry.left()), - available_geometry.left() + available_geometry.width() - frameGeometry().width())); - pos.setY(std::min(std::max(pos.y() - ((frameGeometry().height() - height()) / 2), available_geometry.top()), - available_geometry.top() + available_geometry.height() - frameGeometry().height())); + // We have to calculate new window positions, since the frame is only known once the window was created. + // We will try to find the originally requested dimensions if possible by moving the frame. + + // NOTES: The parameter m_initial_geometry is not necessarily equal to our actual geometry() at this point. + // That's why we use m_initial_geometry instead of the frameGeometry() in some places. + // All of these values, including the screen geometry, can also be negative numbers. + + const QRect available_geometry = screen()->availableGeometry(); // The available screen geometry + const QRect inner_geometry = geometry(); // The current inner geometry + const QRect outer_geometry = frameGeometry(); // The current outer geometry + + // Calculate the left and top frame borders (this will include window handles) + const int left_border = inner_geometry.left() - outer_geometry.left(); + const int top_border = inner_geometry.top() - outer_geometry.top(); + + // Calculate the initially expected frame origin + const QPoint expected_pos(m_initial_geometry.left() - left_border, + m_initial_geometry.top() - top_border); + + // Make sure that the expected position is inside the screen (check left and top borders) + QPoint pos(std::max(expected_pos.x(), available_geometry.left()), + std::max(expected_pos.y(), available_geometry.top())); + + // Find the maximum position that still ensures that the frame is completely visible inside the screen (check right and bottom borders) + QPoint max_pos(available_geometry.left() + available_geometry.width() - frameGeometry().width(), + available_geometry.top() + available_geometry.height() - frameGeometry().height()); + + // Make sure that the "maximum" position is inside the screen (check left and top borders) + max_pos.setX(std::max(max_pos.x(), available_geometry.left())); + max_pos.setY(std::max(max_pos.y(), available_geometry.top())); + + // Adjust the expected position accordingly + pos.setX(std::min(pos.x(), max_pos.x())); + pos.setY(std::min(pos.y(), max_pos.y())); + + // Set the new position setFramePosition(pos); QWindow::showEvent(event);