- Ubuntu v22.04
- MSS v7.0.1
- Python 3.10
This issue is practically identical to: Python: Tkinter + MSS = mss.exception.ScreenShotError: XDefaultRootWindow() failed - however, their question is unsolved. For a minimum reproducible example, see there.
How my project functions
I have a project that involves controlling video game automation scripts/macros via a Python GUI. Using the tool goes something like this:
- Run the program, which opens a navigable single-page GUI.
- Select the game you'd like to automate.
- Select the script you'd like to run.
- Configure the options for the script (this involves opening a new Toplevel window in Tkinter).
- Press
Play
to run the script. - System: When the
Play
button is pressed, my program screenshots the video game client to locate its window position as well as various UI element positions. This occurs in a function calledwin.initialize()
. - Optional: The user may pause, resume, or stop the script, or switch to a different script on the fly.
The problem
Please see this video for a demonstration:
The issue I'm experiencing happens between step 4 and 6. Strangely, the first time I open the options menu, select/save my options, and close that little pop-up window, the script will run successfully - i.e., MSS will not encounter an error when screenshotting the game client. If I stop/restart the script (which does not require me to re-select options), it will still work properly. However, if I change the options by opening the pop-up window again, MSS will throw this error when it attempts to screenshot:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.10/tkinter/__init__.py", line 1921, in __call__
return self.func(*args)
File "/home/my_project/env/lib/python3.10/site-packages/customtkinter/widgets/ctk_button.py", line 372, in clicked
self.command()
File "/home/my_project/src/view/info_frame.py", line 139, in play_btn_clicked
self.controller.play_pause()
File "/home/my_project/src/controller/bot_controller.py", line 21, in play_pause
self.model.play_pause()
File "/home/my_project/src/model/bot.py", line 103, in play_pause
if not self.__initialize_window():
File "/home/my_project/src/model/bot.py", line 132, in __initialize_window
self.win.initialize()
File "/home/my_project/src/model/runelite_bot.py", line 47, in initialize
if not super().initialize():
File "/home/my_project/src/utilities/window.py", line 128, in initialize
a = self.__locate_minimap(client_rect)
File "/home/my_project/src/utilities/window.py", line 257, in __locate_minimap
if m := imsearch.search_img_in_rect(imsearch.BOT_IMAGES.joinpath("minimap.png"), client_rect):
File "/home/my_project/src/utilities/imagesearch.py", line 52, in search_img_in_rect
im = rect.screenshot()
File "/home/my_project/src/utilities/geometry.py", line 64, in screenshot
with mss.mss() as sct:
File "/home/my_project/env/lib/python3.10/site-packages/mss/factory.py", line 34, in mss
return linux.MSS(**kwargs)
File "/home/my_project/env/lib/python3.10/site-packages/mss/linux.py", line 297, in __init__
self.root = self.xlib.XDefaultRootWindow(self._get_display(display))
File "/home/my_project/env/lib/python3.10/site-packages/mss/linux.py", line 184, in validate
raise ScreenShotError(f"{func.__name__}() failed", details=details)
mss.exception.ScreenShotError: XDefaultRootWindow() failed
Screenshot error: XDefaultRootWindow() failed, {'retval': <mss.linux.LP_XWindowAttributes object at 0x7f31d8d38ac0>,
'args': (<mss.linux.LP_Display object at 0x7f31d8d38740>,)}
This indicates that the issue has something to do with opening and closing the TkToplevel (pop-up) widget. I cannot explain why this works the first time I select options. From what I can see, the Toplevel widget is being destroyed properly whenever the user closes it or presses the save
button.
Does anyone know what might be going on here?