Godot Version
Godot 4.3
Question
(Apologies if this is in the wrong topic)
I’m trying to make a thing that renders over the desktop (it’s a little guy that runs across the bottom of the screen), but making the window transparent sometimes works and sometimes doesn’t (displaying as a black background when it doesn’t work). I’m trying to work out what causes it to not work when it does (things I’ve tried below).
Apologies for the “Photo of a Screen” here - the window doesn’t render when being Print-Screened (which is its whole own kettle of fish)
Currently I have:
- Per Pixel Transparency Allowed in the Project Settings and called in code
- The Window spawning as a child of another “Control Panel” window
- The Transparent Flag on the Window set to True, both in the Editor AND in the code when it is spawned
- The Window is borderless, and set to be a specific size when spawned in (slightly smaller than the monitor size)
- The Window is set to be Always On Top
Apologies for the “picture of a screen” here - the window doesn’t show up in Print-Screens, which is its whole own kettle of fish
When it works:
- When a second screen is attached and it’s initialised on that second screen
- SOMETIMES when there is no second screen attached (on the only screen)
- Weirdly, both in the preview of the window when “Alt-Tabbing” and the actual window when in that Alt-Tab menu, but it breaks again when you leave the Alt-Tab
This is it working when in the Alt-Tab menu
When it doesn’t work:
- When a second screen is attached and it’s initialised on the main screen
- SOMETIMES when there is no second screen attached
Any ideas as to why this is happening? Or a way to make it not happen?
Hmmm, this is a lot to unpack I think I can suggest some things but is there any code you can share?
Like you setting all the flags and everything? Just want to double check things.
Sure!
In the code for the “Control Panel” to call the window:
func _ready() -> void:
get_viewport().gui_embed_subwindows = false
func _on_deploy_runners_pressed() -> void:
var monitorSize = DisplayServer.screen_get_size()
var window = load("res://runner_window.tscn")
var viewWindow = window.instantiate()
viewWindow.connect("close_requested",_close_window)
viewWindow.transparent = true
viewWindow.borderless = true
viewWindow.name = "RunnerWindow"
viewWindow.size = monitorSize
$WindowHolder.add_child(viewWindow)
And in the “Runner Window” scene (which has a base Window node, a Sprite2D child (the pavement) and a Node child to hold the runners, when they’re spawned in)
func _ready() -> void:
DisplayServer.window_set_flag(DisplayServer. WINDOW_FLAG_TRANSPARENT, true)
self.transparent=true
The first line here was added as part of me trying to fix this, so it isn’t doing anything
I’m in Compatibility Rendering Mode, for reference
Further Update - it works on one monitor when the window is set to Fullscreen (as opposed to Windowed but made large as I had it on) - I’m just hooking up the second monitor to try and work out if it still works there
So I worked out how to fix this, but still not fully sure on the WHY, so leaving this open for 24 hours just in case.
It seems that when the window is set to be the same size as the monitor and always on top, it automatically switched to “Exclusive Fullscreen” mode - aka “Stop rendering anything behind this.”
The fix was to set it to NOT be the same size as the monitor - both one Pixel larger and one Pixel smaller worked for me
1 Like
Congrats!
That was actually going to be one of my suggestions since I read somewhere that when the window is close to full-screen size or crosses monitor boundaries, some operating systems struggle to handle transparency. If your window spans multiple monitors or is near the edges of the monitor, this might be causing the issue.
And keeping the window slightly smaller than the total screen size and positioned within one monitor boundary would maybe help.