Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to make window transparent? #73

Open
albertwoo opened this issue Nov 3, 2021 · 14 comments
Open

How to make window transparent? #73

albertwoo opened this issue Nov 3, 2021 · 14 comments
Labels
All OS enhancement New feature or request help wanted Extra attention is needed

Comments

@albertwoo
Copy link

No description provided.

@MikeYeager MikeYeager added All OS question Further information is requested labels Nov 11, 2021
@MikeYeager
Copy link
Collaborator

Not sure what you're asking. Do you mean semi-transparent? Or do you mean no chrome (title bar, frame, etc.)? If the latter, try SetChromeless(true).

@albertwoo
Copy link
Author

I want to make things work like this:
image

@MikeYeager MikeYeager added enhancement New feature or request help wanted Extra attention is needed and removed question Further information is requested labels Dec 2, 2021
@MikeYeager
Copy link
Collaborator

This isn't something we have on our roadmap. I'll re-open it in case someone wants to implement it.

@MikeYeager MikeYeager reopened this Dec 2, 2021
@domialex
Copy link

domialex commented May 8, 2022

This could be useful to make overlays with Chromeless set to true.

@flyingpie
Copy link

@albertwoo Perhaps an workaround for getting this effect (note that you can't have only the background transparent, just the window as a whole):

image

User32.cs:

using System;
using System.Runtime.InteropServices;

namespace HelloPhotino.Vue.Native;

public static class User32
{
	[DllImport("user32.dll", SetLastError = true)]
	public static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);

	[DllImport("user32.dll", SetLastError = true)]
	public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

	[DllImport("user32.dll", SetLastError = true)]
	public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

	public const int GWL_EX_STYLE = -20;

	public const int LWA_ALPHA = 0x2;

	public const int WS_EX_LAYERED = 0x80000;

	/// <summary>
	/// Makes the entire window of the specified process transparent.
	/// </summary>
	/// <param name="transparency">Desired transparency, value between 0 (invisible) to 100 (opaque).</param>
	public static void SetTransparency(IntPtr windowHandle, int transparency)
	{
		if (windowHandle == IntPtr.Zero) throw new Exception("Process handle zero");

		// Get original window properties
		var props = GetWindowLong(windowHandle, GWL_EX_STYLE);

		// Add "WS_EX_LAYERED"-flag (required for transparency).
		SetWindowLong(windowHandle, GWL_EX_STYLE, props | WS_EX_LAYERED);

		// Set transparency
		var isSet = SetLayeredWindowAttributes(windowHandle, 0, (byte)Math.Ceiling(255f / 100f * transparency), LWA_ALPHA);
		if (!isSet) throw new Exception("Could not set window opacity");
	}
}

Then somewhere before window.WaitForClose():

window.WindowCreated += (s, a) =>
{
	User32.SetTransparency(window.WindowHandle, 50);
};

I've been using this technique for windows-terminal-quake, works quite well.

@philippjbauer
Copy link
Member

@flyingpie thank you for your contribution!

We will look closer into how to implement this on Linux and macOS. We want to release this functionality for all platforms together to prevent inconsistencies between the different OSs.

Your interop code would go into the Photino.Native package and then expose it in the PhotinoDllImports.cs in the Photino.NET project. We will take care of this while preparing the other implementations.

@skyslide22
Copy link

any news on this?
the full transparency mode (without any titlebar) is essencial for my project ...

@Andersen27
Copy link
Contributor

Andersen27 commented May 8, 2024

Implementation for transparent window background on Windows:
Photino.Native: Andersen27/photino.Native@d39809c
Photino.NET: Andersen27@e56d6d6
You need to uncomment .SetChromeless(true) and .SetTransparent(true) lines in Photino.Test->Program.cs to see result.
It's possible to set any alpha-based background color via html's body background-color value.

For Linux the follow functions can be used, but we need to configure GtkWidget _window correctly.
webkit_web_view_get_background_color
webkit_web_view_set_background_color

image

@philippjbauer
Copy link
Member

Hi @Andersen27, thank you for your contribution! We pulled your changes from your fork and it will be part our next release. Would you be able to implement this change for Linux as well and create a PR for us?

@Andersen27
Copy link
Contributor

@philippjbauer I'll try it soon. I will create draft PR for it.
But i need help for MacOS.

@Andersen27
Copy link
Contributor

Andersen27 commented Jun 4, 2024

For Linux i'm doing something like this:
https://webkitgtk.org/reference/webkit2gtk/2.8.3/WebKitWebView.html#webkit-web-view-set-background-color
But it doesn't work.
It seems that the problem is due to the webview, because if you draw another GtkWidget instead, the window background is transparent, as expected. But for webview it is opaque white, and I haven't been able to fix it yet.
Webview background color doesn't change even if the color is opaque, like Gdk.RGBA(0, 1, 1, 1).

@flyingpie
Copy link

@Andersen27 Could you update the repo with the Linux changes?

Also, is this on X11, Wayland, or both?

@Andersen27
Copy link
Contributor

Andersen27 commented Jun 5, 2024

@flyingpie
Testing on Ubuntu 22.04.
Andersen27/photino.Native@b4025c9
(All branch: tryphotino/photino.Native@master...Andersen27:photino.Native:debug_linuxTransparent)

P.S: I'm not C++ developer, so I could made some stupid mistake.

@flyingpie
Copy link

@Andersen27 It seems that the issue is with actually calling the function.

I've left a couple comments in the native repos.

One thing is that SetTransparentEnabled() wasn't actually called yet, the other was that calling it on app start is too early. We need to wait for the webview to load (basically the opposite of what Windows does), and only then call the function.

I'm not sure what the proper place for that would be, but here's an example where I put the init bit under Photino::Show(), to demonstrate that your code indeed works:

image

image

Maybe @philippjbauer can help? :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
All OS enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

7 participants