macOS: Disable NSAutoFillHeuristicController on macOS 26 (#38179)

Smit Barmase created

Closes #33182

From
https://github.com/zed-industries/zed/issues/33182#issuecomment-3289846957,
thanks @mitchellh.

Release Notes:

- Fixed an issue where scrolling could sometimes feel choppy on macOS
26.

Change summary

crates/gpui/src/platform/mac/platform.rs | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

Detailed changes

crates/gpui/src/platform/mac/platform.rs 🔗

@@ -82,6 +82,10 @@ unsafe fn build_classes() {
         APP_DELEGATE_CLASS = unsafe {
             let mut decl = ClassDecl::new("GPUIApplicationDelegate", class!(NSResponder)).unwrap();
             decl.add_ivar::<*mut c_void>(MAC_PLATFORM_IVAR);
+            decl.add_method(
+                sel!(applicationWillFinishLaunching:),
+                will_finish_launching as extern "C" fn(&mut Object, Sel, id),
+            );
             decl.add_method(
                 sel!(applicationDidFinishLaunching:),
                 did_finish_launching as extern "C" fn(&mut Object, Sel, id),
@@ -1356,6 +1360,25 @@ unsafe fn get_mac_platform(object: &mut Object) -> &MacPlatform {
     }
 }
 
+extern "C" fn will_finish_launching(_this: &mut Object, _: Sel, _: id) {
+    unsafe {
+        let user_defaults: id = msg_send![class!(NSUserDefaults), standardUserDefaults];
+        let defaults_dict: id = msg_send![class!(NSMutableDictionary), dictionary];
+
+        // The autofill heuristic controller causes slowdown and high CPU usage.
+        // We don't know exactly why. This disables the full heuristic controller.
+        //
+        // Adapted from: https://github.com/ghostty-org/ghostty/pull/8625
+        let false_value: id = msg_send![class!(NSNumber), numberWithBool:false];
+        let _: () = msg_send![defaults_dict,
+            setObject: false_value
+            forKey: ns_string("NSAutoFillHeuristicControllerEnabled")
+        ];
+
+        let _: () = msg_send![user_defaults, registerDefaults:defaults_dict];
+    }
+}
+
 extern "C" fn did_finish_launching(this: &mut Object, _: Sel, _: id) {
     unsafe {
         let app: id = msg_send![APP_CLASS, sharedApplication];