Odd auto-resizing of window


#1

I'm trying to figure out why the following doesn't seem to keep the window's size locked to a fixed height:

int prwHeight = pianoRollWindow->getFixedHeight(); // returns 180
pianoRollWindow->setResizeLimits(640,
                                     prwHeight,   //fixed window Height
                                     Desktop::getInstance().getDisplays().getMainDisplay().userArea.getWidth(),
                                     prwHeight);    
pianoRollWindow->setResizable(true, true); 
pianoRollWindow->setUsingNativeTitleBar( true );

 

For whatever reason, as soon as I click the title of the window, the window shrinks to height=141.   This only happens on windows.   i don't have this problem on OS X.   I'm using windows 8.1.    Does anyone have any ideas where to look?   

I thought that "setUsingNativeTitleBar() might have something to do with it, but when I comment that line out, the ability to resize the window disappears. 


#2

Can't think of anything obvious - maybe try putting a breakpoint in the resize method and see what's actually doing it?


#3

well, theres this: 

void PianoRollWindow::resized() {
    //this window always displays 88 keys
    int keyHeight = 108;
    keyboard->setAvailableRange(21, 21+87); //A0 - C8
    //std::cout << "Keyboard Width: " << getWidth() / 52.f << "\n";
    keyboard->setKeyWidth( (getWidth()-3) / 52.f );
    keyboard->setBounds(1, getHeight()-keyHeight, getWidth()-2, keyHeight);
    keyboard->setOctaveForMiddleC(4);
    keyboard->setColour(MidiKeyboardComponent::keyDownOverlayColourId, defaultNoteOnColor);
    keyboard->setScrollButtonsVisible( false );

    if (windowedMode) {
        //setSize(getWidth(), getFixedHeight());
        int h = getHeight();
        h = h;    //TODO: whenever we click the windows version and move it, the window shrinks to h=141
        setSize(getWidth(), getFixedHeight());
        std::cout << "pianoRollWindow height: " << getHeight() << "\n";
    }
    /*
     1303 is the width of our pianoRollWindow when it lines up perfectly
     with the keyboard in PianoRollView's default size.
     */
}

and this: 

void MainContentComponent::resized()
{
    std::cout << "MainContentComponent resized()\n";
    //
    if( menuBar && manuscriptWindow && chordNameView && mainWindow ) {
        this->setSize( mainWindow->getWidth(), mainWindow->getHeight() );
        menuBar->setBounds( 0, 0, mainWindow->getWidth(), 20 );
        if( singleViewMode ) {
            chordNameView->setBounds( manuscriptWindow->getWidth(),
                                     menuBar->getHeight(),
                                     getWidth() - manuscriptWindow->getWidth(),
                                     getHeight() - menuBar->getHeight() - pianoRollWindow->getHeight() );
            chordNameView->setChordNameYOffset( manuscriptWindow->getTopStaffLineY() );
        } else { // otherwise, leave it where useSeparateWindows() sets it
            chordNameView->setBounds( 0,
                                     menuBar->getHeight(),
                                     getWidth(),
                                     getHeight() - menuBar->getHeight() );
        }
    }
}

and finally this: 

void MainContentComponent::displaySeparateWindows() {
    mainWindow->setName( "Chord Names" );
    //can resize in split view mode
    mainWindow->setResizable(true, true);
    mainWindow->setResizeLimits(400,
                                300,
                                Desktop::getInstance().getDisplays().getMainDisplay().userArea.getWidth(),
                                Desktop::getInstance().getDisplays().getMainDisplay().userArea.getHeight() );
    mainWindow->setSize( 400, 300 );
    //setSize( 300, 300 );
    menuBar->setBounds( 0, 0, getWidth(), 20 );
    chordNameView->setBounds( 0,
                             menuBar->getHeight(),
                             getWidth(),
                             getHeight() - menuBar->getHeight() );
    chordNameView->setChordNameXOffset( 30 );
    chordNameView->setChordNameYOffset( 30 );
    chordNameView->setWindowMode( true );
    pianoRollWindow = new PianoRollWindow( /*state*/ );
    int desktopW = Desktop::getInstance().getDisplays().getMainDisplay().userArea.getWidth();
    int desktopH = Desktop::getInstance().getDisplays().getMainDisplay().userArea.getHeight();
    int prwHeight = pianoRollWindow->getFixedHeight();
    pianoRollWindow->setResizable(true, true);
    pianoRollWindow->setUsingNativeTitleBar(true);
    //pianoRollWindow->setBounds(desktopW/2, desktopH/2, 1000, prwHeight);
    pianoRollWindow->setResizeLimits(640,
                                     prwHeight,   //fixed window Height
                                    Desktop::getInstance().getDisplays().getMainDisplay().userArea.getWidth(),
                                     prwHeight);
    pianoRollWindow->setVisible( true );
    pianoRollWindow->toFront( true );
    pianoRollWindow->setWindowedMode(true);
  
    manuscriptWindow = new ManuscriptView();
    manuscriptWindow->setBounds(desktopW/2, desktopH/2, 500, 448);    //this should go in resized()
    manuscriptWindow->setUsingNativeTitleBar( true );
    manuscriptWindow->setResizeLimits(250, 181, desktopW, desktopH);
    manuscriptWindow->setResizable( true, true );
    manuscriptWindow->setFullScreen(false);
    manuscriptWindow->setVisible( true );
    manuscriptWindow->toFront( true );
    //positioning
    pianoRollWindow->setTopLeftPosition(desktopW/2 - pianoRollWindow->getWidth()/2, 100 );
    manuscriptWindow->setTopLeftPosition( desktopW/2 - manuscriptWindow->getWidth()/2,
                                         pianoRollWindow->getScreenY() + pianoRollWindow->getHeight() + 
                                         manuscriptWindow->getTitleBarHeight() );
    mainWindow->setTopLeftPosition( desktopW/2 - mainWindow->getWidth()/2,
                                   manuscriptWindow->getScreenY() + manuscriptWindow->getHeight() + 
                                   mainWindow->getTitleBarHeight() );
    setGlobalKey( currentKey );
}

that's it as far as calls to changing the pianoRollWindow's size anywhere in the project.    Is it possible to get the windows 8 native view dimensions?  i think it's related to that, bceause of the setUsingNativeTitleBar() method being the toggle which controls if I can resize the window or not when it's it's own separate documentWindow.  maybe the size of the window created by Windows8 is different than the size JUCE is trying to create, and once the documentWindow is moved, windows8 or JUCE realizes this, and corrects? 


#4

I vaguely remember seeing funny behaviour here. Does it help to call setUsingNativeTitleBar() before you do any of the sizing?


#5

Ok, i think i found where it's happening:

 

the call stack looks as follows:

MainContentComponent::displaySeparateWindows()

with execution paused on the line:

pianoRollWindow->setBounds(desktopW /2, desktopH/2, 1000, prwheight);

ResizableWindow::setResizeLimits( 640, 180, 1786, 180 ) comes next in the callstack, with the line

defaultConstainer.setSizeLimits( 640, 180, 1786, 180 )

the next line is setBoundsConstrained( getBounds() );

This line leads to the next item in the callstack: 

ResizableWindow::setBoundsConstrained( const Rectangle<int>& newBounds) 

When I mouse over newBounds, the values for the rect are: 

{pos={x=0,y=31} w=624 h = 141 }

So, the call to getBounds() is returning the 141 for some reason, instead of returning 180.  

Let's take a look at what defaultConstrainer.setSizeLimits() does:

a bunch of calls to jmax() set everything in the default constrainer to what is expected..

getBounds returned (0,0,128,128), then we do constrainer->setBoundsForComponent()

somehow, we hit ComponentPeer* Component::getPeer(), where flags.hasHeavyweightPeerFlag is true. 

Eventually we end up on BorderSize<int> getFrameSize(), which returns a window border of (31, 8, 8, 8 ) 

next we arrive in ComponentBoundsConstrainer::setBoundsForComponent() on lines 130 in juce_ComponentBoundsConstrainer

    border.addTo (bounds);

    checkBounds (bounds,
                 border.addedTo (component->getBounds()), limits,
                 isStretchingTop, isStretchingLeft,
                 isStretchingBottom, isStretchingRight);

    border.subtractFrom (bounds);

if I place watches on the variables 'border', 'bounds', and 'limits', and I step thru each line starting with border.addTo( bounds );

        return Rectangle<ValueType> (original.getX() - left, //0 - 8 = -8
                                     original.getY() - top,  //0 - 31  = -31
                                     original.getWidth() + (left + right), //128 + 8 + 8=144
                                     original.getHeight() + (top + bottom)); //128 + 31 + 8=167

we get a rectangle 'bounds' = { x=-8, y=-31, w=144, h=167 }

checkBounds is called with the following params: 

ComponentBoundsConstrainer::checkBounds( {pos={x=-8 y=-31 } w=144 h=167 }, //bounds
                                         {pos={x=-8 y=-31 } w=144 h=167 }, //border.addedTo(component->getBounds())
                                         {pos={x=0 y=0} w=1786 h=882 }, //limits
                                          false, false, false, false );

line 178 changes bounds.width from 144 to 640

line 183 changes bounds.height from 167 to 180

line 197 changes bounds.Y from -31 to 0

border.subtractedFrom(bounds) changes bounds from { x=-8, y=0, w=640, h=180 } to { x=0, y=31, w=624, h=141 } 

so now we call applyBoundsToComponent(), which calls component->setBounds( bounds ) with this height of 141 instead of 180.  

So, somehow, 180 was converted to 141 by way of the window border being {31, 8, 8, 8 }.   180 - (31 + 8) =  141. 

 

With all that said, the solution seems to be to change prwHeight to be: 

int prwHeight = pianoRollWindow->getFixedHeight(); 
#if JUCE_WINDOWS
  prwHeight += pianoRollWindow->getBorderThickness().getTopAndBottom();
#endif

Unfortunately, getTopAndBottom() returns {0, 0, 0, 0}.  When i click on my pianoRollWindow to resize it, it stopped shrinking vertically, but as soon as I try to resize it (increase the width, cuz it's supposed to have a fixed height), it's like the component scales itself inside the Window, so it'll still be 180 pixels high, in a space that is only 180-31-8 pixels tall.   it's really strange. 


#6

ok, so the whole time I was never calling setSize().  I was calling setResizeLimits() and setBounds(), but that's it lol SMH!!!!!   

 

it's always something simple.


#7

Hope you didn't tear all your hair out yet :)