How to detect the "Accessibility Reduce Transparency" In macOS (Objective-C)? - uikit

By default, macOS11.0 Big Sur set the "reduce transparency" to true on Accessibility. That makes the light status menu almost the same as the dark one, thus make the setting of my app's status menubar icon becomes a challenge.
On iOS, a simple UIKit function could do the trick:
if (UIAccessibilityIsReduceTransparencyEnabled()){
//use the icon for dark mode although we are in light mode now
}
But there is no way to implement it on macOS although the Apple documentation indicated the Availability is iOS 8.0+ and macOS Catalyst 13.0+
Any ideas? Thank you!

You can use the defaults read com.apple.universalaccess reduceTransparency command. It's 1 if it's enabled, and 0 if it's not. In Objective-C that looks something like this:
- (BOOL)isTransparencyEnabled {
Boolean keyExists = false;
Boolean transparencyEnabled = CFPreferencesGetAppBooleanValue( CFSTR("reduceTransparency"), CFSTR("com.apple.universalaccess"), &keyExists);
return keyExists && transparencyEnabled;
}

Related

How to detect if OSX in dark or light mode in Auto Appearance Mode in Catalina

My Mac app needs to change behaviour depending on light or dark mode.
Whats the best way to detect style when Appearance option is selected to auto in macOS Catalina?
NSDictionary *dict = [[NSUserDefaults standardUserDefaults] persistentDomainForName:NSGlobalDomain];
id style = [dict objectForKey:#"AppleInterfaceStyle"];
BOOL darkModeOn = ( style && [style isKindOfClass:[NSString class]] && NSOrderedSame == [style caseInsensitiveCompare:#"dark"] );
darkModeOn is still yes/dark even after switching from dark to auto appearance option.
you need to combine AppleInterfaceStyle with this new value introduced in macOS Catalina AppleInterfaceStyleSwitchesAutomatically.
Here is some pseudo-code explaining how to:
theme = light //default is light
if macOS_10.15
if UserDefaults(AppleInterfaceStyleSwitchesAutomatically) == TRUE
if UserDefaults(AppleInterfaceStyle) == NIL
theme = dark // is nil, means it's dark and will switch in future to light
else
theme = light //means it's light and will switch in future to dark
endif
else
if UserDefaults(AppleInterfaceStyle) == NIL
theme = light
else
theme = dark
endif
endif
else if macOS_10.14
if UserDefaults(AppleInterfaceStyle) == NIL
theme = light
else
theme = dark
endif
endif
You can check a macOS sample app here: https://github.com/ruiaureliano/macOS-Appearance.
Cheers 💪
In macOS, the best way to find the current effective appearance (what is actually being displayed) is to look at NSApplication.effectiveAppearance. This value is observable with KVO and can be accessed through the NSApp singleton. A good article regarding watching these changes Supporting Dark Mode: Responding to Change which covers observing this particular value.
General macOS note: Reading the configuration settings from the global user preferences will get you what was last stored, but it won't get you whatever interpretation the OS currently has of that value (which, as you've shown in this example, can shift over time). This is what you're running into here. As a general rule, if you find yourself reading NSUserDefaults for keys that are not defined in the API, you should look around for another approach.

How to implement a dock icon notification indicator with Electron in OS X?

I don't actually know the thing's name, I am talking about the red dot on the right top corner of app icon.
I'll have to make some assumptions here because I don't own a Mac to test this with. I believe that those red dots on the corner of an app icon are referred to as badges. In Electron's App module there are methods to get/set the badge along with other dock features. Check out http://electron.atom.io/docs/v0.30.0/api/app/ for more information. Here are the relevant methods:
app.dock.setBadge(text)
text String Sets the string to be displayed in the dock’s badging
area.
Note: This API is only available on Mac.
app.dock.getBadge()
Returns the badge string of the dock.
Note: This API is only available on Mac.
My guess is the code to produce the dot that you see in the example from Slack that you provided would look something like this:
var app = require('app');
app.dock.setBadge('.');
you can also try this
app.setBadgeCount(numberOfNotifiations)
What I usually do is simply increase the current badge count by 1, like so:
app.setBadgeCount(app.getBadgeCount() + 1)
see https://electron.atom.io/docs/all/#appsetbadgecountcount-linux-macos

OSX: How to filter out the menu bar from CGWindowListCopyWindowInfo

I'm using CGWindowListCopyWindowInfo to grab the list of windows on the desktop. I'd like to filter out only the visible windows using values of the Window List keys. The one window I'm having trouble is the OSX menu bar. One solution I've thought of using is looking at the X and Y of the window bounds. No visible windows seem to have both of those equal to 0, but I'm not sure how reliable this method is.
One other way to do this would be to compare the PID number to that of the OSX Window Server, but I'm not sure how to get that. Can anyone point me towards the right API or know of a reliable way to filter out the menu bar?
Edit: I have the same code as kondy below with the following additions since the listOptions themselves aren't good enough:
CGRect windowBounds;
CGRectMakeWithDictionaryRepresentation((CFDictionaryRef) [windowInfo objectForKey:(id)kCGWindowBounds], &windowBounds);
if (!(windowBounds.origin.x == 0 && windowBounds.origin.y == 0))
{
// Work with windows that aren't the Menubar
}
I have found an answer to filter out the "Window Server":
CGWindowListOption listOptions = kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements;
CFArrayRef windowList = CGWindowListCopyWindowInfo(listOptions, kCGNullWindowID);
Using these ORed options, I get a result as same as mac's "Windowed processes" in "Activity Manager"
I hope it will help you!

Cause for a clipped keyboard in landscape

I have a page with a Pivot, with TextBox controls. In landscape, the SIP (the virtual keyboard) is opffsetted right by 42 pixels, thus clipped to its right.
Another app of mine also has a similar page, without the offsetted keyboard problem. Before I dig more into the differences between the two, has anyone ever encountered this problem before? Can we consider this a bug with Windows Phone 7.1?
(it does occur on a real device too)
It is a bug in windows phone:
If you set the Mode property on the app bar to Minimised and then turn the thing to landscape, the app bar pops back out. The code that figures out where to show the keyboard doesn't realise this and displays the keyboard as if the app bar is still minimised.
I solved it by changing the mode of the app bar as the orientation changes:
private void phoneApplicationPage_OrientationChanged(object sender, OrientationChangedEventArgs e)
{
if (e.Orientation == PageOrientation.LandscapeLeft || e.Orientation == PageOrientation.LandscapeRight)
{
this.ApplicationBar.Mode = Microsoft.Phone.Shell.ApplicationBarMode.Default;
}
else
{
this.ApplicationBar.Mode = Microsoft.Phone.Shell.ApplicationBarMode.Minimized;
}
}
This seems to solve the problem
Try checking if you have a set common right offset margin somewhere in your code. That is the most likely reason for this behavior.
I have never experienced this error myself.

Window resizable - kAXGrowAreaAttribute always return NULL

In my app I want to check if windows from others apps are resizable.
I´m using the accessibility API to test if the window has the kAXGrowAreaAttribute attribute (if NULL is not resizable) as Peter Hosey answered in this question.
The problem is that the kAXGrowAreaAttribute returned value is always NULL it doesn´t matter if the window is resizable or not. Note: to retrieve the value I´m using the UIElementUtilities class from the Apple UIElementInspector example (I also have tried using AXUIElementCopyAttributeValue directly with the same result).
Any idea? I´m working in Lion, could be this the problem? Thanks in advance.
EDITED:
Playing around with the UIElementUtilities class methods I found a solution.
Just use the method
+ (BOOL)canSetAttribute:(NSString *)attributeName ofUIElement:(AXUIElementRef)element
with the kAXSizeAttribute and the focused window. It returns YES or NO depending if the window is sizable or not...
It probably is because you're in Lion. The size box was killed off; resizable windows are resizable at every edge now.
And yes, testing whether the size can be changed is probably the right way. It seems to work for me in Snow Leopard.
Swift 5 version:
func isResizable(axElement: AXUIElement) -> Bool {
var resizable: DarwinBoolean = true
let status = AXUIElementIsAttributeSettable(axElement, kAXSizeAttribute as CFString, &resizable)
if status != .success {
print("unable to determine if window is resizable")
}
return resizable.boolValue
}

Resources