Which display is this window on?

As far as I can gather, the way to find which display a window is on is to take the Top and Left of the window, and then loop through displays looking for the display that has both of these values within it.

Is this the right approach or am I missing something?

That’s the right approach. Couple of thoughts:

  1. Remember to use Window Bounds, Top and Left are the content area
  2. Use class functions like Rect.Contains(otherRect) to make this super easy (Window.Bounds is a rect!)
1 Like

a window could be at two displays in the middle as example.
rect have also a method Contains(p As Point)

Say you move a window by the right side of its title bar, and you move it way offscreen (to the left side of the display). Your code using left/top will identify the display that is to the left of the “current” display (or none, if the left/top corner is on no display at all (just offscreen)).

Move the window half way off the screen and your top left is not going to be on any screen. I typically use the window centre, which is at least more difficult to get outside of the bounds of the screens.

macOS API has a way of asking which display a window is on, but I’ve never bothered to create a Xojo version.

As I said.

The centre may also be wrong. You could have just 1/4 of the window staying on screen, so the center would be offscreen also.

The MBS plugins did, IIRC.

Agreed. Which is why I said more difficult. You could just detect a nil result and try another part of the screen. At least one corner must be on one screen or another, at least if it got where it is by dragging.

Ultimately, it may not be possible to know and you would have to work out what to do. For example return the window to screen 0.

What I was after, with this thread was to investigate how to be able to place a window on some display, hide it, then show it again later, such that it re-appears on the same display it was hidden from, and in the same place.

What I discover after some investigation is that what should be required to effect this is precisely - nothing. I even have a trivial project with a main window and a button to open a sub-window. I move the sub-window anywhere, and click a button on it which hides it. If I then click the button on the main window again, the sub-window appears just where I left it. No code to determine which display or to alter Top and Left is required.

Except that this doesn’t work in my main app. The sub-windows always re-appear on Display(0), for some reason.

have you looked at inspector behavior default location combobox?
have you disabled implicit instance?

That says Default.

That gives me compilation errors. If I turn that off, I imagine I’ll have to create the window explicitly and save a pointer to it, then use that pointer in all my hide/show. In any case, in my trivial demo app, this works as required.

default means left,top if it appear?
i had more success to position the window if i create a new object.
for most windows i just choose the option parent window.

If you have two screens and the window is across both, you won’t get nil (but you still can get the one where the window isn’t shown; on Mac, a window moved to a given screen won’t appear on other displays).

I think Mac OS has a function to return the screen a window is on. In NSScreen or NSWindow? I don’t remember.

So you’re just calling “MyWindow.Visible=true”, on a window that you previously hidden with “MyWindow.Visible=false” and the window re-appears on display(0), the very same window?

Not if you use a point on the window. It can only be on one screen. If and only if fails I look at other points on the window. Ultimately a window cannot be dragged to a place were all of it is off all displays.

Yes, I said this earlier, you said it you thought it was already available in MBS.

No, I’m using:

Self.Show ()
Self.Hide ()

Window.Visible = false

should hide the window without changing it’s coordinates. Simply setting:

Window.Visible = true

Should put it back were it was. If you are closing the window and then reopening it then there is a window property that can force it to appear on window 0. Check “Default Location” on your window. “Main screen” is one of the options.

I usually use Hide to close the window but keep its properties available to the rest of the application. Show is what’s used to show the window in the first place, so perhaps that is what is causing the change in location, especially with the “Default Location” property.

That option appears to have no useful choice in this context.

If you try visible = true / false, it may solve the problem? Avoiding the use of Show?

Just tried that to no avail. In fact it’s worse:

  1. I put me.Show() and me.Visible=False in the sub-window’s Opening event

  2. When I really want to show it, there’s a method that’s called from all over the app to show that sub-window. In there I’ve commented out me.Show() and added me.Visible = True

  3. In the button on the sub-window to hide it, I’ve commented out me.Hide() and added me.Visible = False

What happens is that having shown and hidden the sub-window once, it refuses to reappear anywhere when shown next, even though in the debugger, one can see that its visiblity is True.

One thing I wonder about is whether this is somehow being messed up by a popup menu class I created, instances of which are inside this sub-window. I made it because an ordinary popupmenu, on the Raspberry Pi, if it is too tall for the window, seems to have no way of being scrolled. So I made my own control for those places in the app where I was likely to have a potentially arbitrarily tall popupmenu. It contains a DesktopWindow. Who knows.

In terms of Visible and Show, I would think there needs to be at least one call to Show in order to show the window in the first place. However, Windows do tend to show themselves when the routine that instantiated them ends.

If you remove your popup class does it all work? Are you saying that the popup menu control contains a DesktopWindow? If so wouldn’t a Container Control be a better option, as it is more of an embeddable window to start with.