Re: Accessing the FUS menu?
Re: Accessing the FUS menu?
- Subject: Re: Accessing the FUS menu?
- From: Bjoern Kriews <email@hidden>
- Date: Tue, 30 Mar 2004 23:26:01 +0200
On 30.03.2004, at 17:36, Randall Meadows wrote:
Can anyone shed any light on how one might gain access to the Fast
User Switching menu?
Do you want to be able to switch users programmatically ?
/System/Library/CoreServices/Menu\
Extras/User.menu/Contents/Resources/CGSession -switchToUserID <numeric
id>
(undocumented, subject to break and cause confusion)
Or do you want to hack the menu ?
(even less documented, but I tried it to explore some advanced posing
and because I wanted "bkr" instead of
the rather longish "Bjoern Kriews" in there. Accidentally, it adds a
"Suspend" menu item -
I hear this one was available in early betas - well the code is still
there -
and CGSession has a -suspend switch btw.
I wouldn't ship this to people who don't know about the
undocumented-ness of this stuff,
therefore I release the following Code with NO WARRANTY under the GNU
Public License,
see
http://www.gnu.org/licenses/gpl.html.
create a bundle project with the following files or email me for a
project archive.
Hope that helps, Bjoern
--- UserPoser.h ---
#import <Foundation/Foundation.h>
// make ourselves a subclass of "just something" - we will change that
later
@interface UserPoser : NSView
+ (void)load;
// setAttributedString is used to receiving NSCFStrings
- (void)setAttributedString:(NSString *) aString
isMenuDown:(char)isDown;
--- UserPoser.m ---
// All rights reversed.
#import "UserPoser.h"
#import <objc/objc-class.h>
#import <unistd.h>
@implementation UserPoser
+ (void)load
{
Class usv;
NSString *userExtraPath = @"/System/Library/CoreServices/Menu
Extras/User.menu";
NSBundle *userExtraBundle;
NSString *mainBundleIdentifier;
mainBundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
if( NO == [mainBundleIdentifier isEqualToString:
@"com.apple.systemuiserver"] ) {
//NSLog(@"UserPoser not interested in '%@'",
mainBundleIdentifier);
return;
}
if( nil == ( userExtraBundle = [NSBundle bundleWithPath:
userExtraPath] ) ) {
NSLog(@"could not create bundle for '%@' - giving up",
userExtraPath);
return;
}
if( NO == [userExtraBundle load] ) {
NSLog(@"could not load %@ - giving up", userExtraBundle);
return;
}
if( nil == ( usv = NSClassFromString(@"UserSwitcherView") ) ) {
NSLog(@"could not find class UserSwitcherView - giving up");
return;
}
//NSLog(@"UserPoser was %@", [UserPoser superclass]);
// we should _really_ not be doing that - but Objective-C is so
inviting...
( (struct objc_class *) [UserPoser class] )->super_class = usv;
NSLog(@"UserPoser now posing for %@ in %@", [UserPoser superclass],
mainBundleIdentifier);
[UserPoser poseAsClass: usv];
}
// called when switcher menu title is changed
// setAttributedString is used to receiving NSCFStrings
- (void)setAttributedString:(NSString *) aString isMenuDown:(char)isDown
{
unsigned int flags = [[NSApp currentEvent] modifierFlags];
NSString *shortName;
shortName = isDown ? ( flags & NSAlternateKeyMask ? [NSString
stringWithFormat: @"%d", geteuid()] : @";-)" ) : NSUserName();
// NSLog(@"UserPoser: setAttributedString called with '%@' -> '%@',
%d - ", aString, shortName, isDown);
[super setAttributedString: shortName isMenuDown:isDown]; //
warning ok
if( isDown ) { // this should be in a AppleUser Posers -createMenu,
but I didn't test that
id userSwitcher = nil;
NSMenu *menu = nil;
NSArray *items;
// need to talk straight here
object_getInstanceVariable( self, "mUserSwitcher", (void**)
&userSwitcher ); /* = AppleUser:NSMenuExtra */
object_getInstanceVariable( userSwitcher, "_menu", (void**)
&menu ); /* NSMenuExtra attribute */
items = [menu itemArray];
// since we are suboptimally called too often (see above) we
have to check if kilroy was here
if( [[items lastObject] action] != @selector(SuspendAccount:) )
{
[[menu insertItemWithTitle: @"Suspense..." action:
@selector(SuspendAccount:) keyEquivalent: @"" atIndex: [items count]]
setTarget: userSwitcher];
}
}
}
@end
--- Info file to put in Library/InputManagers/UserPoser alogn with
UserPoser.bundle ---
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist SYSTEM
"file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="0.9">
<dict>
<key>BundleName</key>
<string>UserPoser.bundle</string>
<key>LoadBundleOnLaunch</key>
<string>YES</string>
<key>LocalizedNames</key>
<dict>
<key>English</key>
<string>UserPoser</string>
</dict>
<key>NoMenuEntry</key>
<string>YES</string>
</dict>
</plist>
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.