Looking for better solution than this old hack

  • My app has floating palettes that generally set [NSPanel setBecomesKeyOnlyIfNeeded:YES]; Most of the time these palettes are therefore inactive, and yet provide a large number of useful controls that work as expected when operated. Problem is, a lot of these controls show the inactive state because the window is inactive. (This isn't actually very consistent, it depends on the control style chosen).

    In the past, I have used a hack to fool controls into thinking they were in a window that was active when it actually wasn't, by subclassing NSPanel and overriding:

    - (BOOL)    _hasActiveControls
    {
    return YES;
    }

    This no longer seems to work since some versions ago, as well as being undocumented, and inapplicable for the App Store and so on.

    I'd like to know if there is a supported way to do this. It seems a bit crazy that floating panels even bother modulating the active state of controls when they are floating and are *always* effectively active, and it looks better and is more usable as well.

    --Graham
  • On 18/07/2012, at 2:27 PM, Graham Cox wrote:

    > This no longer seems to work since some versions ago

    On further investigation, it is still being called (as of Lion). But it's still an undocumented hack.

    The particular thing that's bothering me the most is that I have a source-list outline view in my floating palette, and it responds to the window activation state even though for the floating panel it's meaningless. I'd rather it didn't and appeared always active.

    How can I do that? If there's a general answer to that question that would be great, but otherwise doing something with the table/outline view is OK.

    --Graham
  • On Jul 17, 2012, at 21:44 , Graham Cox wrote:

    > The particular thing that's bothering me the most is that I have a source-list outline view in my floating palette, and it responds to the window activation state even though for the floating panel it's meaningless. I'd rather it didn't and appeared always active.

    There are 3 states for enabled controls**, not two:

    1. In an inactive window (Snow Leopard+ at least -- I think the appearance was different in Leopard), controls are colorless with a lighter shade of gray textured background (just like the title bar is a lighter shade of gray). List and text selections are gray.

    2. In a main, non-key window, controls are colorless and a darker shade of gray background, again similar to the title bar. List and text selections are gray, though I can't tell if it's the exactly the same gray as #1.

    3. In a key window, controls are colored, if they have a non-gray color. This includes list and text selections for example.

    You can see these distinctions in TextEdit, if you open 2 document windows and the Fonts panel. (Look at the font size popup in the window toolbars. If you click in the font size field in the panel, you'll see #1 and #2 in the window toolbar popups.) All this is according to HIG AFAICT.

    It would seem that floating panels ought to follow the #2 and #3 rule. It's not clear that "window activation state" is meaningless. A user should be able to see, for example, whether the up and down arrows move the selection in the source list in the panel or not.

    The problem is, perhaps, that you've been using Macs for too long. :) Your brain is used to thinking of gray controls as inactive/disabled, whereas gray currently just encompasses everything non-key. The HIG has changed on this subject over the years (although I believe the 3 active states have been described for quite a while), plus the fact that many apps haven't followed the HIG, especially in custom controls (and perhaps standard controls didn't all draw according to all the rules pre-Snow Leopard).

    I also suspect, though I don't know, that the correctness of the activation has some relationship with accessibility. You might be degrading the accessibility behavior if you try to force the panels to look key when they're not.

    FWIW.

    ** I don't know how many states there are for disabled controls. There might be 2 -- in active and inactive windows, using lighter and darker textured backgrounds, but I'd have to hunt around for an app that demonstrates this. I couldn't see a way of disabling any of TextEdit's toolbar controls, and I'm not sure what other apps to trust to follow the HIG.
  • On 18.07.2012, at 06:27, Graham Cox wrote:
    > I'd like to know if there is a supported way to do this. It seems a bit crazy that floating panels even bother modulating the active state of controls when they are floating and are *always* effectively active, and it looks better and is more usable as well.

    There are some HIG rules on when controls should be inactive, and also several kinds of "active":

    -> there is "main window state" and there is "has keyboard focus". Palettes generally ignore the first, but honor the second, so the user knows whether keypresses will go in the main window or not. So some change in look is expected (different from classic MacOS, where these two states were hardly distinguished, except maybe for the focus border on the view that has keyboard focus).

    -> Pushbuttons can accept the first click or not. If they do not, this means you get the classic MacOS-style "click once to activate the window, click a second time to actually trigger the button" This is good for "dangerous" buttons like "Delete", which you don't want to trigger accidentally when just trying to bring forward a window. -acceptsFirstMouse: determines that. Maybe your buttons give NO from that and such draw inactive?

    -> It's not the floating panel that does anything with the active state, it is each view itself. They register for -windowDidBecomeKey: and similar notifications and redraw themselves accordingly.

    -> Have you tried switching "non-activating panel" on? It sounds like that is what you want. It can still have keyboard focus then, but just won't be the main window.

    Cheers,
    -- Uli Kusterer
    "The Witnesses of TeachText are everywhere..."
    http://www.lookandfeelcast.com
  • On 18.07.2012, at 09:12, Quincey Morris wrote:
    > There are 3 states for enabled controls**, not two:
    >
    > 1. In an inactive window (Snow Leopard+ at least -- I think the appearance was different in Leopard), controls are colorless with a lighter shade of gray textured background (just like the title bar is a lighter shade of gray). List and text selections are gray.

    This state often looks transparent or flattened. The plasticity of a control gets reduced because it's in a background window.

    > 2. In a main, non-key window, controls are colorless and a darker shade of gray background, again similar to the title bar. List and text selections are gray, though I can't tell if it's the exactly the same gray as #1.

    These often just lose the blue tint of a control, but otherwise look active and solid and 3D. But e.g. popup buttons and scrollers are now monochrome, so you don't see this as often anymore.

    > 3. In a key window, controls are colored, if they have a non-gray color. This includes list and text selections for example.

    Cheers,
    -- Uli Kusterer
    "The Witnesses of TeachText are everywhere..."
    http://www.masters-of-the-void.com
  • On 18/07/2012, at 5:12 PM, Quincey Morris wrote:

    > It would seem that floating panels ought to follow the #2 and #3 rule. It's not clear that "window activation state" is meaningless. A user should be able to see, for example, whether the up and down arrows move the selection in the source list in the panel or not.
    >

    Well, there are 3 distinct visual appearances, that's true. non-main (and hence non-key), main-but-not-key, and main-and-key.

    To distinguish between key and non-key in a floater is fine, that makes sense, but the additional distinction between main and non-main is silly here, because a floater works exactly the same in either state. It bugs me for example that the list background changes between white and a light blue in these two "states" even though there is no change in functionality at all. There is a change in functionality when it becomes key, because then I can control it with the keyboard.

    > The problem is, perhaps, that you've been using Macs for too long. :) Your brain is used to thinking of gray controls as inactive/disabled, whereas gray currently just encompasses everything non-key.

    Could be. But that goes for our users as well.

    Another particularly bad example is the segmented control, which I'm using as a set of related pushbuttons. They look completely disabled (light grey text) when the window is inactive, and yet work just fine. When the window is made active, they change in appearance to what looks "enabled" to my way of thinking (black text), but only when the mouse enters them! This seems doubly broken to me. The same goes when the window becomes inactive - the buttons stay "enabled" until the mouse happens to stray into their rects, when they "grey out". If that is the intended behaviour, all I can say is somebody was on acid when they made that.

    On 18/07/2012, at 6:10 PM, Uli Kusterer wrote:

    > -> It's not the floating panel that does anything with the active state, it is each view itself. They register for -windowDidBecomeKey: and similar notifications and redraw themselves accordingly.

    It must work in some other way. The list view can't be the window's delegate, so that should only leave the possibility that it is asking for those notifications from the window. However, if I deliberately force the list view to unsubscribe from ALL notifications, it still changes state when the window changes state. So there must be a private mechanism in place that the list view uses to track the window state. Corbin, any comment?

    > -> Have you tried switching "non-activating panel" on? It sounds like that is what you want. It can still have keyboard focus then, but just won't be the main window.

    No. This means that the panel won't activate the app if it is clicked when the app is inactive, but since it's set to hide on deactivate, this setting doesn't apply anyway. The setting you may be thinking of is -setBecomesKeyOnlyIfNeeded:, which I'm using, but this is something else again - it only makes the window key for controls such as text fields that require it when they are clicked for text entry. The list view can become key at times, but is never required to be. But the visual appearance change it makes conveys no information at all, so it is redundant, and I'd like to eliminate it if I can.

    --Graham
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