Remove unused article-content-wide classes
This commit is contained in:
parent
86bd8a39ee
commit
3c76daed1e
@ -189,10 +189,6 @@ header {
|
|||||||
text-wrap: pretty;
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
.read-more {
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-anchor {
|
.header-anchor {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
{% if latest_post.excerpt %}
|
{% if latest_post.excerpt %}
|
||||||
{{ latest_post.excerpt }}
|
{{ latest_post.excerpt }}
|
||||||
<p>
|
<p>
|
||||||
<a href="{{ latest_post_permalink }}" class="read-more">Read more…</a>
|
<a href="{{ latest_post_permalink }}" class="italic">Read more…</a>
|
||||||
</p>
|
</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ latest_post_content }}
|
{{ latest_post_content }}
|
||||||
|
@ -130,13 +130,13 @@ I knew the name of the notification I needed to fire, but not what to do with it
|
|||||||
|
|
||||||
Looking at the disassembly, we can see exactly what it's doing:
|
Looking at the disassembly, we can see exactly what it's doing:
|
||||||
|
|
||||||
<div class="article-content-wide"><img src="/2021/scrollswitcher/awakefromnib.png" alt="Hopper showing the disassembly for -[MouseController awakeFromNib]"></div>
|
<img src="/2021/scrollswitcher/awakefromnib.png" alt="Hopper showing the disassembly for -[MouseController awakeFromNib]">
|
||||||
|
|
||||||
It's adding an observer to `NSDistributedNotificationCenter`'s `defaultCenter` for the `SwipeScrollDirectionDidChangeNotification`—the notification name I saw earlier in the Console. The other place it's referenced from (`[MTMouseScrollGesture initWithDictionary:andReadPreferences:]`) is doing the same thing: adding an observer. So, it looks like this notification isn't what triggers the actual change to the actual scroll input handling deep in the guts of the system. If that were the case, I'd expect to see the preference pane _send_ the notification, not just receive it.
|
It's adding an observer to `NSDistributedNotificationCenter`'s `defaultCenter` for the `SwipeScrollDirectionDidChangeNotification`—the notification name I saw earlier in the Console. The other place it's referenced from (`[MTMouseScrollGesture initWithDictionary:andReadPreferences:]`) is doing the same thing: adding an observer. So, it looks like this notification isn't what triggers the actual change to the actual scroll input handling deep in the guts of the system. If that were the case, I'd expect to see the preference pane _send_ the notification, not just receive it.
|
||||||
|
|
||||||
But, it still may be useful. Looking at the implementation of the `_swipeScrollDirectionDidChangeNotification:` method it's setting as the callback for the action, we can see that it's probably updating the checkbox value. That `setState:` call sure seems like it's on the `NSButton` used for the natural scrolling checkbox.
|
But, it still may be useful. Looking at the implementation of the `_swipeScrollDirectionDidChangeNotification:` method it's setting as the callback for the action, we can see that it's probably updating the checkbox value. That `setState:` call sure seems like it's on the `NSButton` used for the natural scrolling checkbox.
|
||||||
|
|
||||||
<div class="article-content-wide"><img src="/2021/scrollswitcher/notificationhandler.png" alt="Hopper showing the disassembly for -[MouseController _swipeScrollDirectionDidChangeNotification:]"></div>
|
<img src="/2021/scrollswitcher/notificationhandler.png" alt="Hopper showing the disassembly for -[MouseController _swipeScrollDirectionDidChangeNotification:]">
|
||||||
|
|
||||||
[`NSDistributedNotificationCenter`](https://developer.apple.com/documentation/foundation/nsdistributednotificationcenter) is described as being like the regular notification center but for inter-process communication, which sounds like what we want. It has pretty much the same API as the regular one, so we can just send that notification when we change the scroll mode.
|
[`NSDistributedNotificationCenter`](https://developer.apple.com/documentation/foundation/nsdistributednotificationcenter) is described as being like the regular notification center but for inter-process communication, which sounds like what we want. It has pretty much the same API as the regular one, so we can just send that notification when we change the scroll mode.
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ With that in place, clicking the menu bar item both sets the default and causes
|
|||||||
|
|
||||||
That's all well and good, but clicking the menu item still doesn't actually change what happens when you move two fingers on the trackpad. It clearly works when clicking the checkbox in System Preferences, so there must be something else it's doing that we're not. Internally, this feature seems to be consistently referred to as the "swipe scroll direction" (even though it affects non-swipe scrolling), so, back in Hopper, we can search for procedures named like that. There's one that immediately looks promising `setSwipeScrollDirection`, that just delegates to an externally implemented `_setSwipeScrollDirection`.
|
That's all well and good, but clicking the menu item still doesn't actually change what happens when you move two fingers on the trackpad. It clearly works when clicking the checkbox in System Preferences, so there must be something else it's doing that we're not. Internally, this feature seems to be consistently referred to as the "swipe scroll direction" (even though it affects non-swipe scrolling), so, back in Hopper, we can search for procedures named like that. There's one that immediately looks promising `setSwipeScrollDirection`, that just delegates to an externally implemented `_setSwipeScrollDirection`.
|
||||||
|
|
||||||
<div class="article-content-wide"><img src="/2021/scrollswitcher/setswipescrolldirection.png" alt="Hopper showing the assembly for setSwipeScrollDirection"></div>
|
<img src="/2021/scrollswitcher/setswipescrolldirection.png" alt="Hopper showing the assembly for setSwipeScrollDirection">
|
||||||
|
|
||||||
Looking at the references to the function, I saw it was called by the `-[MouseController scrollingBehavior:]` setter. That seems like the function that I wanted, but since it was implemented elsewhere, I had no idea what parameters it took. So, where's it implemented?
|
Looking at the references to the function, I saw it was called by the `-[MouseController scrollingBehavior:]` setter. That seems like the function that I wanted, but since it was implemented elsewhere, I had no idea what parameters it took. So, where's it implemented?
|
||||||
|
|
||||||
@ -185,9 +185,9 @@ Actually getting the framework binaries is a bit tricky, since, starting with ma
|
|||||||
$ dyld_shared_cache_util -extract ~/Desktop/Libraries/ /System/Library/dyld/dyld_shared_cache_x86_64
|
$ dyld_shared_cache_util -extract ~/Desktop/Libraries/ /System/Library/dyld/dyld_shared_cache_x86_64
|
||||||
```
|
```
|
||||||
|
|
||||||
It took a couple guesses, but I found that the `_setSwipeScrollingDirection` function is defined in `PreferencePanesSupport.framework`.
|
It took a couple guesses, but I found that the `_setSwipeScrollingDirection` function is defined in `PreferencePanesSupport.framework`.
|
||||||
|
|
||||||
<div class="article-content-wide"><img src="/2021/scrollswitcher/preferencepanessupport.png" alt="Hopper showing the disassembly for _setSwipeScrollDirection in PreferencePanesSupport"></div>
|
<img src="/2021/scrollswitcher/preferencepanessupport.png" alt="Hopper showing the disassembly for _setSwipeScrollDirection in PreferencePanesSupport">
|
||||||
|
|
||||||
Hopper thinks it takes an int, but we can clearly see the parameter's being used as a bool. `rcx` is initialized to `kCFBooleanFalse` and set to `kCFBooleanTrue` if the parameter is true, and that's the value being passed to `CFPreferencesSetValue`. Perfect.
|
Hopper thinks it takes an int, but we can clearly see the parameter's being used as a bool. `rcx` is initialized to `kCFBooleanFalse` and set to `kCFBooleanTrue` if the parameter is true, and that's the value being passed to `CFPreferencesSetValue`. Perfect.
|
||||||
|
|
||||||
@ -218,4 +218,3 @@ I can't really take a screen recording of that, so you'll have to take my word t
|
|||||||
If you're interested in the complete code, it can be found [here](https://git.shadowfacts.net/shadowfacts/ScrollSwitcher). It's not currently packaged for distribution, but you can build and run it yourself. Because it needs the sandbox disabled, it won't ever been in the App Store, but at some point I might slap an app icon on it and published a notarized, built version. So, if anyone's interested, let me know.
|
If you're interested in the complete code, it can be found [here](https://git.shadowfacts.net/shadowfacts/ScrollSwitcher). It's not currently packaged for distribution, but you can build and run it yourself. Because it needs the sandbox disabled, it won't ever been in the App Store, but at some point I might slap an app icon on it and published a notarized, built version. So, if anyone's interested, let me know.
|
||||||
|
|
||||||
As it currently exists, the app—which I'm calling ScrollSwitcher—covers 90% of my needs. I don't generally dock/undock more than a one or twice a day, so just being able to click a menu bar item is plenty fast. That said, I may still extend it for "fun". One obvious improvement would be automatically changing the state when an external mouse is connected/disconnected. That shouldn't be too hard, right? Right?
|
As it currently exists, the app—which I'm calling ScrollSwitcher—covers 90% of my needs. I don't generally dock/undock more than a one or twice a day, so just being able to click a menu bar item is plenty fast. That said, I may still extend it for "fun". One obvious improvement would be automatically changing the state when an external mouse is connected/disconnected. That shouldn't be too hard, right? Right?
|
||||||
|
|
||||||
|
@ -29,15 +29,14 @@ The next step, then—having been thoroughly nerd-sniped by this—was to figure
|
|||||||
|
|
||||||
The first stop was [`NSPageLayout`](https://developer.apple.com/documentation/appkit/nspagelayout), the panel object that is responsible for displaying the panel. It was unlikely that the class would actually contain the implementation of the panel, but it was at least a starting point.
|
The first stop was [`NSPageLayout`](https://developer.apple.com/documentation/appkit/nspagelayout), the panel object that is responsible for displaying the panel. It was unlikely that the class would actually contain the implementation of the panel, but it was at least a starting point.
|
||||||
|
|
||||||
In order to actually look at the disassembled implementation of this AppKit class, I needed the actual AppKit framework binary. Since macOS Big Sur, all system framework binaries are stored merged in the `dyld` shared cache, rather than in separate files. But, I need them as separate files in order to actually inspect them.
|
In order to actually look at the disassembled implementation of this AppKit class, I needed the actual AppKit framework binary. Since macOS Big Sur, all system framework binaries are stored merged in the `dyld` shared cache, rather than in separate files. But, I need them as separate files in order to actually inspect them.
|
||||||
|
|
||||||
Since the [last time](/2021/scrollswitcher/) I wrote about this, a couple things have changed. Before, I built the Apple `dyld_shared_cache_util` from one of the periodic `dyld` source dumps. This is annoying because you have to make a bunch of changes to the source code to get it to compile outside of an Apple-internal environment. It also may break whenever there's an OS update. So, I've switched to using [this utility](https://github.com/keith/dyld-shared-cache-extractor) which uses the `dyld_extractor.bundle` that ships with Xcode. The other difference since before is a minor one: the dyld shared cache has moved. Wheras before it was in `/System/Library/dyld/`, in the Ventura beta it's moved to `/System/Cryptexes/OS/System/Library/dyld/` (the Cryptex seems to be part of the [Rapid Security Response](https://threedots.ovh/blog/2022/06/a-quick-look-at-macos-rapid-security-response/) feature Apple announced).
|
Since the [last time](/2021/scrollswitcher/) I wrote about this, a couple things have changed. Before, I built the Apple `dyld_shared_cache_util` from one of the periodic `dyld` source dumps. This is annoying because you have to make a bunch of changes to the source code to get it to compile outside of an Apple-internal environment. It also may break whenever there's an OS update. So, I've switched to using [this utility](https://github.com/keith/dyld-shared-cache-extractor) which uses the `dyld_extractor.bundle` that ships with Xcode. The other difference since before is a minor one: the dyld shared cache has moved. Wheras before it was in `/System/Library/dyld/`, in the Ventura beta it's moved to `/System/Cryptexes/OS/System/Library/dyld/` (the Cryptex seems to be part of the [Rapid Security Response](https://threedots.ovh/blog/2022/06/a-quick-look-at-macos-rapid-security-response/) feature Apple announced).
|
||||||
|
|
||||||
With the shared cache extracted, I could load the AppKit binary into Hopper (I had to disable the Objective-C analysis, otherwise the app crashed when trying to load the binary) and start poking around. I searched for the `NSPageLayout` class that I'm interested in, and looked at the `runModalWithPrintInfo:` method, since that sounded like a good candidate for something that would lead to the bulk of the implementation. And, indeed, it was. The method appears to be a fairly simple wrapper around the `PMPrepare...` function that sounds like it lives in a separate private framework.
|
With the shared cache extracted, I could load the AppKit binary into Hopper (I had to disable the Objective-C analysis, otherwise the app crashed when trying to load the binary) and start poking around. I searched for the `NSPageLayout` class that I'm interested in, and looked at the `runModalWithPrintInfo:` method, since that sounded like a good candidate for something that would lead to the bulk of the implementation. And, indeed, it was. The method appears to be a fairly simple wrapper around the `PMPrepare...` function that sounds like it lives in a separate private framework.
|
||||||
|
|
||||||
<div class="article-content-wide">
|
<img src="/2022/clarus/appkit.png" alt="Hopper window with AppKit showing the runModalWithPrintInfo: method">
|
||||||
<img src="/2022/clarus/appkit.png" alt="Hopper window with AppKit showing the runModalWithPrintInfo: method">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<aside class="inline">
|
<aside class="inline">
|
||||||
|
|
||||||
@ -47,9 +46,8 @@ Curious about what those `_objc_msgSend$...` calls are? I would be to, if I hadd
|
|||||||
|
|
||||||
The next step was figuring out where that prepare function is actually implemented. Running `otool -L` on the AppKit binary doesn't reveal anything obviously useful, but in the PrivateFrameworks directory extracted from the dyld shared cache, there's something called `PrintingPrivate.framework`, which sounds promising. Opening it up in Hopper, I saw that this is indeed the framework I was looking for.
|
The next step was figuring out where that prepare function is actually implemented. Running `otool -L` on the AppKit binary doesn't reveal anything obviously useful, but in the PrivateFrameworks directory extracted from the dyld shared cache, there's something called `PrintingPrivate.framework`, which sounds promising. Opening it up in Hopper, I saw that this is indeed the framework I was looking for.
|
||||||
|
|
||||||
<div class="article-content-wide">
|
<img src="/2022/clarus/printingprivate.png" alt="PrintingPrivate in Hopper showing the _PMPrepareAppKitPageSetupDialogWithPrintInfoPrivate function">
|
||||||
<img src="/2022/clarus/printingprivate.png" alt="PrintingPrivate in Hopper showing the _PMPrepareAppKitPageSetupDialogWithPrintInfoPrivate function">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
Looking at the implementation of the prepare function, what immediately jumps out is the call to `_LoadAndGetPrintingUIBundle`. This seems to be yet another layer of indirection with the actual thing implemented in a different bundle. There's also a call in the else branch to the similarly-named `_LoadAndGetPrintCocoaUIBundle`, but let's start with the first one in hopes that it's more common.
|
Looking at the implementation of the prepare function, what immediately jumps out is the call to `_LoadAndGetPrintingUIBundle`. This seems to be yet another layer of indirection with the actual thing implemented in a different bundle. There's also a call in the else branch to the similarly-named `_LoadAndGetPrintCocoaUIBundle`, but let's start with the first one in hopes that it's more common.
|
||||||
|
|
||||||
@ -59,9 +57,8 @@ If you look for the function PrintingPrivate calls, it turns out it winds up in
|
|||||||
|
|
||||||
What's this? A method called `updateClarus`? Could it be? Have we finally reached it?
|
What's this? A method called `updateClarus`? Could it be? Have we finally reached it?
|
||||||
|
|
||||||
<div class="article-content-wide">
|
<img src="/2022/clarus/printingui.png" alt="The PrintingUI binary in Hopper with the search panel showing a bunch of methods with 'clarus' in the name">
|
||||||
<img src="/2022/clarus/printingui.png" alt="The PrintingUI binary in Hopper with the search panel showing a bunch of methods with 'clarus' in the name">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
Yes! Clarus, I'm coming! One method that sounds particularly encouraging is `-[PMPageSetupController setClarusImageView:]`. If I can find out what's setting the image view, maybe that'll lead to where it's being configured with the image.
|
Yes! Clarus, I'm coming! One method that sounds particularly encouraging is `-[PMPageSetupController setClarusImageView:]`. If I can find out what's setting the image view, maybe that'll lead to where it's being configured with the image.
|
||||||
|
|
||||||
@ -118,4 +115,3 @@ let image = bundle.image(forResource: "Clarus")
|
|||||||
I'm not sure if the Mac App Store would consider that using private SPI, so use it at your own risk.
|
I'm not sure if the Mac App Store would consider that using private SPI, so use it at your own risk.
|
||||||
|
|
||||||
It would be very cool to see Clarus return as an SF Symbol some day. If hundreds of icons for various Apple products can go in, so too can everyone's favorite dogcow.
|
It would be very cool to see Clarus return as an SF Symbol some day. If hundreds of icons for various Apple products can go in, so too can everyone's favorite dogcow.
|
||||||
|
|
||||||
|
@ -34,9 +34,8 @@ While the app was in the foreground, ActivityKit would log a message whenever I
|
|||||||
|
|
||||||
I scratched my head at the issue of background updates for a while, and tried a couple things to no avail, until I attached Console.app to my phone and filtered for "activity". At which point, I saw a bunch of messages like these from `sessionkitd` (which is the system daemon that manages live activities):
|
I scratched my head at the issue of background updates for a while, and tried a couple things to no avail, until I attached Console.app to my phone and filtered for "activity". At which point, I saw a bunch of messages like these from `sessionkitd` (which is the system daemon that manages live activities):
|
||||||
|
|
||||||
<div class="article-content-wide">
|
<img src="/2022/live-activities/console.png" alt="com.apple.activitykit sessionkitd xpc Process is playing background media and forbidden to update activity: 984">
|
||||||
<img src="/2022/live-activities/console.png" alt="com.apple.activitykit sessionkitd xpc Process is playing background media and forbidden to update activity: 984">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
Apps playing background audio seem to be completely forbidden from updating Live Activities. The only possible reason for this I can imagine is to prevent apps from making their own now playing activities, rather than relying on the system one. I don't know why this is the case, but whatever, back to trying to find workarounds.
|
Apps playing background audio seem to be completely forbidden from updating Live Activities. The only possible reason for this I can imagine is to prevent apps from making their own now playing activities, rather than relying on the system one. I don't know why this is the case, but whatever, back to trying to find workarounds.
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ So, when put all together, there will be three layers which are (back to front):
|
|||||||
30%, 50% { width: 100%; height: 100px; top: 50px; left: 0; }
|
30%, 50% { width: 100%; height: 100px; top: 50px; left: 0; }
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<div id="layer-diagram" class="article-content-wide" aria-labelled="Diagram of the animation's layer structure. The presenter layer at the back is always visible. The presented layer in the middle fades in and out. The matched layer at the front changes shape between a small square while the presented layer is hidden and a larger rectangle when the presented layer is visible.">
|
<div id="layer-diagram" aria-label="Diagram of the animation's layer structure. The presenter layer at the back is always visible. The presented layer in the middle fades in and out. The matched layer at the front changes shape between a small square while the presented layer is hidden and a larger rectangle when the presented layer is visible.">
|
||||||
<div id="layer-container">
|
<div id="layer-container">
|
||||||
<div id="red"><p>Presenter</p></div>
|
<div id="red"><p>Presenter</p></div>
|
||||||
<div id="green"><div id="background"></div><p>Presented</p></div>
|
<div id="green"><div id="background"></div><p>Presented</p></div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user