How to make a background window for my app

I like to have a fullscreen background that’s visible when my app is front. That window shall stay behind all other windows of my app, at all times, even when one clicks on it.

The idea is that while my app is active, I want the windows of all other apps to remain hidden under my app’s background window, so that the user is fully focused on the windows my app presents.

Basically, it should behave similar to if you only have the Finder running: There is a background (the Desktop window), on which appear all the Finder’s windows.

While I can initially make such a fullscreen window appear in my app, the problem is that as soon as the user clicks on that background window, it comes to front, hiding all other windows my app is showing.

Simply returning true from the MouseDown event isn’t helping. And trying to bring the window all to the back in its Activate event is a pain, too, as I’d have to go thru all the other windows, calling Show for each, which leads to a lot of flicker.

I’d rather keep the bg window from even coming to front.

I need this only for OSX, so if there’s a Cocoa (MBS, too) way to do it, that’s fine.

What is sounds like you are trying to do is emulate the old “MDI Interface” that windows has/had?

Why do you need a window to hide things behind? Why not just “HIDE” them? and show them when appropriate?

Yes, like MDI.

How shall I hide all other apps’ windows? They’re not under my control.

And even I did, there would still be all the icons on the desktop visible.

I want to provide a clean white background when my app is front (well, with a branding logo in it).

I think all I need is to intercept any clicks to the window so that the window is not brought to front. But how?

Curious if this for your personal use or for a shippable app ?
If its for a shippable app I’d make that a user preference. And make it possible to run full screen.
“MDI for the mac” sounds nasty

Missed the “other apps” part…
But there really is no way to do it… even if you managed to get a window that covered the screen, the taskbar is still there, and clicking on it will bring that “other app” to the forefront… And personally I’d not be happy with an app that commandeered by screen like that. (Oh… another monkey wrench for you :slight_smile: , what if there are MULTIPLE monitors???)

Geez guys, please don’t question my UI decisions. It’s for a special application in the vertical market where this is simply necessary. And the app will still have a menu and there’s be the Dock and you can switch using Spotlight or whatever. That’s really not for discussion here. I’m not a newbie to Mac app programming.

I’ve now decided to ask on SO, maybe that’ll get me a solution: http://stackoverflow.com/questions/37840435/

Isnt this the ‘Kiosk’ scenario?

Huh, not sure. In my understanding, Kiosk mode prevents the user from even switching to other apps. That’s not my goal.

My mind remembers something about ignoring front clicks, but I can’t make a connection.

Predictable

Would seem that you want to have these windows in a layer above all others - and your actual window above the “background” one which are both in front of everything else

And yes you can hide other apps
see SharedWorkspace : hideOtherApplications

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSWorkspace_Class/index.html

Using hideOtherApplications won’t work because then the user would see the desktop with its icons, not my clean custom background with the branding logo on it.

hideOtherApplications is also the equivalent of cmd-shift-h which I would not appreciate as a user.
Have you looked at window level settings? Maybe there’s an unclickable back level.

Perhaps addChildWindow:ordered: will work? The child window becomes attached to the parent and moves when the parent moves, but the parent always keeps the child in front, even if the parent has focus, if NSWindowOrderingMode is NSWindowAbove.

[code] Declare sub addChildWindowordered lib “AppKit” selector “addChildWindow:ordered:” (win as ptr, child as ptr, mode as uint32)

dim w as new Window2

addChildWindowordered(ptr(self.Handle),ptr(w.Handle),1)[/code]

I think what you want to set is the Window Level.

You can actually put a window behind the desktop or behind the desktop icons (very funny looking) all the way to above the dock and menubar. Uh, well I see the Dock Level is now deprecated. I’m not sure which level is best for you, maybe NSFloatingWindowLevel for the obscuring window and any higher level for your actual windows.

doc for level which has a link to Window Levels which has a link to Window Level Keys.

And here’s my code for setting desktop level https://forum.xojo.com/conversation/post/267743

Will, your “level” link is wrong.

Doh !
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSWindow_Class/#//apple_ref/occ/instp/NSWindow/level

Stupid answer: quit the Finder ?

Setting child relationships is not a good solution because that will make the child windows immovable. But I want the windows of my app still to be movable as usual.

Changing the level of all but the bg window works somewhat. However, that makes all the windows floaters, which is still a bit odd, but workable (for instance, when debugging, those windows would stay in front of the IDE even when breaking into the debugger - I can avoid this by not changing the level when debugging, though).

However, clicking the background window will then still remove the focus from the previous front window.
Now, if I could just find a way to have clicks to the bg window ignored, then I’d be set.

There is no real solution for what you want (just serarch for it in stackoverflow). It will break the user’s expectations, it will not work with multiple monitors, “fullscreening” two or more windows of your application separately will not work, etc.

The only way I can think of would be to have one regular window and inspector panels as “MDI” windows. But even if that would work: either it’s a Kiosk-worthy application or not.

This is a real hammer but you could install a local event monitor for mousedowns and reject those landing on the bg window. I’ve tried it and it works, but I just filtered any X < 500 for the test.

To do a full window hit test could be involved. NSWindow has
+windowNumberAtPoint:belowWindowWithWindowNumber: but I’m not sure how to use it. (Hmm, I guess a loop over the non-bg windows testing w.Bounds.Contains(point) would work).

Or for a bigger hammer you could run the bg window from a helper app where the local monitor can just filter all mousedowns.

Maybe an NSResponder inserted high in the chain could more easily filter the events. It’s been a long time since I used NSResponders and I’m not sure this idea has merit.

I would hope there’s a cleaner, lighter way.