Re: 10.7 Full-Screen transition animation corrupts my UI - how to avoid?

  • (BTW, your reply from which I'm quoting below wasn't CC'ed to the list, but it looks like it was intended for the list. I'll let you go ahead and repost if that was your intention.)

    On Jul 22, 2012, at 11:56 , Motti Shneor wrote:

    > One thing you say raises a question, though. How can minContentSize: "override" the "minSize" ? these are two different sizes, isn't it?. I'm using setContentMinSize because I don't know how to calculate the "minSize" which also depends on the presence of tool-bar, title-bar and other window parts that can change with versions of the OS. Am I wrong here? should I directly call setMinSize/setMaxSize on my windows?
    >
    > I assumed that the window's minSize is calculated from its contentMinSize, plus the other parts of the window.

    Here's what the documentation for 'setMinSize:' says:

    > The setContentMinSize: method takes precedence over this method.

    I took this to mean that the window maintains separate 'minSize' and 'contentMinSize' properties, each of which can be set or not set, and if they're both set, 'contentMinSize' wins. However, I just tried it in an existing project, and this isn't what happens. (See below.)

    You can "convert" between window frame and content rect using these class methods:

    + (NSRect)contentRectForFrameRect:(NSRect)windowFrame styleMask:(NSUInteger)windowStyle
    + (NSRect)frameRectForContentRect:(NSRect)windowContentRect styleMask:(NSUInteger)windowStyle

    However, things are a bit messier than that, since these methods obviously don't take the toolbar into account. The NSToolbar programming guide says you can calculate the toolbar height by subtracting "the height of the window’s content view from the window’s height", and gives this sample code (in part):

    windowFrame = [NSWindow contentRectForFrameRect:[window frame] styleMask:[window styleMask]];
    toolbarHeight = NSHeight(windowFrame) - NSHeight([[window contentView] frame]);

    Interestingly, this means that the window's content rect is *not* the same thing as the window's content view's frame rect. That's probably what's going wrong in your code -- looking back at what you posted, I think you're assuming that contentMinSize is the content view frame's min size, but it isn't.

    Furthermore, there's an additional level of messiness, in general. The documentation's 2009-era statement about the toolbar height is (I think) now incorrect, because windows now also have a contentBorderThickness property, potentially at the top and bottom of the window, which needs to be taken into account.

    So, here's what I found in testing, with an existing project that has a window minimum height that shows as 500 in IB, and which has a toolbar permanently visible, and which is given a contentBorderThickness of 30 for the bottom border in the window controller's windowDidLoad.

    When I stop at a breakpoint after the window is displayed, contentMinSize.height is 500 and minSize.height is 578. That's a difference of 78.

    If I set contentMinSize.height to 700 (i.e. +200), minSize.height changes to 778. Same difference of 78. However, if I set minSize.height to 778, then contentMinSize.height changes to 756 *and minSize.height actually changes to 834*. Still a difference of 78, so the two properties are still linked, but I have no idea where 756/834 came from. Did the contentMinSize property "take precedence"?

    Er, QED, proof left as an exercise to the reader, gotta go, let's do lunch, my people will call your people. ;)
  • Hi Quincy, and thanks. You're were right, and I forgot to send my post to the mailing-list (late night programming). I already redirected the message to the list.

    In the mean time --- I think you dug deep, maybe too-deep for what I need. The latest docs for setContentsMinSize are clear enough , and render it the right API for me.

    Here are the docs.
    --------------
    setContentMinSize:
    Sets the minimum size of the window’s content view in the window’s base coordinate system.

    - (void)setContentMinSize:(NSSize)contentMinSize
    Parameters
    contentMinSize
    The minimum size of the window’s content view in the window’s base coordinate system.
    Discussion
    The minimum size constraint is enforced for resizing by the user as well as for the setContentSize: method and the setFrame... methods other than setFrame:display:and setFrame:display:animate:. This method takes precedence over setMinSize:.
    -------------

    I don't really care about the complicated relation between toolbar, contentBorderThickness, Window title-bar, window shadows and so on. My constraints strictly apply to my content-view. That's where I need the system to protect me, and that's what's promised by the API.

    To verify that, I have been measuring my window content-view size externally, after user drag-resizes it to minimum, and it reaches the exact size I expect - i.e. my content-view can only shrink to my window's "contentMinSize". This works.

    HOWEVER --- it is also clear from the docs that animations, by default, IGNORE this constraint. Of course a standard animation won't first ask a window "what is your min-size". It will simply animate it using a series of setFrame:display:animate: calls, and by the way ruin my UI.

    My question is two-fold.
    1. Who's responsibility is this, Apple or mine, to "protect" my window from the destructive animation.
    2.  Suppose "Apple" is not going to help, What strategy can best (and simplest) serve me in doing this. Currently, I see these options:
    a. replacing the animation with custom animation that doesn't impose small sizes on the content-view.
    b. somehow making the standard animation work on a "snapshot" image of the window's contents instead of actually resizing the view-hierarchy again and again (how can one do this?)
    c. Find the "secret little thing" that prevents this nasty bug from happening in OTHER applications :)

    Any ideas?

    On 23 ביול 2012, at 00:25, Quincey Morris wrote:

    > (BTW, your reply from which I'm quoting below wasn't CC'ed to the list, but it looks like it was intended for the list. I'll let you go ahead and repost if that was your intention.)
    >
    > On Jul 22, 2012, at 11:56 , Motti Shneor wrote:
    >
    >> One thing you say raises a question, though. How can minContentSize: "override" the "minSize" ? these are two different sizes, isn't it?. I'm using setContentMinSize because I don't know how to calculate the "minSize" which also depends on the presence of tool-bar, title-bar and other window parts that can change with versions of the OS. Am I wrong here? should I directly call setMinSize/setMaxSize on my windows?
    >>
    >> I assumed that the window's minSize is calculated from its contentMinSize, plus the other parts of the window.
    >
    > Here's what the documentation for 'setMinSize:' says:
    >
    >> The setContentMinSize: method takes precedence over this method.
    >
    > I took this to mean that the window maintains separate 'minSize' and 'contentMinSize' properties, each of which can be set or not set, and if they're both set, 'contentMinSize' wins. However, I just tried it in an existing project, and this isn't what happens. (See below.)
    >
    > You can "convert" between window frame and content rect using these class methods:
    >
    > + (NSRect)contentRectForFrameRect:(NSRect)windowFrame styleMask:(NSUInteger)windowStyle
    > + (NSRect)frameRectForContentRect:(NSRect)windowContentRect styleMask:(NSUInteger)windowStyle
    >
    > However, things are a bit messier than that, since these methods obviously don't take the toolbar into account. The NSToolbar programming guide says you can calculate the toolbar height by subtracting "the height of the window’s content view from the window’s height", and gives this sample code (in part):
    >
    > windowFrame = [NSWindow contentRectForFrameRect:[window frame] styleMask:[window styleMask]];
    > toolbarHeight = NSHeight(windowFrame) - NSHeight([[window contentView] frame]);
    >
    > Interestingly, this means that the window's content rect is *not* the same thing as the window's content view's frame rect. That's probably what's going wrong in your code -- looking back at what you posted, I think you're assuming that contentMinSize is the content view frame's min size, but it isn't.
    >
    > Furthermore, there's an additional level of messiness, in general. The documentation's 2009-era statement about the toolbar height is (I think) now incorrect, because windows now also have a contentBorderThickness property, potentially at the top and bottom of the window, which needs to be taken into account.
    >
    >
    > So, here's what I found in testing, with an existing project that has a window minimum height that shows as 500 in IB, and which has a toolbar permanently visible, and which is given a contentBorderThickness of 30 for the bottom border in the window controller's windowDidLoad.
    >
    > When I stop at a breakpoint after the window is displayed, contentMinSize.height is 500 and minSize.height is 578. That's a difference of 78.
    >
    > If I set contentMinSize.height to 700 (i.e. +200), minSize.height changes to 778. Same difference of 78. However, if I set minSize.height to 778, then contentMinSize.height changes to 756 *and minSize.height actually changes to 834*. Still a difference of 78, so the two properties are still linked, but I have no idea where 756/834 came from. Did the contentMinSize property "take precedence"?
    >
    > Er, QED, proof left as an exercise to the reader, gotta go, let's do lunch, my people will call your people. ;)
    >

    Motti Shneor
    e-mail: <motti.shneor...>
    phone: +972-8-9267730
    mobile: +972-54-3136621
    ----------------------------------------
    Ceterum censeo Microsoftinem delendam esse
previous month july 2012 next month
MTWTFSS
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
Go to today