summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorisanae <14251494+isanae@users.noreply.github.com>2019-09-23 17:52:46 -0400
committerisanae <14251494+isanae@users.noreply.github.com>2019-09-23 17:52:46 -0400
commit829124d8b899101370e55eb2a9cb9164ffd68a55 (patch)
treeeaff00bafee0c07e7ab00d04a5e4c23de55004ca
parentd0099f577e9eabc7575321e68754fd41663827fe (diff)
ensure windows are on screen
-rw-r--r--src/settings.cpp90
-rw-r--r--src/settings.h51
2 files changed, 107 insertions, 34 deletions
diff --git a/src/settings.cpp b/src/settings.cpp
index 7cea52fb..19eca5ec 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -22,7 +22,9 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "serverinfo.h"
#include "executableslist.h"
#include "appconfig.h"
-#include "expanderwidget.h"
+#include "env.h"
+#include "envmetrics.h"
+#include <expanderwidget.h>
#include <utility.h>
#include <iplugingame.h>
@@ -604,21 +606,80 @@ void GeometrySettings::resetIfNeeded()
removeSection(m_Settings, "Geometry");
}
-void GeometrySettings::saveGeometry(const QWidget* w)
+void GeometrySettings::saveGeometry(const QMainWindow* w)
+{
+ saveWindowGeometry(w);
+}
+
+bool GeometrySettings::restoreGeometry(QMainWindow* w) const
+{
+ return restoreWindowGeometry(w);
+}
+
+void GeometrySettings::saveGeometry(const QDialog* d)
+{
+ saveWindowGeometry(d);
+}
+
+bool GeometrySettings::restoreGeometry(QDialog* d) const
+{
+ return restoreWindowGeometry(d);
+}
+
+void GeometrySettings::saveWindowGeometry(const QWidget* w)
{
set(m_Settings, "Geometry", geoSettingName(w), w->saveGeometry());
}
-bool GeometrySettings::restoreGeometry(QWidget* w) const
+bool GeometrySettings::restoreWindowGeometry(QWidget* w) const
{
if (auto v=getOptional<QByteArray>(m_Settings, "Geometry", geoSettingName(w))) {
w->restoreGeometry(*v);
+ ensureWindowOnScreen(w);
return true;
}
return false;
}
+void GeometrySettings::ensureWindowOnScreen(QWidget* w) const
+{
+ // users report that the main window and/or dialogs are displayed off-screen;
+ // the usual workaround is keyboard navigation to move it
+ //
+ // qt should have code that deals with multiple monitors and off-screen
+ // geometries, but there seems to be bugs or inconsistencies that can't be
+ // reproduced
+ //
+ // the closest would probably be https://bugreports.qt.io/browse/QTBUG-64498,
+ // which is about multiple monitors and high dpi, but it seems fixed as of
+ // 5.12.4, which is shipped with 2.2.1
+ //
+ // without being to reproduce the problem, some simple checks are made in a
+ // timer, which may mitigate the issues
+
+ QTimer::singleShot(100, w, [w] {
+ const auto borders = 20;
+
+ // desktop geometry, made smaller to make sure there isn't just a few pixels
+ const auto originalDg = env::Environment().metrics().desktopGeometry();
+ const auto dg = originalDg.adjusted(borders, borders, -borders, -borders);
+
+ const auto g = w->geometry();
+
+ if (!dg.intersects(g)) {
+ log::warn(
+ "window '{}' is offscreen, moving to main monitor; geo={}, desktop={}",
+ w->objectName(), g, originalDg);
+
+ // widget is off-screen, center it on main monitor
+ centerOnMonitor(w, -1);
+
+ log::warn("window '{}' now at {}", w->objectName(), w->geometry());
+ }
+ });
+}
+
void GeometrySettings::saveState(const QMainWindow* w)
{
set(m_Settings, "Geometry", stateSettingName(w), w->saveState());
@@ -771,12 +832,17 @@ void GeometrySettings::setModInfoTabOrder(const QString& names)
void GeometrySettings::centerOnMainWindowMonitor(QWidget* w)
{
const auto monitor = getOptional<int>(
- m_Settings, "Geometry", "MainWindow_monitor");
+ m_Settings, "Geometry", "MainWindow_monitor").value_or(-1);
+
+ centerOnMonitor(w, monitor);
+}
+void GeometrySettings::centerOnMonitor(QWidget* w, int monitor)
+{
QPoint center;
- if (monitor && QGuiApplication::screens().size() > *monitor) {
- center = QGuiApplication::screens().at(*monitor)->geometry().center();
+ if (monitor >= 0 && monitor < QGuiApplication::screens().size()) {
+ center = QGuiApplication::screens().at(monitor)->geometry().center();
} else {
center = QGuiApplication::primaryScreen()->geometry().center();
}
@@ -1887,15 +1953,3 @@ void DiagnosticsSettings::setCrashDumpsMax(int n)
{
set(m_Settings, "Settings", "crash_dumps_max", n);
}
-
-
-GeometrySaver::GeometrySaver(Settings& s, QDialog* dialog)
- : m_settings(s), m_dialog(dialog)
-{
- m_settings.geometry().restoreGeometry(m_dialog);
-}
-
-GeometrySaver::~GeometrySaver()
-{
- m_settings.geometry().saveGeometry(m_dialog);
-}
diff --git a/src/settings.h b/src/settings.h
index cd478a5b..b5366911 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -41,20 +41,6 @@ class ServerList;
class Settings;
-// helper class that calls restoreGeometry() in the constructor and
-// saveGeometry() in the destructor
-//
-class GeometrySaver
-{
-public:
- GeometrySaver(Settings& s, QDialog* dialog);
- ~GeometrySaver();
-
-private:
- Settings& m_settings;
- QDialog* m_dialog;
-};
-
// setting for the currently managed game
//
@@ -141,8 +127,11 @@ public:
void resetIfNeeded();
- void saveGeometry(const QWidget* w);
- bool restoreGeometry(QWidget* w) const;
+ void saveGeometry(const QMainWindow* w);
+ bool restoreGeometry(QMainWindow* w) const;
+
+ void saveGeometry(const QDialog* d);
+ bool restoreGeometry(QDialog* d) const;
void saveState(const QMainWindow* window);
bool restoreState(QMainWindow* window) const;
@@ -182,6 +171,12 @@ public:
private:
QSettings& m_Settings;
bool m_Reset;
+
+ void saveWindowGeometry(const QWidget* w);
+ bool restoreWindowGeometry(QWidget* w) const;
+
+ void ensureWindowOnScreen(QWidget* w) const;
+ static void centerOnMonitor(QWidget* w, int monitor);
};
@@ -764,4 +759,28 @@ private:
DiagnosticsSettings m_Diagnostics;
};
+
+// helper class that calls restoreGeometry() in the constructor and
+// saveGeometry() in the destructor
+//
+template <class W>
+class GeometrySaver
+{
+public:
+ GeometrySaver(Settings& s, W* w)
+ : m_settings(s), m_widget(w)
+ {
+ m_settings.geometry().restoreGeometry(m_widget);
+ }
+
+ ~GeometrySaver()
+ {
+ m_settings.geometry().saveGeometry(m_widget);
+ }
+
+private:
+ Settings& m_settings;
+ W* m_widget;
+};
+
#endif // SETTINGS_H