Forum Xamarin.Mac

Desktop overlay (transparent fullscreen window)

jensbrakjensbrak Member ✭✭
edited March 1 in Xamarin.Mac

Hi,

(Maybe I'm asking in the wrong place but I have to start somewhere. There are some samples and questions/answers within this area but I'm not getting it to work - think there's more to it in my case. And I'm fully aware it might be more of a xcode/cocoa/platform question, but maybe someone here might know where to point me if that's the case)

I'm trying to write an application that is a desktop overlay (in essence I'm going to "draw on the desktop"). Most examples mention code that set IsOpaque of the window to false and the BackgroundColor to Clear, like so:

public override void ViewWillAppear()
{
    base.ViewWillAppear();
    View.Window.IsOpaque = false;
    View.Window.BackgroundColor = NSColor.Clear;
}

This, along with disabling shadow will for sure make the titlebar transparent. But the content of the window remain black. In the end I'll use SkiaSharp view to render my content but I've tried other views to see if behaviour change. Seems not, still black.

Since it is the area of the view and viewcontroller that is black, I guess there's some content below my view that is in between it and the desktop. Not sure where though, but since my SkiaSharp view behave like some other views I figure it's more of a cocoa/platform issue. Still, maybe someone here knows enough to point me in the right direction?

(side note: did it quite easily on The Other platform, where I just defined a transparency color of the container and used it to clear the view/canvas with)

Answers

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    So bending Cocoa to your will can be difficult, specially when you start going out of the standard UX "box" Apple provides.

    Given the small Xamarin.Mac community, it is unlikely you'll be able to find an answer to your exact issue in C#. The following documentation should provide enough background to help you convert objective-c to C#:

    https://developer.xamarin.com/guides/mac/application_fundamentals/patterns/
    https://developer.xamarin.com/guides/mac/application_fundamentals/mac-apis/

    Often I find that appending "cocoa" to your search term filters out iOS specific answers. Searching google for "cocoa transparent fullscreen" pointed me to:

    https://stackoverflow.com/questions/16779469/cocoa-app-create-transparent-view-on-top-of-all-mac-running-applications

    which points me to https://developer.apple.com/library/mac/#samplecode/FunkyOverlayWindow/Introduction/Intro.html

    which suggests you may need to derive your own NSWindow and do the tricks shown here:

    https://developer.apple.com/library/archive/samplecode/FunkyOverlayWindow/Listings/FunkyOverlayWindow_OverlayWindow_m.html#//apple_ref/doc/uid/DTS10000391-FunkyOverlayWindow_OverlayWindow_m-DontLinkElementID_8

    see initWithContentRect.

  • jensbrakjensbrak Member ✭✭

    @ChrisHamons Thank you so much for taking your time! Much appreciated! Exactly the kind of pointers I'd hope for. Ironically I believe I just stumbled across all of the above links too (after posting here) - leading me to think in the same direction as you are suggesting. However, since it's quite a step for someone just opened up the Cocoa-box I hesitated and thought I might as well ask around a little.

    Not only do I appreciate the links, confirming what I "feared" but even more, the advice upon search terms. See, that's what I find the hardest when trying to find solutions to problems I in domains I don't feel at home in. Know what to look for (or not to look for).

    I've just started to dig into the Mac-world to learn more about how it is working but I was kind of hoping to avoid it - since the whole purpose of going SkiaSharp and Xamarin was to benefit from multi-platform functionality, lol. Then again, my "use case" is not easily fitted within any guidelines or frameworks since it pretty much mixes several things: custom rendering, fullscreen but also desktop visibility. It's easy to do one part but to combine them and do the same on two different platforms. Well, that's the problem right there. Since it was a 'just for fun and to learn some' project it really does not bother me, I'm just surprised it was so easy on Windows and so... not out of the box on Mac.

    Back to topic: I've started to play around with some custom NSWindow classes trying to figure out what's going on underneath the surface. In addition to the links you've mentioned, I also found this project - also Cocoa and Objective-C - that I believe could be useful:

    www.cocoawithlove.com/2008/12/drawing-custom-window-on-mac-os-x.html

  • jensbrakjensbrak Member ✭✭

    A little update... Thanks again @ChrisHamons for encouraging reply, got me going!

    Some of my issues getting things to work was related to me using the Interface Builder. Too much 'under the hood' to be controllable for someone not really knowing all the mechanics behind it. I resorted to a xamarin sample showing how to create a xib-less code directly window (github.com/xamarin/mac-samples/tree/master/MacXibless)

    Combining this with using AlphaValue of the Window I can get a fully transparent window. A bittersweet victory, since that transparency overides anything inside it, including the SkiaSharp GL-rendered content I'd like to show. So I am only half way there. Tried to crank up the alpha of the SKGLView within my transparent window but the window seem to override this.

    I can, if nothing else work, live with say a transparency of 0.5 or something, since it will allow user to see the desktop while also drawing the tools on top of it. It would be a compromise but it would work. Since I do this to learn and understand I'd like to know if it's possible to actually have the window transparent and a selection of its contents too (background of GL view using Clear()) but not everything (the thing I draw on the canvas).

    Guess I have to dig a little further into the inner workings of Cocoa and how it render its contents. But I'm going forward at least, slow but still...

    Sidenote: why does the "xibless" mac sample require a xibfile in the project to work?... (just by asking this question to myself I know I know to little to actually know what I'm doing - fully aware of that. Still want to understand... :smile: )

  • jensbrakjensbrak Member ✭✭

    If I override the ContentView property (but still use it) in my custom NSWindow class, only title bar of window is visible. Contents dissappear completely. Which is another way of verifying that it is actually something that is in between th SKGLView and the NSWindow.

    Guess it's something theme-related that Cocoa inserts. Not let's see if I can interfere with it from Xamarin or not....

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    Sidenote: why does the "xibless" mac sample require a xibfile in the project to work?... (just by asking this question to myself I know I know to little to actually know what I'm doing - fully aware of that. Still want to understand... :smile: )

    Because Cocoa really expects a xib/storyboard file and you have to do non-trivial hacking to convince it otherwise, in particular having a NSMenu is tricky.

    It can be done, but when I wrote the sample years ago I felt like this was the best compromise.

  • jensbrakjensbrak Member ✭✭

    @ChrisHamons said:

    Sidenote: why does the "xibless" mac sample require a xibfile in the project to work?... (just by asking this question to myself I know I know to little to actually know what I'm doing - fully aware of that. Still want to understand... :smile: )

    Because Cocoa really expects a xib/storyboard file and you have to do non-trivial hacking to convince it otherwise, in particular having a NSMenu is tricky.

    It can be done, but when I wrote the sample years ago I felt like this was the best compromise.

    Allright, thanks! I kinda suspected that but still confusing to me, at least initially.
    Getting more confident around my code now and I have tried several different setups to do the app without having to resort to Interface Builder (in my case I do my own interface).

    It gets more and more obvious that whatever I need to address lies somewhere between the Xamarin code and the native code - which indicates that I am far outside of the intended UI functionality. Then again, that was expected. It is a very special kind of use case I'm aiming for. Still, loads of fun but also frustrating. :)

  • jensbrakjensbrak Member ✭✭

    Well, seems to me that this is no longer a xamarin specific issue for me. Finally I understand enough of this to realize what's happening (or not happening).

    I can render a fully transparent window with view on it that has certain things on it visible but all in all is transparent to the background. For instance - a window with a text in it where the text is visible and everything else is transparent. Pretty much as any example on the topic suggest. It's just a matter of using clear color for background for both the window and the textview.

    However, as soon as I replace this with the view I use to render OpenGL, I get a black backgroud of the view. My GL view clears its canvas with a transparent color and this works fine. However, the background of the view is still black - even though the parent window has a clear color (which used fine using the textview). If I change the background color of the parent window to anything but clear, my GL view will allow full transparency to that window color when I clear my canvas.

    Or to put it the other way around. If I use a window with transparent background and render my transparent GL view on it, I will have a black background. If I use a window with blue background and do the same, I will have a blue background when drawing GL on it. And if I use the same transparent window with a textview that has a transparent background - it will be all transparent (part from the text that is).

    So there's something about that SKGLView that prevent the transparency of the parent window to be used. It gets black but it is transparent when the parent window is not transparent. I assume I need to dig further into the Skiasharp parts. I got so distracted by the workings of Cocoa I didn't realize this.


  • jensbrakjensbrak Member ✭✭
    edited March 10

    ...and I can now present the working solution. Subclassing the SKGLView of SkiaSharp and overriding PrepareGL:

            public override void PrepareOpenGL()
            {
                base.PrepareOpenGL();
                OpenGLContext.SurfaceOpaque = false;
            }
    

    This achieved what I initially intended. Sorry for all the confused reasoning above but as I wrote, got distracted by things. I leave my solution here for future reference.

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    🎉

Sign In or Register to comment.