Disabling the auto-hiding of scroll bars on Lion - cocoa

In Mac Lion, the scroll bar hides itself after a few seconds if no activity occurs. I have written an apple script to modify that behavior. I have to turn on the radio button every time my app launches. My question is, I have a cocoa application. Is it possible to keep the scroll enabled for the application always with out having to change the settings in system preferences.I don't want to enable for all the other apps always. And is the only way via the applescript. Or is there a defaults write to enable the scroll bars in lion ?.

I don't know about a defaults key to set up the style.
When you change the Appearance preference panel's "Show scroll bars", all the NSScrollView instances are notified and receive a setScrollerStyle: with the new style (through the NSPreferredScrollerStyleDidChangeNotification notification).
You can achieve the same result by explictly calling setScrollerStyle: on the NSScrollView with the NSScrollerStyleLegacy scroller style.

You can write to defaults to accomplish this.
The key is AppleShowScrollBars and it has three possible values:
Automatic
WhenScrolling
Always
To set it system-wide from the command line, you could do:
defaults write -g AppleShowScrollBars Always
It can also be done programmatically by modifying preferences in any of various ways. It can get a little tricky depending on application sandboxing. This blog post explains it in more detail.

Related

Make macOS window capture hover events even if set _setPreventsActivation:true and canBecomeKeyWindow:true

I want to achieve a certain window behavior for a macOS app. I subclassed NSWindow to be able to add additional properties. So far, it works well with almost all requirements (dragging it, clicking buttons) while preserving the core requirement of not making the currently active app losing focus. What does not work is making the window's UI elements react to mouse-hover events.
Requirements:
☑️ Don't activate the app when showing the window → _setPreventsActivation:true
☑️ Prevent activation of the app when interacting with the window (click/drag) → _setPreventsActivation:true
﹖Make the window react to mouse hover events over interactive UI elements without activating the app
An example of an application that does very much what I intend to do (UX-wise) is 1Password. Here is a short clip: An animated GIF showing 1Password UX
Can someone explain what they likely do to make their window behave this way?

Is there a way to get NSPanel “Non activating” style functionality on an NSWindow?

NSPanel has a “Non activating” option for HUD Panels. I’d like to get that same functionality working on an NSWindow, i.e. I want the window to accept clicks but not take focus away from whatever the active app is (by this I mean the app that was active before clicking on the window activated my app—in this case Sketch).
I have tried creating an NSWindow subclass and setting canBecomeMainWindow and canBecomeKeyWindow to NO but that doesn’t seem to be working—I think because those settings only apply to windows within the same app.
What I’m trying to do here is prevent this flickering. I’m pretty sure this is doable as apps like Alfred seem to be doing it.

Mac OS X Carbon: What is the difference between SelectWindow vs. ActivateWindow and what are the Cocoa equivalents

The title basically sums up my question. I'd like to know what the difference between the Mac Carbon SelectWindow and ActivateWindow(..., TRUE) is. I've found these in old source and wonder if they are interchangeable (or what their Cocoa equivalents might be).
From memory...
SelectWindow was the response to clicking on a window. It brought the window to the front, activated it, and (usually) made it the first responder. (I'm using Cocoa terminology here.) It's sort of like OrderFront
The SelectWindow function removes highlighting from the previously
active window, brings the specified window to the front, highlights
it, and generates the activate events to deactivate the previously
active window and activate the specified window. If the specified
window is already active, SelectWindow has no effect. Call
SelectWindow when the user presses the mouse button while the cursor
is in the content region of an inactive window.
Activate Window updated the window frame to indicate that the window was the first responder.
You don't really need to know a Cocoa equivalent, you just need to identify what you want to do. Many things from Carbon that required you to implement them are done for you by AppKit. Other paradigms of Carbon APIs just do not happen in Cocoa. They look similar, and had many similar hooks to common OS things, but they're very very different.

Cocoa accessibility API, can I click a window in the background without activating it?

I've been searching forever for a solution to this, so I thought I'd seek out the brainpower of greater minds than mine. I'm developing a Cocoa app that uses the Accessibility API to manipulate another program (it's a hotkey app). The app I'm controlling typically has multiple windows open, with some hidden behind others. What I would like to do, if it's possible, is to send mouse events to windows using the Accessibility API in a way that presses a button in the window without bringing it to the foreground (interact with the window but don't activate it). The reason I'm trying to do this is that sending the mouse event to this other window will force it to the foreground and disrupt the user's interaction with the foremost window.
This is possible on Windows - apparently, because apps similar to mine do it there - but I'm getting the feeling that this isn't possible with Cocoa, given the way the window manager works. Am I mistaken?
Accessibility is higher-level than that. You send, for example, AXPress actions to AXButton objects, but “press” is not necessarily a click—pressing the space bar while a view is focused, for example, is also a “press”. AXPress is a high-level action that means “do your thing”, which obviously has meaning for some views (such as buttons) and not others (such as fields).
Accessibility activating the application does make sense when you look at it from its intended purpose: Assistive devices for disabled users. If the user “presses” something by whatever means, they probably intend to activate the application and work in it.
Quartz Event Services will get you almost there: You can create an event tap for the process you want to control, and you can forge events and send them to a tap. The catch is that you can only send events to a tap when the tap fires—i.e., when the application already has an event to deal with. When it doesn't, you're stuck.

How do I get keyboard events in an NSStatusWindowLevel window while my application is not frontmost?

After creating a translucent window (based on example code by Matt Gemmell) I want to get keyboard events in this window. It seems that there are only keyboard events when my application is the active application while I want keyboard events even when my application isn't active but the window is visible.
Basically I want behavior like that provided by the Quicksilver application (by blacktree).
Does anybody have any hints on how to do this?
There are two options:
Use GetEventMonitorTarget() with a tacked-on Carbon run loop to grab keyboard events. Sample code is available on this page at CocoaDev.
Register an event trap with CGEventTapCreate. Sample code can be found in this thread from the Apple developer mailing list.
Edit: Note that these methods only work if you check off “Enable access for assistive devices” in the Universal Access preference pane.
A simpler route that may work better for you is to make your app background-only. The discussion on CocoaDev of the LSUIElement plist key explains how to set it up. Basically, your application will not appear in the dock or the app switcher, and will not replace the current application's menu bar when activated. From a user perspective it's never the 'active' application, but any windows you open can get activated and respond to events normally. The only caveat is that you'll never get to show your menu bar, so you'll probably have to set up an NSStatusItem (one of those icon menus that show up on the right side of the menu bar) to control (i.e. quit, bring up prefs, etc.) your application.
Edit: I completely forgot about the Non-Activating Panel checkbox in Interface Builder. You need to use an NSPanel instead of an NSWindow to get this choice. This setting lets your panel accept clicks and keyboard input without activating your application. I'm betting that some mix of this setting and the Carbon Hot Keys API is what QuickSilver is using for their UI.
Update:
Apple actually seems to have changed everything again starting with 10.5 BTW (I recently upgraded and my sample code did not work as before).
Now you can indeed only capture keydown events setting up an event tap if you are either root or assistive devices are enabled, regardless on which level you plan to capture and regardless if you selected to capture (which allows you to modify and even discard events) or to be listen only. You can still get information when flags have changed (actually even change these) and other events, but keydown under no other circumstances.
However, using the carbon event handler and the method RegisterEventHotKey() allows you to register a hotkey and you'll get notified when it is pressed, you neither need to be root for that nor do you need anything like assistive devices enabled. I think Quicksilver is probably doing it that way.

Resources