MousePassthrough for non-same applications?

Godot Version

4.2.1 Mono

Question

I was trying to make a transparent window with pass-through click events but:

GetWindow().MousePassthrough = true

only works for same application windows (I wanted to be for any other application/desktop), and:

GetWindow().MousePassthroughPolygon = null;
///
GetWindow().MousePassthroughPolygon = new []{new Vector2(), new Vector2(), new Vector2()};

is not really available either (the “clickable/unclickable” behavior is correct, but when in pass-through the window gets cut as well)

Intention: I was trying to render 3D meshes on a Transparent background (and transparent window as well ofc) and I already managed to detect the pixel under the cursor (if it’s alpha > .5f it should be clickable, else it should passthrough)

Is it even possible? Or if I have to deal with it at lower level / editing the engine, where should I even begin with?

It looks like currently (on windows) you will need to set your polygon to cover exactly what you want to see/click on. if you want to be able to click through things you can also see you’ll need to deal with the windows API directly, not sure how to do it but it seems possible

1 Like

At last I resolved, using calls to the Windows API in C#

I am not 100% sure of what the things do and why, but it seems to be working

tl;dr if anyone wants to implement something like this

// [... inside a Node inherited class]
// GetActiveWindow() retrieves the handle of the currently active window on the desktop. 
	[DllImport("user32.dll")]
	public static extern IntPtr GetActiveWindow();

	//  SetWindowLong() modifies a specific flag value associated with a window.
	[DllImport("user32.dll")]
	private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
	
	private const int GwlExStyle = -20;
	
	// "Properties" of the window to be set, Layered is to have transparent pixels, Transparent is to make the window click-through
	private const uint WsExLayered = 0x00080000;
	private const uint WsExTransparent = 0x00000020;

	// index reference of the window
	private IntPtr _hWnd;

	public override void _Ready()
	{
		// Get the reference of the game window
		_hWnd = GetActiveWindow();

		// setting the flags of becoming a layered and transparent window
		SetWindowLong(_hWnd, GwlExStyle, WsExLayered | WsExTransparent);
	}

	// Call this method via your preferred detection algorythm (personally I check the 
	// pixel under cursor to have alpha < 0.5f but you do you)
	public void SetClickThrough(bool clickthrough)
	{
		if (clickthrough)
		{
			SetWindowLong(_hWnd, GwlExStyle, WsExLayered | WsExTransparent);
		}
		else
		{
			SetWindowLong(_hWnd, GwlExStyle, WsExLayered);
		}
	}

for reference I used this tutorial for unity (but the C# code is the same so yeah)
Transparent Windows Tutorial

Also ofc I added this to an already transparent window (set in the Project Settings) AND already Always On Top

2 Likes

If you put a minimal project that did this up on github I’m sure other people would be interested in this too :eyes:

Stripped down and very basic, but here we go!
Github: Godot Clickthrough

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.