Repository: spyder-ide/spyder

Issue:
Modal dialog post resolution rescale locks up Spyder
<!--- **PLEASE READ:** When submitting here, please ensure you've completed the following checklist and checked the boxes to confirm. Issue reports without it may be closed. Thanks! --->

### Issue Report Checklist

* [X] Searched the [issues page](https://github.com/spyder-ide/spyder/issues?q=is%3Aissue) for similar reports
* [X] Read the relevant sections of the [Spyder Troubleshooting Guide](https://github.com/spyder-ide/spyder/wiki/Troubleshooting-Guide-and-FAQ) and followed its advice
* [X] Reproduced the issue after updating with ``conda update spyder`` (or ``pip``, if not using Anaconda)
* [ ] Could not reproduce inside ``jupyter qtconsole`` (if console-related)
* [X] Tried basic troubleshooting (if a bug/error)
    * [X] Restarted Spyder
    * [X] Reset preferences with ``spyder --reset``
    * [X] Reinstalled the latest version of [Anaconda](https://www.anaconda.com/download/)
    * [X] Tried the other applicable steps from the Troubleshooting Guide
* [X] Completed the **Problem Description**, **Steps to Reproduce** and **Version** sections below


## Problem Description

When Spyder detects a monitor resolution change it pops up a modal dialog prompting a Spyder restart.  When this dialog is triggered after a laptop shutdown the modal dialog is in the background, hidden behind the main Spyder window and locks up all of Spyder.  The only way to resolve is to force terminate and restart Spyder.


### What steps reproduce the problem?

1.  Connect laptop to an external monitor with resolution different from that of the built-in monitor
2.  Launch Spyder and leave it running
3.  Shut down laptop and disconnect from the external monitor
4. Wake up laptop and log back in - Spyder is now frozen with no means to acknowledge the modal resolution rescaling dialog other than a forced termination and restart

### What is the expected output? What do you see instead?

Modal dialog is in the foreground, or the dialog is not modal.


### Paste Traceback/Error Below (if applicable)
<!--- Copy from error dialog or View > Panes > Internal Console --->

```python-traceback

PASTE TRACEBACK HERE

```

## Versions
<!--- You can get this information from Help > About Spyder...
or (if Spyder won't launch) the "conda list" command
from the Anaconda Prompt/Terminal/command line. --->

* Spyder version: 5.0.5 but also present in 4.2.5
* Python version: 3.8.10
* Qt version: 
* PyQt version: 5.12.3
* Operating System name/version: Windows 10

### Dependencies
<!--- Please go to the menu entry Help > Dependencies,
press the Copy to clipboard button and paste below --->

```
PASTE DEPENDENCIES HERE
```



Discussion:
Hey @GroovyGeek, thanks for reporting. We'll try to fix this in our next version (5.2.0), to be released next month.

Resolving patch:
diff --git a/spyder/plugins/application/container.py b/spyder/plugins/application/container.py
--- a/spyder/plugins/application/container.py
+++ b/spyder/plugins/application/container.py
@@ -17,6 +17,7 @@
 
 # Third party imports
 from qtpy.QtCore import Qt, QThread, QTimer, Signal, Slot
+from qtpy.QtGui import QGuiApplication
 from qtpy.QtWidgets import QAction, QMessageBox, QPushButton
 
 # Local imports
@@ -566,3 +567,12 @@ def show_dpi_change_message(self, dpi):
             self.dpi_messagebox.finished.connect(
                 lambda result: self.handle_dpi_change_response(result, dpi))
             self.dpi_messagebox.open()
+            # Show dialog always in the primary screen to prevent not being
+            # able to see it if a screen gets disconnected while
+            # in suspended state. See spyder-ide/spyder#16390
+            dpi_messagebox_width = self.dpi_messagebox.rect().width()
+            dpi_messagebox_height = self.dpi_messagebox.rect().height()
+            screen_geometry = QGuiApplication.primaryScreen().geometry()
+            x = (screen_geometry.width() - dpi_messagebox_width) / 2
+            y = (screen_geometry.height() - dpi_messagebox_height) / 2
+            self.dpi_messagebox.move(x, y)


Test patch: