Default monitor doesn't fit me


#1

Hi,

I’m back again for a stupid request but it’s really painful defaut behaviour.
Is there a way to set the main monitor index ?

Currently in my dual monitor setup, the monitor with index 1 is not the “main” monitor, but Juce default to popping its dialog on it.
I’ve fixed this everywhere in my code (thus I can’t use centreWithSize / kiosk-mode and co), but as soon as I need to add a dialog, I forget about this again, or I simply can’t change it (like file browser dialog).

As both Linux and Windows returns monitor indexed by a number, I don’t get why Juce doesn’t respect this.
When I list monitors with Xinerama functions, I do get the same index as I’ve specified in my xorg.conf (and the API is clear, it’s an screen number, not an index in a table).
Currently, it’s a painful parse all monitor and find the one with the right resolution (which is, IMHO very hacky and will break for similar resolution monitors) to figure out the monitor index.

Here’s a quick fix for juce_Desktop.cpp

// Line 115
const Rectangle<int> Desktop::getMainMonitorArea (const bool clippedToWorkArea) const throw()
{
    return getDisplayMonitorCoordinates (defaultMonitorIndex, clippedToWorkArea);
}

void Desktop::setDefaultMonitorIndex(const int index) 
{
    defaultMonitorIndex = index;
}

// Append defaultMonitorIndex to the members and initialize to 0

Ideally, I would prefer Juce to respect the same order as what is said in the configuration file.


#2

I’ts certainly supposed to work correctly, and definitely works on mac + windows… Looking at the linux code, it does sort the screens by the screen_number value that xinerama returns, which I’d have expected to reflect the correct order…? (of course in typical linux style, there’s zero documentation for the XineramaScreenInfo struct, so hard to know what that number really represents)


#3

Well, there is an asumption in juce that screen 0 position is (0x0 => screen0.width x screen0.height), which is not my case.
Like here:

Component.cpp : 3141
 const Rectangle<int> Component::getParentMonitorArea() const
{
        return Desktop::getInstance()
                .getMonitorAreaContaining (relativePositionToGlobal (Point<int> (getWidth() / 2,
                                                                                 getHeight() / 2)));
}
(or in the previous code snippet I've posted)

My monitor 0 is on the right of the monitor 1 (I can’t change this).

I doubt it works on Mac or Windows, or only in the case if the 2nd monitor is on the right of or below the first (not above or on the left).
Anyway, I think using a global monitor index as the main monitor would at least allow to fix this (so the code should read:

Component.cpp : 3141
 const Rectangle<int> Component::getParentMonitorArea() const
{
        return Desktop::getInstance()
                .getMonitorAreaContaining (Destkop::getInstance().getMainMonitorArea().getPosition() + relativePositionToGlobal (Point<int> (getWidth() / 2,
                                                                                 getHeight() / 2)));
}

#4

In fact, the more I read about this, the more obvious the assumption is everywhere.
centreWithSize centre on the (0x0 => min(parent.width, mainMonitor.Width), min(parent.height, mainMonitor.Height))

Ok, would you accept such change as it doesn’t change anything when main monitor is at (0x0) ?

void Component::centreWithSize (const int width, const int height)
{
    setBounds (Desktop::getMainMonitorArea().getX() + (getParentWidth() - width) / 2,
               Desktop::getMainMonitorArea().getY() + (getParentHeight() - height) / 2,
               width,
               height);
}

#5

Components in general aren’t designed to be aware of monitor positions, and centreWithSize() wasn’t designed for use on the desktop - it expects to be inside a parent component, where the origin is always at (0, 0).

In fact it does all work ok on windows + mac because they always ensure that the main monitor contains the origin, regardless of the monitor positions, which seems very sensible to me.

Your suggestion would break any non-desktop comps, but it could be made a bit smarter, e.g.

if (isOnDesktop()) setBounds (Desktop::getMainMonitorArea().getCentreX() - width / 2, Desktop::getMainMonitorArea().getCentreY() - height / 2, width, height); else setBounds ((getParentWidth() - width) / 2, (getParentHeight() - height) / 2, width, height);


#6

…actually, a cleaner approach would be something like a Component::getParentBounds() call, which would either just give the normal parent bounds, or the main monitor… I’ll have a think.


#7

[quote=“jules”]Components in general aren’t designed to be aware of monitor positions, and centreWithSize() wasn’t designed for use on the desktop - it expects to be inside a parent component, where the origin is always at (0, 0).
[/quote]
All internal Juce’s dialog (FileChooser, AlertWindow, …) don’t have a parent component set when they call centreWithSize (debugged them, so I’m sure about this, parentComponent_ is null).
They somehow fallback to the main monitor size (through getParentMonitorArea) but ignore its position, just use the size.

Maybe Windows allow negative coordinates for a monitor. I will check. If it’s not the case, I wonder how the main monitor put on the right of the second monitor (with windows’s term, that is the 2 inside the monitor icon in Desktop properties) could be at 0x0.

As soon as I get home, I’ll try this and confirm.


#8

Isn’t the role of getParentMonitorArea() ?


#9

Yes, it does, and so does the mac.

I’ll take a look at this today, and see if I can make it a bit more robust.