Closed MacKeeper28 closed 6 years ago
Haven't had a chance to tinker with Sierra yet, but I will update this to work with it if possible. Hopefully it will be!
Have some installers remorse with sierra =\ gotta fight the beta temptation next time! Lol... So many things broken -_-
Ikr Bartender doesn't work ;-;
Yeah, this is why I don't upgrade to beta OS's. In fact, I usually wait a little while after the initial official release of a new OS X / macOS to upgrade my main system so that everything I rely on is likely to be working and some of the initial bugs have been worked out. Seems to be important for some homebrew installations I rely on.
Yea... Bartender was the first site I went to, and they say they are working on it and expect it in a few weeks... So until then, I guess it'll be good for me to clean up some menubar stuff that I don't use, lol. Surprisingly, the homebrew dependencies I have work fine [: I thank them for not changing the kernel too much :D
I'd like to +1 this issue for when you have a chance to look, thanks! :+1:
Hey @briankendall just wondering if you've had a chance to look into this yet? Thank you very much!
Bad news folks. I've spent some hours trying to fix things for 10.12, and it looks like the Dock has been significantly rewritten in swift, and most of the objective-c methods with conveniently readable names have been replaced by totally anonymous functions with no real name and no indication as to what they do. There's no obvious entry point for changing the behavior of Mission Control, and reverse engineering it and modifying it while it's running may be well beyond my level of knowledge and expertise. Worse still, I don't think it'll be possible to do this using objective-c method swizzling, and instead would require mach_override, which is more difficult and much more likely to break in future updates to macOS.
I'm going to keep trying, because I absolutely loath the new Mission Control behavior, but I may simply be incapable of doing this.
Thanks for the feedback, great to hear you are looking into it! No worries if you can't get it.
Having experienced the return to a sane Mission Control behaviour courtesy of @briankendell I have no intention of going back. Since my iMac is mid-2011 it wouldn't support all of the Sierra bells and whistles anyway plus I don't see anything compelling in Sierra, such as the Improved Notes iCloud features that pushed me to El Capitan.
This puts "truck drivers" like me in a difficult position. With a mid-2011 iMac and a mid-2009 MBP (much loved and still useful with its 500 Gb SSD), these machines will break sooner or later and I'll be forced onto newer un-upgradable hardware and an idiot's idea of how to save space in one of my favourite features and no option to turn it off.
I think this is my Snow Leopard moment.
... and an idiot's idea of how to save space in one of my favourite features and no option to turn it off
I'm glad I'm not the only one who feels this way!
Sadly for me I have to stay on the latest macOS for my work so I'll have no choice but to suffer the new Mission Control UI. I'm still trying to think of other ideas of how to change it, but so far I don't have much other than an improved version of what exists in BetterTouchTool where a tool or something enters Mission Control and then posts some fake mouse move events at the top of the screen to get the spaces to expand. (Improved because BTT's version doesn't work consistently for me and often leaves the mouse at the top of the screen.)
Ha, if you're referring to this Reddit post, I wrote that (which I abandoned after finding forceFullDesktopBar to be a better solution). After updating to Sierra, I came here to see if you had a better solution, and it looks like I have to fall back on my original solution.
Just in case anyone sees this issue I had that is now solved... (OS X 10.11.6) ---quote--- I recently had cause to boot into Safe mode (shift) and since I rebooted from that I’ve been having problems with forceFullDesktopBar. I thought initially Safe mode might have reset csrutil, which it had, but even after switching it back whenever I install forceFullDesktopBar the dock constantly crashes resulting in a flashing desktop. If I uninstall it all is well. ---end quote---
On reflection I don't think it was the safe mode boot, I now suspect an application that had altered the default permissions on /usr/local. A quick 'sudo chown root:wheel /usr/local' and a re-install of forceFullDesktopBar and I am again back to sanity.
I should have spotted it sooner but I've been having a busy few months.
@briankendall I took a look at the headers, and I found something that looked promising:
@interface Dock.ExposeSpacesBarController : NSObject
{
// Error parsing type: , name: display
// Error parsing type: , name: spacesBar
// Error parsing type: , name: spaceScale
// Error parsing type: , name: showSpacesBarOnDemand
// Error parsing type: , name: delegate
// Error parsing type: , name: _dragTargetSpace
// Error parsing type: , name: _dragTileSizePercent
// Error parsing type: , name: _dragObject
// Error parsing type: , name: _dragInWindow
// Error parsing type: , name: _delayDismissCounter
// Error parsing type: , name: _dismissDelayed
// Error parsing type: , name: _coreDragDelay
// Error parsing type: , name: _coreDragSpringTimer
// Error parsing type: , name: _coreDragScrollStart
// Error parsing type: , name: _dragTimerDelay
// Error parsing type: , name: _dragHoldTimer
// Error parsing type: , name: _dragLastLocation
// Error parsing type: , name: _visibility
}
- (CDUnknownBlockType).cxx_destruct;
- (id)init;
- (id)accessibilitySpaceAtGlobalPoint:(struct CGPoint)arg1;
- (void)accessibilitySelectSpaceAtIndex:(long long)arg1;
- (BOOL)accessibilityDeleteSpaceIndex:(long long)arg1;
- (BOOL)accessibilityCanDeleteSpaceIndex:(long long)arg1;
- (void)accessibilityAddUserSpace;
- (struct CGRect)accessibilitySpaceGlobalFrame:(id)arg1;
- (id)accessibilityTitleForSpace:(id)arg1;
@property(nonatomic, readonly) struct CGRect accessibilityAddSpaceFrame;
@property(nonatomic, readonly) BOOL accessibilityCanAddUserSpace;
- (void)setSpaceVisibilityForAnimation:(id)arg1 visible:(BOOL)arg2;
- (BOOL)spaceBarPressed;
- (void)refreshSpaceWindows:(id)arg1;
- (BOOL)dragSpring:(id)arg1;
- (void)cancelSpaceDrag;
- (void)transformToSpace:(id)arg1 space:(id)arg2;
- (id)transformWindowsToSpace:(id)arg1;
- (BOOL)exposeDragCompleted:(CDUnknownBlockType)arg1;
- (void)exposeDragCancelled;
- (BOOL)handleMouseMoved:(id)arg1;
- (BOOL)handleLeftMouseDragged:(id)arg1;
- (void)refreshWindowsOnSpace:(id)arg1;
- (void)moveSpace:(id)arg1 afterSpace:(id)arg2;
- (BOOL)deleteSpace:(id)arg1 targetSpace:(id)arg2 sourceOfTheDelete:(BOOL)arg3;
- (void)setSelectedSpace:(id)arg1;
- (void)insertSpace:(id)arg1 index:(long long)arg2;
- (void)showFullSpacesBar:(BOOL)arg1;
- (void)hideImmediately:(struct _SLSTransaction *)arg1;
- (void)hide:(double)arg1;
- (void)completeFluidHide;
- (void)completeFluidShow;
- (void)showFluidProgress:(double)arg1;
- (void)prepareFluidHide;
- (void)prepareFluidShow;
- (void)showImmediate;
- (void)show:(double)arg1;
@property(nonatomic, readonly) BOOL showingAsMiniBar;
@property(nonatomic, readonly) BOOL canSpringSpace;
@property(nonatomic, readonly) BOOL inSpaceDrag;
@property(nonatomic, retain) _TtC4Dock12ManagedSpace *currentSpace;
@property(nonatomic, readonly) CALayer *eventLayer;
@property(nonatomic, readonly) WALayerKitWindow *eventWindow;
@property(nonatomic, readonly) struct CGRect globalFrame;
@property(nonatomic, readonly) BOOL showing;
@property(nonatomic) BOOL showSpacesBarOnDemand; // @synthesize showSpacesBarOnDemand;
@property(nonatomic, readonly) double height;
@property(nonatomic, readonly) double spaceScale; // @synthesize spaceScale;
@end
Unfortunately, I hit a roadblock when trying to compile and load forceFullDesktopBar (it's not loaded due to a Sandbox violation), so I can't test these methods out. Would you mind going in a bit more detail on how compile and load it?
@saagarjha I did see that class already in the 10.12 Dock, but for whatever reason, none of its methods are ever called. I suspect that it may be defunct code that's not used any longer. If so, why they kept it compiled in is a bit strange. In any case I wasn't able to fix things by swizzling any of its methods.
Also, I just realized I never pushed any of my work in Sierra to GitHub. I have a highly experimental, messy, and non-working branch that I'm not planning on pushing, but there is a branch "sierra_fix" that I just pushed that contains a commit that fixes a link error when trying to build in Sierra.
I'm not sure why you're getting a Sandbox violation -- I've never gotten that. All you should have to do is open the Xcode project, build, and then use terminal to launch forceFullDesktopBar as root. (Of course SIP must be disabled too.) Usually I just cd
into the same directory that the binary and dylibs are being built in by Xcode as it's convenient and forceFullDesktopBar will look for the dylibs it needs in the same directory as itself.
Also, could you let me know what tool you're using to generate that header? I can see class and method names using a disassembler, but that doesn't generally reveal properties.
Yes, I had that problem too initially; apparently the Dock
executable is protected. Running deprotect
on it gives a file that class-dump and Hopper can work with. As for swizzling its methods, you might have to mangle its class name when you use NSClassFromString
. I'll take a look at swizzling completeFluidShow
, if I can get forceFullDesktopBar running.
@saagarjha You didn't have any luck hooking into any of the Dock's functions, did you?
For what it's worth, I have an alternative method of bringing back the original desktop bar in Sierra via a program that triggers Mission Control in a special (read: hacky) way. I'll put it up in GitHub in the not too distant future.
No, I haven't had too much luck with swizzling those methods, though I haven't put a lot of time into it yet. However, I'm still pretty sure they're being called, 1) because their names are too perfect to be a coincidence and 2) if they we're called, they would have optimized out during compilation, right? I'm guessing that the injection method forceFullDesktopBar is using just doesn't work on Sierra. I'll look online to see if anyone else has had success injecting into Dock (using SIMBL, maybe?)
Either way, I'd love to see the your method!
Hey, has the method @briankendall spoke about been uploaded yet? Thanks!
@wwdc17 No, not yet. I've been very busy with other stuff and haven't had a chance to work on it. I'm currently trying to slap it together in a form that other people can use and make a new repo for it. I'll update you here when I've got that ready.
OK, thanks!
@wwdc17 and everyone else, check out the repo I just made: https://github.com/briankendall/missionControlFullDesktopBar
That in conjunction with a tool like BetterTouchTool will more or less allow you to get Mission Control working the way you want again.
Thanks! Testing now, will report anything I find!
@briankendall I found a function that controls expanding the thumbnails, and have a working forceFullDesktopBar in my repository. I'll leave it up to you choose whether this is worth merging.
@saagarjha Great work! Seems that you've dug into this deeper than I was able to. I'd love to be able to get this app working again, as my other solution (missionControlFullDesktopBar) isn't nearly as good.
However since this solution is overwriting the Dock's code in memory rather than swizzling an objective-c method via the objective-c runtime, I worry that it will break a lot more frequently between minor macOS updates since any slight modification to the function it's patching will likely prevent it from being able to find the bytes it needs to patch, requiring an update to the app.
More importantly, with your current implementation, if a macOS update changes the Dock so that the prologue its searching for remains as is but the rest of that function changes, there's potential for it patching the wrong part of the Dock's code resulting in crashes.
I'm not sure how likely those scenarios actually are, but I feel like a better implementation of this would be to perform a single search looking for the bytes that starts at the beginning of this function and ends with the bytes you want to patch. That way, you a) don't risk patching anything in a completely different part of the Dock, and b) you don't patch the function if its been modified in a future update. That search is more likely to fail after an update, but I'd rather have the app fail to patch something than risk patching the wrong thing and risk seriously destabilize the user's system (as a constantly crashing Dock practically renders your mac useless).
This sort of low-level binary patching is slightly outside my area of expertise, though. I'm curious what your thoughts are. If we can agree that there's a reasonably stable way of patching the Dock using this method than I may very well want to merge your changes in.
If you like you could make a pull request so that we can discuss your work in its own thread.
See #7
For the people following this thread, good news! I may have found an alternative way of getting forceFullDesktopBar to work in both macOS 10.13 and 10.14 without needing to use unstable methods like mach_override. The method I've found seems to be relatively safe and robust, but I'm going to need to test it further before I know for sure and can update the app.
For people following development, here's an explanation of how it works:
It makes use of fishhook to override a named symbol in the Dock, as well as using Objective-C method swizzling. The idea is to swizzle the changeMode:
method of _TtC4Dock8WVExpose
and then to replace CGSCurrentInputPointerPosition
using fishhook. The new version of changeMode:
checks to see if the argument it was passed equals 1 (indicating the user is about to enter Mission Control) at which point it sets a flag. The replacement version of CGSCurrentInputPointerPosition
checks to see if the flag is set, and if so returns a coordinate of something like 200,40
and unsets the flag, otherwise it just calls the original CGSCurrentInputPointerPosition
. That way, every time the user enters Mission Control, the Dock will query the current location of the mouse cursor, think it's at the top of the screen, and cause Mission Control to open with the full desktop bar. In all other respects its behavior should remain the same.
As I said, I'm going to test this some more to make sure it works as well as I hope it does, and then I may go ahead and make a new release. 🎉
Awesome! If you push a branch I can test it out and see if it works 👍
Nice work! I think you can get by with a standard DYLD_INTERPOSE
instead of fishhook here, since this is macOS.
@justJS Thanks! Would you try checking out the high_sierra_fix branch and seeing if it works for you? I've tested in both 10.13.6 and 10.14.0 and so far it seems to work in both.
Do I need to build it or just run install.sh? Doesn’t seem to work for me, except maybe when I invoke Mission Control from a full screen app. I’m on 10.14.0 as well.
On Oct 8, 2018, at 6:32 AM, Brian Kendall notifications@github.com wrote:
@justJS Could you try checking out the high_sierra_fix branch and seeing if it works for you? I've tested in both 10.13.6 and 10.14.0 and so far it seems to work in both.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.
@justJS You should be able to run install.sh. Did you remember to disable SIP?
Yeah, i've got SIP completely disabled for other reasons. Also tried restarting. I don't have experience with hacking the dock but if you tell me how to debug I can try.
@justJS Could you do the following:
killall Dock
forceFullDesktopBar
as root from the install directoryThey should look something like this (though these are the messages that get printed when everything is working):
Somebodys-Mac:install moof$ sudo ./forceFullDesktopBar
2018-10-08 15:27:35.030 forceFullDesktopBar[487:4470] Searching for Dock processes...
2018-10-08 15:27:35.030 forceFullDesktopBar[487:4470] Found Dock process... will inject into pid: 484
module: 0x7fdbfac0dd10
bootstrapfn: 0x1050d8d90
default 15:27:35.045192 -0400 Dock forceFullDesktopBar: dockInjection installed and running
default 15:27:35.045335 -0400 Dock forceFullDesktopBar: Using 10.13 and later method...
default 15:27:35.048683 -0400 Dock forceFullDesktopBar: Successfully swizzled target method in _TtC4Dock8WVExpose class and rebound CGSCurrentInputPointerPosition symbol
2018-10-09 07:27:37.153 forceFullDesktopBar[19917:1518948] Searching for Dock processes...
2018-10-09 07:27:37.154 forceFullDesktopBar[19917:1518948] Found Dock process... will inject into pid: 19892
module: 0x7ff32ce00c80
bootstrapfn: 0x108836d90
default 07:27:37.153520 +0800 forceFullDesktopBar Searching for Dock processes...
default 07:27:37.154613 +0800 forceFullDesktopBar Found Dock process... will inject into pid: 19892
default 07:27:37.159724 +0800 Dock forceFullDesktopBar: dockInjection installed and running
default 07:27:37.159898 +0800 Dock forceFullDesktopBar: Using 10.13 and later method...
default 07:27:37.372727 +0800 Dock forceFullDesktopBar: Successfully swizzled target method in _TtC4Dock8WVExpose class and rebound CGSCurrentInputPointerPosition symbol
It seems like it succeeded, but the behavior hasn't changed in Mission Control.
@justJS Interesting... What method are you using to invoke mission control? Also, are you running macOS 10.14.0 or do you have one of the developer betas of 10.14.1 installed?
I'm swiping up with 3 fingers. I'm on the public Mojave release.
Actually I haven't tested that method of triggering Mission Control yet since I'm working in a VM. What happens if you press Control+Up? (or whichever hot key is currently set up to invoke Mission Control)
Still nothing :/ (Tried to take a video but Github isn't letting me upload it)
Doesn't exactly show much, but here (this is with ControlUp):
I'm trying to run it on my MacBook and every time the app tries to inject its payload into the Dock it causes the Dock to crash. I've seeing the same issue on a virtual 10.11 system. So something is clearly wrong with mach_inject right now. I don't know if that's related to it not working on your system but it's possible that it is. I'm going to have to dig deeper to figure out what's going wrong.
Just built a fresh copy of forceFullDesktopBar from the high_sierra_fix branch; ^+↑ works for me on macOS Mojave 10.14.1 Beta (18B57c). Swiping up on the trackpad does nothing. Using the debugger, it seems like Dock doesn't call -[Dock.WVExpose changeMode:]
for the fluid gesture.
Using the debugger, it seems like Dock doesn't call -[Dock.WVExpose changeMode:] for the fluid gesture.
Ah, too bad. I can use the same method if we can find a function with a symbol that gets called for trackpad gestures. I'll look into it, and I'll keep digging into the issues with mach_inject too.
@saagarjha mach_inject is a bit of a black box for me, though I've started reading through it to try and understand it better. Do you have any familiarity with it or the methods it uses?
I have a general idea of what it's doing; it's scanning for new processes and then allocating a stack in the remote process and pivoting to it. Why, is there something in particular that needs to be changed?
I don't know, but I'm trying to dig into why things are crashing on a few of my systems. I can't test forceFullDesktopBar with a trackpad right now because mach_inject keeps crashing the Dock on my laptop. But not on my desktop. What I do know is that the crash is probably happening in bootstrap()
based on the call stack in the resultant crash log. If I comment out everything except the first and last line in bootstrap()
(so that the thread does nothing other than call _pthread_set_self
and thread_suspend
) the crash still occurs.
Either way, the relevant part of the crash log looks like one of these:
Thread 3 Crashed:
0 ??? 0x0000000106f082b9 0 + 4411392697
Thread 3 Crashed:
0 ??? 0x0000000105ea0ee0 0 + 4394192608
1 ??? 0x00000deadbea7dad 0 + 15302363086253
The first is on my 10.11 system, and the second is on my laptop. At least in the second crash log we can see that we're in the bootstrap function due to its fake return address at the bottom of the stack. I haven't had a chance to use a debugger yet to try and see precisely where the crash is happening.
@saagarjha Which debugger are you using on the Dock?
LLDB?
I'm facing a serious heisenbug here. On my 10.11 system, the crash goes away if I install Xcode or the command line developer tools, so I can't debug it in a state where the crash occurs. And on my 10.14 system (my laptop), if I attach lldb to the Dock, the crash goes away. Note that the payload still doesn't get properly injected into the Dock so Misson Control behavior is unaltered. But I can't trace where the crash is happening because there isn't one. I'm hitting a brick wall with this issue and I'm not sure what I can do about it.
Note that the payload still doesn't get properly injected into the Dock so Misson Control behavior is unaltered.
You can try to debug this, at least. What I usually do is "run" (⌘+R in Xcode) the forceFullDesktopBar scheme with the target executable set to Dock (Product > Scheme > Edit Scheme…) and "Wait for executable to be launched" checked:
I put a breakpoint on the first line of install
(or wherever you want) and then I run sudo ./uninstall.sh && killall Dock && sudo ./install.sh
from the install folder. Usually Xcode catches the process before the constructor function runs so your breakpoint is hit.
Sadly the same method isn't working for me on my laptop. Something is definitely going wrong with mach_inject, because either it crashes the Dock when the debugger isn't attached to it, or none of the code in either bootstrap of dockInjection is executed when a debugger is attached. (No print statements execute, and no breakpoints are triggered.)
I may try contacting the authors of mach_inject. They say not to come to them with crash reports but I'm not sure what else I can do at this point, especially since I'm getting inconsistent results between two different systems running the same version of macOS.
After uninstallation and reinstallation, it still doesn't work on 10.12.