Skip to content

Commit

Permalink
new version of quick cursor
Browse files Browse the repository at this point in the history
  • Loading branch information
jessegrosjean committed Sep 3, 2009
1 parent 208a756 commit f1ecb58
Show file tree
Hide file tree
Showing 213 changed files with 33,525 additions and 870 deletions.
71 changes: 71 additions & 0 deletions BBAppSessionLoginState.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// NSLoginItems.h
//
// Created by BrotherBard on 4/18/09.
// Copyright 2009 BrotherBard <nkinsinger at earthlink dot net>. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

#import <Cocoa/Cocoa.h>


// This singleton class handles the state of the running app in the users login items list (called
// Session Login items by the LSSharedFileList API).

// It sets up an observer of the Session Login List and keeps track if the user changes the state
// in System Preferences or any other outside app. The property isAppInSessionLoginList will be updated
// when that happens.

// isAppInSessionLoginList is only meant to represent the state, so do not set it yourself.
// Use the four instance methods for that. When changing the state, the state is re-read from LSSharedFileList
// so isAppInSessionLoginList should never not represent the current state.

// Since there is no way to recover or re-apply a state change there are no returned errors. If it doesn't
// work then isAppInSessionLoginList will not be updated.

// NOTE: The LSSharedFileList API is only documented in the header file at:
// file://localhost/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Headers/LSSharedFileList.h



@interface BBAppSessionLoginState : NSObject
{
LSSharedFileListRef _sessionLoginItemsList;
NSString *_appPath;

BOOL isAppInSessionLoginList;
}
// this is the latest state of whether the app is in the login list
// observe it for KVC changes, setting it will have no effect, use the methods below
@property (assign) BOOL isAppInSessionLoginList;


// designated init/access of singleton
+ (id)sharedController;


- (void)toggleAppSessionLoginListState;
- (void)setAppSessionLoginListState:(BOOL)state;

- (void)removeAppFromSessionLoginList;
- (void)addAppToSessionLoginList;

@end
220 changes: 220 additions & 0 deletions BBAppSessionLoginState.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
//
// NSLoginItems.m
//
// Created by BrotherBard on 4/18/09.
// Copyright 2009 BrotherBard <nkinsinger at earthlink dot net>. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

#import "BBAppSessionLoginState.h"

// Private
@interface BBAppSessionLoginState()

- (LSSharedFileListItemRef)itemRefForApp;
- (void)updateLoginItemState;

@end



@implementation BBAppSessionLoginState

@synthesize isAppInSessionLoginList;


- (void)setIsAppInSessionLoginList:(BOOL)isInList {
if (isAppInSessionLoginList != isInList) {
isAppInSessionLoginList = isInList;
if (isInList) {
[self addAppToSessionLoginList];
} else {
[self removeAppFromSessionLoginList];
}
}
}

// When something changes I get six calls to this method. The first two have the same seed and
// the last four do too. I'm not sure if it is something wierd on my computer, but I compare the
// seed to the previous one to stop updating the login state too often.
static void SharedFileListChanged(LSSharedFileListRef list, void *context)
{
static UInt32 previousSeed = 0;

// there are other types of lists, so make sure we are just looking at the Session Login list
LSSharedFileListRef sessionLoginList = (LSSharedFileListRef)context;

if (list == sessionLoginList) {
UInt32 seed = LSSharedFileListGetSeedValue(list);
if (seed > previousSeed) {
[[BBAppSessionLoginState sharedController] updateLoginItemState];
previousSeed = seed;
}
}
}


+ (id)sharedController
{
static BBAppSessionLoginState *sharedController = nil;
if (!sharedController)
sharedController = [[self alloc] init];

return sharedController;
}


- (id)init
{
self = [super init];
if(!self) return nil;

_sessionLoginItemsList = LSSharedFileListCreate(kCFAllocatorDefault, // inAllocator
kLSSharedFileListSessionLoginItems, // inListType
NULL); // listOptions
if(!_sessionLoginItemsList) {
[self release];
return nil;
}

LSSharedFileListAddObserver(_sessionLoginItemsList, // inList
[[NSRunLoop mainRunLoop] getCFRunLoop], // inRunloop
kCFRunLoopDefaultMode, // inRunloopMode
SharedFileListChanged, // callback
_sessionLoginItemsList); // context

_appPath = [[NSBundle mainBundle] bundlePath];
[self updateLoginItemState];

return self;
}


- (void)dealloc
{
if (_sessionLoginItemsList) {
LSSharedFileListRemoveObserver(_sessionLoginItemsList, // inList
[[NSRunLoop mainRunLoop] getCFRunLoop], // inRunloop
kCFRunLoopDefaultMode, // inRunloopMode
SharedFileListChanged, // callback
_sessionLoginItemsList); // context

CFRelease(_sessionLoginItemsList);
}

[super dealloc];
}


- (LSSharedFileListItemRef)itemRefForApp
{
UInt32 seed;
NSArray *items = (NSArray *)LSSharedFileListCopySnapshot(_sessionLoginItemsList, &seed);

for (id item in items) {
LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)item;

NSURL *theURL;
LSSharedFileListItemResolve(itemRef, // inItem
kLSSharedFileListNoUserInteraction, // inFlags
(CFURLRef*)&theURL, // outURL
NULL); // outFSRef
[theURL autorelease];

if ([_appPath isEqualToString:[theURL path]])
return itemRef;
}

return NULL;
}


- (void)updateLoginItemState
{
BOOL currentState = [self itemRefForApp] ? YES : NO;
if (self.isAppInSessionLoginList != currentState)
isAppInSessionLoginList = currentState;
}


- (void)toggleAppSessionLoginListState
{
if (isAppInSessionLoginList)
[self removeAppFromSessionLoginList];
else
[self addAppToSessionLoginList];
}


- (void)setAppSessionLoginListState:(BOOL)state
{
if (state)
[self addAppToSessionLoginList];
else
[self removeAppFromSessionLoginList];
}


- (void)removeAppFromSessionLoginList
{
LSSharedFileListItemRef itemRef = [self itemRefForApp];

if (itemRef) {
OSStatus error = LSSharedFileListItemRemove(_sessionLoginItemsList, itemRef);
if (error != noErr)
NSLog(@"Failed to remove App from Session Login Items");
}

[self updateLoginItemState];
}


- (void)addAppToSessionLoginList
{
LSSharedFileListItemRef itemRef = [self itemRefForApp];

if (!itemRef) {
// I believe the default is to not Hide the app, but I'm not really sure because the
// kLSSharedFileListItemHidden property is not read corretly by LSSharedFileListItemCopyProperty.
// I'm just setting it here to have a default value.
NSDictionary* propertiesToSet = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO]
forKey:(id)kLSSharedFileListItemHidden];
NSURL *url = [NSURL fileURLWithPath:_appPath];
NSLog(@"%@", url);

itemRef = LSSharedFileListInsertItemURL(_sessionLoginItemsList, // inList
kLSSharedFileListItemLast, // insertAfterThisItem
NULL, // inDisplayName - NULL = will use app name
NULL, // inIconRef - NULL = will use app icon
(CFURLRef)url, // inURL
(CFDictionaryRef)propertiesToSet, // inPropertiesToSet
NULL); // inPropertiesToClear

if (itemRef)
CFRelease(itemRef);
else
NSLog(@"Failed to add App to Session Login Items");
}

[self updateLoginItemState];
}

@end
Binary file modified English.lproj/InfoPlist.strings
Binary file not shown.
Loading

0 comments on commit f1ecb58

Please sign in to comment.