NSTrackingArea with cursorUpdate does not work (it is documented not to; I've tried it just out of desperation since no other way worked either).
NSTrackingArea with mouseEntered: and mouseExited: is not related to the mouse cursor shape at all, far as I understand properly. Do please correct me if I am wrong, but I understand that's just one possible way (there are others as well) to detect that the current mouse position is over my view. That's not the problem. The problem is changing the cursor. I presume I should call NSCursor.push (or set) when entered, pop (or a manual reset) when exited. Which, as mentioned above, does not work for me :(
Does it work for you (ie. does NSCursor.push or set work for you even when called from an inactive application), which would mean I am doing something wrong?
Post
Replies
Boosts
Views
Activity
Quinn,
thanks! Alas, I must be still doing something wrong, neither approach did help :(
I've extended my test code to try both, the default and explicit subsystem, like this:
os_log(OS_LOG_DEFAULT,"private shown: %@", [NSString stringWithFormat:@"OK"]);
os_log_t withss=os_log_create("cz.ocs.CCC", "test");
os_log(withss,"private-ss shown: %@", [NSString stringWithFormat:@"OK"]);
I've removed my previous profile, copied down the profile from the end of your linked message, changed the system ID and display name, saved it as “syslog-CCC.mobileconfig”, installed as new profile in Settings. Installation went OK, looks like this:
Tested, still getting <private>, both in Xcode and Console, for both the logs. For reference, my slightly changed profile added completely at the end of this message. To make extra sure, I've tried also to install the profile verbatim with your original content (com.example.apple-samplecode.Test738648 etc); not surprisingly did not help either.
I've added the first snippet (again with only change in the subsystem ID) to my “Info.plist”. Checked that it is indeed properly generated into the build:
1016 ocs /tmp> ~/Library/Developer/Xcode/DerivedData/CCC-aqmufkksnhojayaidbhwkprlyegv/Build/Products/Debug
1017 ocs Build/Products/Debug> tail -14 CCC.app/Contents/Info.plist
<string>NSApplication</string>
<key>OSLogPreferenceso</key>
<dict>
<key>cz.ocs.CCC</key>
<dict>
<key>app</key>
<dict>
<key>Enable-Private-Data</key>
<true/>
</dict>
</dict>
</dict>
</dict>
</plist>
1018 ocs Build/Products/Debug>
Still I am consistently getting <private> in all the cases :( Again, to make completely sure I am not missing something obvious, I've tried the same with your original com.example.apple-samplecode.Test738648 key and also with com.example.apple-samplecode.PrivateValueLogger, as shown in the detailed documentation; neither (not surprisingly) did help.
I am outta ideas. What could be wrong, what should I check? Thanks!
Almost forgot: macOS 13.6 (22G120), Xcode 15.0.1 (15A507), MacBook Air M1, 2020 (should be irrelevant, but who knows). I've restarted both Console and Xcode. I did not restart macOS (since I've got open work in other apps, not speaking of this message); I'll try that later and will add here the outcome.
Here's a complete contents of my slightly updated profile, as I've tested it:
1015 ocs /tmp> <syslog-CCC.mobileconfig
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadDescription</key>
<string>System Logging CCC</string>
<key>PayloadDisplayName</key>
<string>System Logging CCC</string>
<key>PayloadIdentifier</key>
<string>com.apple.system.logging.684C6584-DDFB-4DC5-AD4B-DF084028C248</string>
<key>PayloadType</key>
<string>com.apple.system.logging</string>
<key>PayloadUUID</key>
<string>684C6584-DDFB-4DC5-AD4B-DF084028C248</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>Subsystems</key>
<dict>
<key>cz.ocs.CCC</key>
<dict>
<key>app</key>
<dict>
<key>Enable-Private-Data</key>
<true/>
</dict>
</dict>
</dict>
</dict>
</array>
<key>PayloadDescription</key>
<string>Enables logging for the CCC app.</string>
<key>PayloadDisplayName</key>
<string>CCC Enable Logging</string>
<key>PayloadIdentifier</key>
<string>Slimey.02BFD8E9-601F-40D3-96CF-8EA446D0ABD6</string>
<key>PayloadRemovalDisallowed</key>
<false/>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>84BE502F-BB63-4D65-BBAF-64FCC31AA00A</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</plist>
1016 ocs /tmp>
Essentially solved. Sorry, I'm completely dumb and have messed up the categories; with
os_log_t withss=os_log_create("cz.ocs.CCC", "app");
os_log(withss,"private-ss shown: %@", [NSString stringWithFormat:@"OK"]);
it works all right, based on the profile installed. Also, with DEFAULT-OPTIONS category works all right for any category inside of the right subsystem. Whew!
Nevertheless, still
the Info.plist part still does not seem to work: whatever I set up in there yields <private>
is there a way to set up the profile so that OS_LOG_DEFAULT works? Xcode show the subsystem for my app as “CCC”, Console shows an empty string, but neither works (nor does its bundle identifier, which happens to be “cz.ocs.CCC”)
is there a way to set up Enable-Private-Data for more subsystems at once, without multiplicating the dictionaries? I did find DEFAULT-OPTIONS for categories, but I did not find anything like that for subsystems.
Thanks a lot and do please forgive my previous stupidity.
P.S. The option to store directly the options plist into “/Library/Preferences/Logging/Subsystems/” seems to work as well; is there some drawback to it, a reason why you suggest profile installation (which does essentially the same under the hood) instead?
Anyway, it sort-of solves my third question, for at least, in the folder I can set up as many subsystems as I want to through hard-links :) Though still, a way to set up “any cz.ocs.* subsystem” would be really handy, if possible somehow.
Hmmm, more questions (I do wonder what I am again overlooking), this time related to the levels. I've tried to play with the Level sub-dictionary. Not surprisingly, in Info.plist it does nothing. In a plist stored in ...Logging/Subsystems it sort of works, sort of; the log tool sees the setup:
248 root Preferences/Logging/Subsystems# <cz.ocs.CCCy.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>DEFAULT-OPTIONS</key>
<dict>
<key>Enable-Private-Data</key>
<true/>
<key>Level</key>
<dict>
<key>Enable</key>
<string>Default</string>
</dict>
</dict>
</dict>
</plist>
249 root Preferences/Logging/Subsystems# log config --status --subsystem cz.ocs.CCCy
Mode for 'cz.ocs.CCCy' DEFAULT PERSIST_DEFAULT
250 root Preferences/Logging/Subsystems#
The problem is, it does not seem to affect the logging at all. Whatever I set in there — I've tried all values from Default to Debug — the outcome is always the same:
the log tool properly shows whatever I set in there (meaning my dicts probably are not all wrong)
nevertheless, both Xcode and Console (when both Action/Include... are on) always print out all the message levels, including os_log_info and os_log_debug, regardless the current setting — even though Default is set up as shown above.
What am I overlooking now? The subsystem and category settings are all right, proved by that Enable-Private-Data works all right. The level setup seems OK too, given it is confirmed by log config --status. Nevertheless I can't see why neither Xcode nor Console are affected by the level settings the slightest bit?
FB13562748
(Sorry for the delay, have been sorta busy lately.)
I have lately bumped into the new Sonoma clipsToBounds behaviour. I must be missing something obvious, but it seems to me the current documentation now is at best misleading (if not plain wrong), and also it seems to me — far as the documentation is to be trusted — there's not any easy way to implement drawRect: anymore.
I'd be grateful is Quinn or anybody, who understands this properly, explains. Here are my problems:
The drawRect: documentation, at this moment, says pretty explicitly
[dirty] rect ... The portion of the view’s bounds that needs to be updated. The first time your view is drawn, this rectangle is typically the entire visible bounds of your view. However, during subsequent drawing operations, the rectangle may specify only part of your view
This seems to me to be at odds with the Sonoma reality that the dirty rect now is allowed to extend beyond the geometry of the view itself. Do I understand it wrong?
This feels to me a documentation bug, looks like pre-Sonoma documentation which was not updated accordingly to the new behaviour, but as always, I can be wrong.
Worse is, how do we implement drawRect: now (presumed we want to stick with the new clipsToBounds behaviour)?
Let's say we want simply a coloured background, the thing which pre-Sonoma was rightly and properly implemented by
[colour set]; NSRectFill(dirtyRect); The release notes suggest we simply replace it with [colour set]; NSRectFill(self.bounds); — This pattern can be adjusted by filling the bounds instead of the dirty rect, but — do please correct me if I am missing something of importance — this seems to be at odds with the drawRect: documentation, which very explicitly states (the above, and)
You should limit any drawing to the rectangle specified in the rect parameter
Given we draw whole self.bounds as suggested, and given the dirty rect very definitely can specify only part of our view, it seems plain wrong.
Actually, the sentence quoted above feels very strange to me. Far back as I can recall, it always used to be pretty usual to draw outside of the dirty rect (but inside of bounds).
I might have missed something of importance somewhere, but I've always though the dirty rect is just an optimising tool, which allow us to simplify complex drawing skipping anything which does not intersect it; but we should draw all parts which do intersect the dirty rect even if they exceed it (which many of them usually do). Besides, in simple cases, we can safely ignore the dirty rect completely and just fill the bounds as need be.
Is that not so anymore in Sonoma? I cannot recall the “You should limit any drawing...” sentence quoted above in the older documentation, but I might recall it wrong. Anyway, if that sentence is really meant to be taken into account, it seems to me we should always explicitly clip all our drawing to both bounds and dirty rect, which sometimes might be a bit non-trivial?
Thanks for any elucidation,
OC
Kevin,
thanks a lot for a quick answer!
What does this cooperation actually involve?
The applications communicate (through DO) and perform tasks as needed. Typically, the standard application (SA) sends requests to the login item (LI), which contains most of the GUI, whenever the user selects a menu item.
Is it just that they both run at the same time
When the problem with non-functional hidden menu happens, they do.
Sometimes only LI runs (when the user quits SA), but of course, there's no menu in this case and thus no problem either.
they're cooperatively interacting with the same underlying data
In fact the data is not shared; LI manages it, and if need be (e.g., to validate menu items), it sends the current state to SA through DO.
To be frank tho, I can't really see how this could be relevant to the problem that the menu of SA does not unhide properly when SA is the menu owner and the pointer goes up.
are they directly manipulating each other interfaces
Not sure what does this mean :( The apps communicate through DO, which affect both the GUIs:
when the user selects a menu item in SA, it (usually, not always — e.g., About... is solved completely SA-side) sends an appropriate request to LI, which updates its GUI accordingly
LI validates menu items for SA based on the current data and application state
None of this though actually happens in the simplest case when the problem happens. No menu (and essentially no SA/LI functionality) is really used. The typical scenario is
LI runs and does nothing
SA is launched, connects to LI and asks it to show the main window, which LI does (now, SA is menu owner, LI frontmost, all works well; when the pointer goes up, SA menu shows all right)
SA is deactivated. Another application (e.g., System Settings, Console, Xcode, whatever) is frontmost/menu owner. When the pointer goes up, the menu of the other app shows
LI is re-activated e.g., by clicking to its main window title bar. When it gets didBecomeActive, it checks whether SA happens to be the menu owner, and if not, it activates SA (to make it menu owner)
When SA gets didBecomeActive, it activates LI (to make it frontmost)
Now, SA is the menu owner and LI frontmost. Nevertheless, (pretty often) when the pointer goes up, nothing happens — the SA menu is not shown.
does your main app always operate as a standard application
Yes, SA is normal application and never changes its presentationOptions (nor does other tricks like that).
Which process logged that state?
I wrote a very simple independent application which does nothing but
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSWorkspace *wsp=NSWorkspace.sharedWorkspace;
NSLog(@"menu owner: “%@” front: “%@”", wsp.menuBarOwningApplication.localizedName, wsp.frontmostApplication.localizedName);
[self performSelector:_cmd withObject:nil afterDelay:5];
}
I keep it running and observe its log.
Do you have logging from both process at the same time so that you can see what they both "thought"?
Yes, aside of the above, both LI and SA happen to log when they get didBecomeActive, and those logs show that the steps 4 and 5 above do happen all right.
Thanks for the elaboration.
As a "side bar" to your original questions, why is your login item running like this at all?
Mostly for historical reasons (the applications are pretty old, 10+ years, and underwent many changes meantime). We are considering a serious refactoring, but now we need to solve the problem quickly.
Interaction in your SA cause UI activity in your LI and, more importantly, your LI is attempting to activate your SA.
Quite. Unless/until we refactor, we simply have to, for clicking into the LI window must bring up the SA menu.
Which works well and completely reliably when the menu is not hidden.
When it is hidden though, for some weird reason the very menu bar which would normally be visible does not show when the pointer goes up. That's the problem we need to solve now.
When someone uses your app and another app unexpectedly steals focus...
... is not what happens here. In our case, the other app does not “steal” the focus and it is not unexpected. The focus is given to it willingly, it is as expected, and both the GUIs are written so that it works properly.
We never encountered any problem like accidentally entering text into the wrong app or so, and never we need to switch back to the original app: as mentioned above, both the applications are written to work like one from the user's perspective.
Our problem is quite different: while the SA is the menu owner and the menu is hidden, it (occasionally) does not show when the pointer goes up.
I strongly suspect that the issues you're seeing only happen when another app is involved in the activation process
Not really. The only involvement of another application is that it is active (both menu owner and frontmost) before the problem occurs.
not if you first activate your SA directly (for example, but clicking on the dock).
Quite, that's not our current problem. It happens when SA is activated through LI, as already outlined above:
another application is both menu owner and frontmost (which is the only involvement of any other application)
the LI's window title is clicked (seems that when the window content is clicked, the problem occasionally happens, but when the title bar is clicked, it always happens; weird)
this makes LI frontmost, but not menu owner (since it is a login item which does not mess with its presentation and thus can't have menu)
therefore, LI activates SA, so that it becomes the menu owner (note SA does not steal focus; LI gives it willingly)
then in the final step, SA activates LI to make its window the frontmost one (again, LI does not steal the focus; SA gives it willingly).
Now, LI is frontmost, SA is the menu owner. If menu is not hidden, the SA menu is at this moment shown properly. Alas, if the menu is hidden and at this moment the pointer goes up, nothing happens. What could we do to make sure that the SA menu occurs? Thanks.