forked from phoenix3200/libstatusbar
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1 parent
8810f06
commit a92bf30
Showing
16 changed files
with
1,376 additions
and
415 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,22 @@ | ||
|
||
@interface StatusBarItemClient : NSObject | ||
@interface LSStatusBarClient : NSObject | ||
{ | ||
bool _isLocal; | ||
NSDictionary* _currentMessage; | ||
NSArray* _titleStrings; | ||
} | ||
|
||
+ (id) sharedInstance; | ||
|
||
- (id) init; | ||
|
||
- (NSDictionary*) currentMessage; | ||
- (void) retrieveCurrentMessage; | ||
- (bool) processCurrentMessage; | ||
- (void) updateStatusBar; | ||
|
||
- (void) setProperties: (id) properties forItem: (NSString*) item; | ||
|
||
- (NSString*) titleStringAtIndex: (int) idx; | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,265 @@ | ||
|
||
//#define TESTING | ||
|
||
#import "common.h" | ||
#import "defines.h" | ||
|
||
#import "classes.h" | ||
#import "LSStatusBarClient.h" | ||
#import "LSStatusBarServer.h" | ||
#import "UIStatusBarCustomItem.h" | ||
|
||
void UpdateStatusBar(CFNotificationCenterRef center, LSStatusBarClient* client) | ||
{ | ||
[client updateStatusBar]; | ||
} | ||
|
||
@implementation LSStatusBarClient | ||
|
||
+ (id) sharedInstance | ||
{ | ||
static LSStatusBarClient* client; | ||
|
||
if(!client) | ||
{ | ||
client = [[self alloc] init]; | ||
} | ||
return client; | ||
} | ||
|
||
- (id) init | ||
{ | ||
self = [super init]; | ||
if(self) | ||
{ | ||
_isLocal = $SpringBoard ? YES : NO; | ||
|
||
CFNotificationCenterRef darwin = CFNotificationCenterGetDarwinNotifyCenter(); | ||
CFNotificationCenterAddObserver(darwin, self, (CFNotificationCallback) UpdateStatusBar, (CFStringRef) @"libstatusbar_changed", NULL, NULL); | ||
|
||
[self updateStatusBar]; | ||
|
||
} | ||
return self; | ||
} | ||
|
||
- (NSDictionary*) currentMessage | ||
{ | ||
return _currentMessage; | ||
} | ||
|
||
- (void) retrieveCurrentMessage | ||
{ | ||
[_currentMessage release]; | ||
if(_isLocal) | ||
{ | ||
_currentMessage = [[[LSStatusBarServer sharedInstance] currentMessage] retain]; | ||
} | ||
else | ||
{ CPDistributedMessagingCenter* dmc = [CPDistributedMessagingCenter centerNamed: @"com.apple.springboard.libstatusbar"]; | ||
|
||
_currentMessage = [[dmc sendMessageAndReceiveReplyName: @"currentMessage" userInfo: nil] retain]; | ||
} | ||
NSDesc(_currentMessage); | ||
} | ||
|
||
- (NSString*) titleStringAtIndex: (int) idx | ||
{ | ||
if(idx < (int)[_titleStrings count]) | ||
{ | ||
return [_titleStrings objectAtIndex: idx]; | ||
} | ||
return nil; | ||
} | ||
|
||
- (bool) processCurrentMessage | ||
{ | ||
bool ret = NO; | ||
|
||
//NSMutableDictionary *processedMessage = [_currentMessage mutableCopy]; | ||
|
||
NSMutableArray* processedKeys = [[_currentMessage objectForKey: @"keys"] mutableCopy]; | ||
|
||
|
||
[_titleStrings release]; | ||
_titleStrings = [[_currentMessage objectForKey: @"titleStrings"] retain]; | ||
|
||
|
||
/* | ||
if(_titleStrings) | ||
{ | ||
[processedMessage removeObjectForKey: @"titleStrings"]; | ||
} | ||
*/ | ||
|
||
int keyidx = 22; | ||
|
||
NSDesc(_currentMessage); | ||
extern NSMutableArray* customItems[3]; | ||
|
||
for(int i=0; i<3; i++) | ||
{ | ||
if(customItems[i]) | ||
{ | ||
NSDesc(customItems[i]); | ||
int cnt = [customItems[i] count]-1; | ||
/* | ||
extern NSMutableArray* allCustomItems; | ||
if(allCustomItems) | ||
{ | ||
int cnt = [allCustomItems count]-1; | ||
*/ | ||
for(; cnt>= 0; cnt--) | ||
// for(UIStatusBarCustomItem* item in customItems[i]) | ||
{ | ||
UIStatusBarCustomItem* item = [customItems[i] objectAtIndex: cnt]; | ||
//UIStatusBarCustomItem* item = [allCustomItems objectAtIndex: cnt]; | ||
|
||
NSString* indicatorName = [item indicatorName]; | ||
|
||
NSObject* properties = nil; | ||
if(_currentMessage) | ||
{ | ||
properties = [_currentMessage objectForKey: indicatorName]; | ||
} | ||
|
||
if(!properties) | ||
{ | ||
ret = YES; | ||
|
||
NSLog(@"removing item: %@", indicatorName); | ||
[item removeAllViews]; | ||
//[allCustomItems removeObjectAtIndex: cnt]; | ||
[customItems[i] removeObjectAtIndex: cnt]; | ||
// [customItems[i] removeObject: item]; | ||
} | ||
else | ||
{ | ||
NSLog(@"keeping item: %@", indicatorName); | ||
//[processedMessage removeObjectForKey: indicatorName]; | ||
[processedKeys removeObject: indicatorName]; | ||
|
||
int &type(MSHookIvar<int>(item, "_type")); | ||
if(type > keyidx) | ||
keyidx = type; | ||
|
||
item.properties = [properties isKindOfClass: [NSDictionary class]] ? (NSDictionary*) properties : nil; | ||
} | ||
} | ||
} | ||
else | ||
{ | ||
NSLog(@"creating array"); | ||
customItems[i] = [[NSMutableArray alloc] init]; | ||
} | ||
} | ||
|
||
keyidx++; | ||
|
||
if(processedKeys && [processedKeys count]) | ||
{ | ||
ret = YES; | ||
GETCLASS(UIStatusBarItem); | ||
for(NSString* key in processedKeys)//processedMessage) | ||
{ | ||
NSLog(@"adding item: %@", key); | ||
|
||
UIStatusBarCustomItem* item = [$UIStatusBarItem itemWithType: keyidx++]; | ||
[item setIndicatorName: key]; | ||
|
||
NSObject* properties = [_currentMessage objectForKey: key]; | ||
item.properties = [properties isKindOfClass: [NSDictionary class]] ? (NSDictionary*) properties : nil; | ||
|
||
|
||
if([item leftOrder]) | ||
{ | ||
if(!customItems[0]) | ||
{ | ||
customItems[0] = [[NSMutableArray alloc] init]; | ||
} | ||
[customItems[0] addObject: item]; | ||
} | ||
else if([item rightOrder]) | ||
{ | ||
if(!customItems[1]) | ||
{ | ||
customItems[1] = [[NSMutableArray alloc] init]; | ||
} | ||
[customItems[1] addObject: item]; | ||
} | ||
else | ||
{ | ||
if(!customItems[2]) | ||
{ | ||
customItems[2] = [[NSMutableArray alloc] init]; | ||
} | ||
[customItems[2] addObject: item]; | ||
} | ||
} | ||
} | ||
|
||
|
||
//if(_titleStrings && [_titleStrings count]) | ||
|
||
// too many cases; just refresh the damn thing. | ||
{ | ||
ret = YES; | ||
} | ||
|
||
|
||
|
||
[processedKeys release]; | ||
|
||
NSLog(@"processCurrentMessage? %@", ret ? @"YES" : @"NO"); | ||
return ret; | ||
} | ||
|
||
- (void) updateStatusBar | ||
{ | ||
SelLog(); | ||
|
||
[self retrieveCurrentMessage]; | ||
|
||
// need a decent guard band because we do call before UIApp exists | ||
if([self processCurrentMessage] && UIApp) | ||
{ | ||
UIStatusBarForegroundView* _foregroundView = MSHookIvar<UIStatusBarForegroundView*>([UIApp statusBar], "_foregroundView"); | ||
if(_foregroundView) | ||
{ | ||
//[_foregroundView _reflowItemViewsWithDuration: 0.0f suppressCenterAnimation: YES]; | ||
|
||
[_foregroundView setStatusBarData: (StatusBarData*) [$UIStatusBarServer getStatusBarData] actions: 1 animated: YES]; | ||
} | ||
} | ||
} | ||
|
||
- (void) setProperties: (id) properties forItem: (NSString*) item | ||
{ | ||
SelLog(); | ||
if(item) | ||
{ | ||
NSString* bundleId = [[NSBundle mainBundle] bundleIdentifier]; | ||
|
||
if(_isLocal) | ||
{ | ||
[[LSStatusBarServer sharedInstance] setProperties: properties forItem: item bundle: bundleId]; | ||
} | ||
else | ||
{ | ||
|
||
|
||
NSDictionary* dict = [[NSDictionary alloc] initWithObjectsAndKeys: | ||
item, @"item", | ||
properties, @"properties", | ||
bundleId, @"bundle", | ||
nil]; | ||
|
||
CPDistributedMessagingCenter* dmc = [CPDistributedMessagingCenter centerNamed: @"com.apple.springboard.libstatusbar"]; | ||
|
||
[dmc sendMessageName: @"setProperties:userInfo:" userInfo: dict]; | ||
[dict release]; | ||
} | ||
} | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
enum StatusBarAlignment | ||
{ | ||
StatusBarAlignmentLeft = 1, | ||
StatusBarAlignmentRight = 2, | ||
StatusBarAlignmentCenter = 4 | ||
}; | ||
|
||
|
||
@interface LSStatusBarItem : NSObject | ||
{ | ||
NSString* _identifier; | ||
NSMutableDictionary* _properties; | ||
NSMutableSet* _delegates; | ||
BOOL _manualUpdate; | ||
} | ||
|
||
+ (void) updateItems; | ||
|
||
- (void) dealloc; | ||
- (void) setProperties: (NSDictionary*) dict; | ||
|
||
@end | ||
|
||
|
||
@interface LSStatusBarItem (API) | ||
|
||
- (id) initWithIdentifier: (NSString*) identifier alignment: (StatusBarAlignment) alignment; | ||
|
||
// bitmasks (e.g. left or right) are not supported yet | ||
@property (nonatomic, readonly) StatusBarAlignment alignment; | ||
|
||
@property (nonatomic, getter=isVisible) BOOL visible; | ||
|
||
// useful only with left/right alignment - will throw error for center alignment | ||
@property (nonatomic, assign) NSString* imageName; | ||
|
||
// useful only with center alignment - will throw error otherwise | ||
// will not be visible on the lockscreen | ||
@property (nonatomic, assign) NSString* titleString; | ||
|
||
// set to NO and manually call update if you need to make multiple changes | ||
@property (nonatomic, getter=isManualUpdate) BOOL manualUpdate; | ||
|
||
// manually call if manualUpdate = YES | ||
- (void) update; | ||
|
||
@end | ||
|
||
|
||
|
||
|
||
@interface LSStatusBarItem (Unimplemented) | ||
|
||
|
||
// leave alone unless you want to limit which apps your icon shows up in | ||
@property (nonatomic, assign) NSString* exclusiveToApp; | ||
|
||
// convenience methods? | ||
//@property (nonatomic, getter=isSpringBoardOnly) BOOL springBoardOnly; | ||
//@property (getter=isCurrentAppOnly) BOOL currentAppOnly; | ||
|
||
// delegate must respond to @selector(statusBarAction:); only valid from inside of SpringBoard | ||
- (void) addTouchDelegate: (id) delegate; | ||
- (void) removeTouchDelegate: (id) delegate; | ||
|
||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,257 @@ | ||
|
||
|
||
//#define TESTING | ||
|
||
#import "common.h" | ||
#import "defines.h" | ||
|
||
#import "LSStatusBarItem.h" | ||
#import "LSStatusBarClient.h" | ||
|
||
|
||
NSMutableDictionary* sbitems = nil; | ||
|
||
@implementation LSStatusBarItem | ||
|
||
|
||
+ (void) updateItems | ||
{ | ||
NSDictionary* currentMessage = [[LSStatusBarClient sharedInstance] currentMessage]; | ||
|
||
if(!sbitems) | ||
{ | ||
sbitems = [NSMutableDictionary new]; | ||
} | ||
|
||
for(NSString* key in sbitems) | ||
{ | ||
NSDictionary* dict = [currentMessage objectForKey: key]; | ||
|
||
if(dict) | ||
{ | ||
NSArray* idArray = [sbitems objectForKey: key]; | ||
for(LSStatusBarItem* item in idArray) | ||
{ | ||
[item setProperties: dict]; | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
- (id) initWithIdentifier: (NSString*) identifier alignment: (StatusBarAlignment) alignment | ||
{ | ||
if(!identifier) | ||
{ | ||
[NSException raise: NSInternalInconsistencyException format: @"LSStatusBarItem: No identifer specified"]; | ||
} | ||
|
||
if(!alignment) | ||
{ | ||
[NSException raise: NSInternalInconsistencyException format: @"LSStatusBarItem: Alignment not specified"]; | ||
} | ||
|
||
if(!UIApp) | ||
{ | ||
[NSException raise: NSInternalInconsistencyException format: @"LSStatusBarItem: Wait for UIApp to load!"]; | ||
} | ||
|
||
|
||
if((self = [super init])) | ||
{ | ||
// get the current message | ||
NSDictionary* currentMessage; | ||
{ | ||
LSStatusBarClient* client = [LSStatusBarClient sharedInstance]; | ||
|
||
currentMessage = [client currentMessage]; | ||
if(!currentMessage) | ||
[client retrieveCurrentMessage]; | ||
|
||
if(!currentMessage) | ||
{ | ||
[NSException raise: NSInternalInconsistencyException format: @"LSStatusBarItem: Cannot retrieve the current message!"]; | ||
} | ||
|
||
} | ||
|
||
// save all the settings | ||
{ | ||
_identifier = [identifier retain]; | ||
|
||
[self setProperties: [currentMessage objectForKey: _identifier]]; | ||
|
||
NSNumber* align = [_properties objectForKey: @"alignment"]; | ||
if(!align) | ||
{ | ||
[_properties setObject: [NSNumber numberWithInt: alignment] forKey: @"alignment"]; | ||
} | ||
else if([align intValue] != alignment) | ||
{ | ||
[NSException raise: NSInternalInconsistencyException format: @"LSStatusBarItem: You cannot specify a new alignment!"]; | ||
} | ||
} | ||
|
||
// keep track of StatusBarItem(s) | ||
{ | ||
if(!sbitems) | ||
{ | ||
sbitems = [NSMutableDictionary new]; | ||
} | ||
|
||
NSMutableArray* idArray = [sbitems objectForKey: identifier]; | ||
if(!idArray) | ||
{ | ||
// this creates a retain/release-less NSMutableArray | ||
idArray = (NSMutableArray*) CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL); | ||
[sbitems setObject: idArray forKey: identifier]; | ||
CFRelease(idArray); | ||
} | ||
|
||
if(idArray) | ||
{ | ||
[idArray addObject: self]; | ||
} | ||
} | ||
return self; | ||
} | ||
|
||
return nil; | ||
} | ||
|
||
|
||
- (void) dealloc | ||
{ | ||
if(sbitems) | ||
{ | ||
NSMutableArray* idArray = [sbitems objectForKey: _identifier]; | ||
|
||
// kill the current item count | ||
if(idArray) | ||
{ | ||
[idArray removeObject: self]; | ||
|
||
if([idArray count] == 0) | ||
{ | ||
// item is no longer in use by this process, let the server no | ||
[[LSStatusBarClient sharedInstance] setProperties: nil forItem: _identifier]; | ||
} | ||
} | ||
|
||
[_identifier release]; | ||
[_properties release]; | ||
} | ||
|
||
[super dealloc]; | ||
} | ||
|
||
|
||
- (void) setProperties: (NSDictionary*) dict | ||
{ | ||
if(!dict) | ||
{ | ||
_properties = [NSMutableDictionary new]; | ||
} | ||
else | ||
{ | ||
_properties = [dict mutableCopy]; | ||
} | ||
} | ||
|
||
|
||
- (StatusBarAlignment) alignment | ||
{ | ||
NSNumber* alignment = [_properties objectForKey: @"alignment"]; | ||
return alignment ? (StatusBarAlignment) [alignment intValue] : StatusBarAlignmentLeft; | ||
} | ||
|
||
- (void) setVisible: (BOOL) visible | ||
{ | ||
[_properties setObject: [NSNumber numberWithBool: visible] forKey: @"visible"]; | ||
|
||
if(!_manualUpdate) | ||
[self update]; | ||
} | ||
|
||
- (BOOL) isVisible | ||
{ | ||
NSNumber* visible = [_properties objectForKey: @"visible"]; | ||
return visible ? [visible boolValue] : YES; | ||
} | ||
|
||
|
||
- (void) setImageName: (NSString*) imageName | ||
{ | ||
if(self.alignment & StatusBarAlignmentCenter) | ||
{ | ||
[NSException raise: NSInternalInconsistencyException format: @"LSStatusBarItem: Cannot use images with a center alignment"]; | ||
} | ||
[_properties setObject: imageName forKey: @"imageName"]; | ||
|
||
if(!_manualUpdate) | ||
[self update]; | ||
} | ||
|
||
- (NSString*) imageName | ||
{ | ||
return [_properties objectForKey: @"imageName"]; | ||
} | ||
|
||
- (void) setTitleString: (NSString*) string | ||
{ | ||
if(self.alignment & (StatusBarAlignmentLeft | StatusBarAlignmentRight)) | ||
{ | ||
[NSException raise: NSInternalInconsistencyException format: @"LSStatusBarItem: Cannot use a title string with a side alignment"]; | ||
} | ||
|
||
[_properties setObject: string forKey: @"titleString"]; | ||
|
||
if(!_manualUpdate) | ||
[self update]; | ||
} | ||
|
||
- (NSString*) titleString | ||
{ | ||
return [_properties objectForKey: @"titleString"]; | ||
} | ||
|
||
|
||
- (void) setManualUpdate: (BOOL) manualUpdate | ||
{ | ||
_manualUpdate = manualUpdate; | ||
} | ||
|
||
- (BOOL) isManualUpdate | ||
{ | ||
return _manualUpdate; | ||
} | ||
|
||
- (void) update | ||
{ | ||
SelLog(); | ||
[[LSStatusBarClient sharedInstance] setProperties: _properties forItem: _identifier]; | ||
} | ||
|
||
|
||
// future API | ||
|
||
- (void) setExclusiveToApp: (NSString*) bundleId | ||
{ | ||
[_properties setObject: bundleId forKey: @"exclusiveToApp"]; | ||
} | ||
|
||
- (NSString*) exclusiveToApp | ||
{ | ||
return [_properties objectForKey: @"exclusiveToApp"]; | ||
} | ||
|
||
- (void) addTouchDelegate: (id) delegate | ||
{ | ||
} | ||
|
||
- (void) removeTouchDelegate: (id) delegate | ||
{ | ||
} | ||
|
||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,29 @@ | ||
|
||
@interface StatusBarItemServer : NSObject | ||
@interface LSStatusBarServer : NSObject | ||
{ | ||
CPDistributedMessagingCenter *_dmc; | ||
NSMutableDictionary* _currentMessage; | ||
NSMutableArray* _currentKeys; | ||
NSMutableDictionary* _currentKeyUsage; | ||
|
||
CFRunLoopTimerRef timer; | ||
} | ||
|
||
+ (id) sharedInstance; | ||
|
||
- (id) init; | ||
|
||
- (void) appDidExit: (NSString*) bundle; | ||
|
||
- (void) setProperties: (NSString*) message userInfo: (NSDictionary*) userInfo; | ||
- (void) setProperties: (id) properties forItem: (NSString*) item; | ||
- (void) setProperties: (id) properties forItem: (NSString*) item bundle: (NSString*) bundle; | ||
|
||
- (NSMutableDictionary*) currentMessage; | ||
|
||
- (void) incrementTimer; | ||
- (void) updateLockStatus; | ||
|
||
- (void) startTimer; | ||
- (void) stopTimer; | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,356 @@ | ||
|
||
//#define TESTING | ||
|
||
#import "common.h" | ||
#import "defines.h" | ||
|
||
#import "classes.h" | ||
#import "LSStatusBarServer.h" | ||
|
||
#import "LSStatusBarItem.h" | ||
|
||
|
||
void updateLockStatus(CFNotificationCenterRef center, LSStatusBarServer* server) | ||
{ | ||
NSLine(); | ||
[server updateLockStatus]; | ||
} | ||
|
||
void incrementTimer()//CFRunLoopTimerRef timer, LSStatusBarServer* self) | ||
{ | ||
[[LSStatusBarServer sharedInstance] incrementTimer]; | ||
} | ||
|
||
|
||
@implementation LSStatusBarServer | ||
|
||
|
||
+ (id) sharedInstance | ||
{ | ||
static LSStatusBarServer* server; | ||
|
||
if(!server) | ||
{ | ||
server = [[self alloc] init]; | ||
} | ||
return server; | ||
} | ||
|
||
|
||
- (id) init | ||
{ | ||
self = [super init]; | ||
if(self) | ||
{ | ||
_dmc = [CPDistributedMessagingCenter centerNamed: @"com.apple.springboard.libstatusbar"]; | ||
[_dmc runServerOnCurrentThread]; | ||
[_dmc registerForMessageName: @"currentMessage" target: self selector: @selector(currentMessage)]; | ||
[_dmc registerForMessageName: @"setProperties:userInfo:" target: self selector: @selector(setProperties:userInfo:)]; | ||
|
||
_currentMessage = [[NSMutableDictionary alloc] init]; | ||
_currentKeys = [[NSMutableArray alloc] init]; | ||
_currentKeyUsage = [[NSMutableDictionary alloc] init]; | ||
|
||
CFNotificationCenterRef darwin = CFNotificationCenterGetDarwinNotifyCenter(); | ||
CFNotificationCenterAddObserver(darwin, self, (CFNotificationCallback) updateLockStatus, (CFStringRef) @"com.apple.springboard.lockstate", self, NULL); | ||
|
||
} | ||
return self; | ||
} | ||
|
||
|
||
|
||
|
||
- (NSMutableDictionary*) currentMessage | ||
{ | ||
return _currentMessage; | ||
} | ||
|
||
|
||
- (void) processMessageCommon | ||
{ | ||
NSMutableArray* titleStrings = [NSMutableArray array]; | ||
for(NSString* key in _currentKeys) | ||
{ | ||
NSDictionary* dict = [_currentMessage objectForKey: key]; | ||
|
||
if(!dict || ![dict isKindOfClass: [NSDictionary class]]) | ||
continue; | ||
|
||
NSNumber* alignment = [dict objectForKey: @"alignment"]; | ||
if(alignment && ((StatusBarAlignment) [alignment intValue]) == StatusBarAlignmentCenter) | ||
{ | ||
NSLine(); | ||
NSNumber* visible = [dict objectForKey: @"visible"]; | ||
if(!visible || [visible boolValue]) | ||
{ | ||
NSLine(); | ||
if(NSString* titleString = [dict objectForKey: @"titleString"]) | ||
{ | ||
NSLine(); | ||
[titleStrings addObject: titleString]; | ||
} | ||
} | ||
} | ||
} | ||
|
||
[_currentMessage setValue: _currentKeys forKey: @"keys"]; | ||
NSDesc(_currentKeys); | ||
|
||
|
||
|
||
if([titleStrings count]) | ||
{ | ||
[_currentMessage setValue: titleStrings forKey: @"titleStrings"]; | ||
|
||
[self startTimer]; | ||
} | ||
else | ||
{ | ||
[_currentMessage setValue: nil forKey: @"titleStrings"]; | ||
|
||
//if(!timer) | ||
// notify_post("libstatusbar_changed"); | ||
[self stopTimer]; | ||
} | ||
NSDesc(_currentMessage); | ||
|
||
notify_post("libstatusbar_changed"); | ||
} | ||
|
||
- (void) setProperties: (id) properties forItem: (NSString*) item bundle: (NSString*) bundle | ||
{ | ||
SelLog(); | ||
if(!item || !bundle) | ||
{ | ||
NSLog(@"missing info. returning..."); | ||
return; | ||
} | ||
|
||
// get the current item usage by bundles | ||
NSMutableArray* bundles = [_currentKeyUsage objectForKey: item]; | ||
if(!bundles) | ||
{ | ||
bundles = [NSMutableArray array]; | ||
[_currentKeyUsage setObject: bundles forKey: item]; | ||
} | ||
|
||
int itemIdx = [_currentKeys indexOfObject: item]; | ||
|
||
if(properties) | ||
{ | ||
[_currentMessage setValue: properties forKey: item]; | ||
|
||
if(![bundles containsObject: bundle]) | ||
{ | ||
[bundles addObject: bundle]; | ||
} | ||
|
||
if(itemIdx == NSNotFound) | ||
{ | ||
[_currentKeys addObject: item]; | ||
} | ||
} | ||
else | ||
{ | ||
[bundles removeObject: bundle]; | ||
NSLog(@"removing object"); | ||
|
||
if([bundles count]==0) | ||
{ | ||
// object is truly dead | ||
[_currentMessage setValue: nil forKey: item]; | ||
|
||
if(itemIdx!=NSNotFound) | ||
[_currentKeys removeObjectAtIndex: itemIdx]; | ||
} | ||
} | ||
|
||
/* | ||
int itemIdx = [_currentKeys indexOfObject: item]; | ||
if(!properties && itemIdx != NSNotFound) | ||
{ | ||
[_currentKeys removeObjectAtIndex: itemIdx]; | ||
} | ||
else if(properties && itemIdx == NSNotFound) | ||
{ | ||
[_currentKeys addObject: item]; | ||
} | ||
*/ | ||
|
||
|
||
// find all title strings | ||
|
||
[self processMessageCommon]; | ||
} | ||
|
||
|
||
- (void) appDidExit: (NSString*) bundle | ||
{ | ||
|
||
|
||
int nKeys = [_currentKeys count]; | ||
for(int i=nKeys - 1; i>=0; i--) | ||
{ | ||
NSString* item = [_currentKeys objectAtIndex: i]; | ||
|
||
NSMutableArray* bundles = [_currentKeyUsage objectForKey: item]; | ||
if(!bundles) | ||
{ | ||
continue; | ||
} | ||
|
||
if([bundles containsObject: bundle]) | ||
{ | ||
[bundles removeObject: bundle]; | ||
NSLog(@"removing object"); | ||
|
||
if([bundles count]==0) | ||
{ | ||
// object is truly dead | ||
[_currentMessage setValue: nil forKey: item]; | ||
|
||
int itemIdx = [_currentKeys indexOfObject: item]; | ||
if(itemIdx!=NSNotFound) | ||
[_currentKeys removeObjectAtIndex: itemIdx]; | ||
} | ||
} | ||
} | ||
|
||
[self processMessageCommon]; | ||
} | ||
|
||
|
||
|
||
|
||
- (void) setProperties: (NSString*) message userInfo: (NSDictionary*) userInfo | ||
{ | ||
NSString* item = [userInfo objectForKey: @"item"]; | ||
NSDictionary* properties = [userInfo objectForKey: @"properties"]; | ||
NSString* bundleId = [userInfo objectForKey: @"bundle"]; | ||
|
||
[self setProperties: properties forItem: item bundle: bundleId]; | ||
} | ||
|
||
- (void) startTimer | ||
{ | ||
NSLine(); | ||
|
||
// is timer already running? | ||
if(timer) | ||
{ | ||
NSLog(@"timer is already active. Leaving it alone"); | ||
return; | ||
} | ||
|
||
// check lock status | ||
uint64_t locked; | ||
{ | ||
int token = 0; | ||
notify_register_check("com.apple.springboard.lockstate", &token); | ||
notify_get_state(token, &locked); | ||
} | ||
|
||
NSLine(); | ||
|
||
// reset timer state | ||
[self stopTimer]; | ||
NSLine(); | ||
|
||
if(!locked) | ||
{ | ||
NSLine(); | ||
|
||
NSArray* titleStrings = [_currentMessage objectForKey: @"titleStrings"]; | ||
if(titleStrings && [titleStrings count]) | ||
{ | ||
NSLine(); | ||
|
||
timer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent()+3.5f, 3.5f, 0, 0, (CFRunLoopTimerCallBack) incrementTimer, NULL); | ||
CFRunLoopAddTimer(CFRunLoopGetMain(), timer, kCFRunLoopCommonModes); | ||
} | ||
} | ||
NSLine(); | ||
|
||
} | ||
|
||
- (void) stopTimer | ||
{ | ||
NSLine(); | ||
|
||
// reset the statusbar state | ||
{ | ||
const char* notif = "libstatusbar_changed"; | ||
|
||
uint64_t value = NSNotFound; | ||
int token = 0; | ||
notify_register_check(notif, &token); | ||
|
||
notify_set_state(token, value); | ||
|
||
if(timer) // only post a notification if the timer was running | ||
notify_post(notif); | ||
} | ||
|
||
// kill timer | ||
if(timer) | ||
{ | ||
CFRunLoopTimerInvalidate(timer); | ||
CFRelease(timer); | ||
timer = nil; | ||
} | ||
NSLine(); | ||
} | ||
|
||
|
||
- (void) incrementTimer | ||
{ | ||
NSLine(); | ||
|
||
NSArray* titleStrings = [_currentMessage objectForKey: @"titleStrings"]; | ||
|
||
const char* notif = "libstatusbar_changed"; | ||
|
||
if(titleStrings && [titleStrings count]) | ||
{ | ||
uint64_t value; | ||
int token = 0; | ||
notify_register_check(notif, &token); | ||
notify_get_state(token, &value); | ||
|
||
value++; | ||
if(value > [titleStrings count]) | ||
{ | ||
value = 0; | ||
} | ||
|
||
NSLog(@"idx = %ld", value); | ||
|
||
notify_set_state(token, value); | ||
notify_post(notif); | ||
} | ||
else | ||
{ | ||
[self stopTimer]; | ||
/* | ||
NSLog(@"idx = %ld", value); | ||
CFRunLoopTimerInvalidate(timer); | ||
CFRelease(timer); | ||
timer = nil; | ||
notify_post(notif); | ||
*/ | ||
} | ||
} | ||
|
||
|
||
- (void) updateLockStatus | ||
{ | ||
[self stopTimer]; | ||
[self startTimer]; | ||
} | ||
|
||
|
||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
Libstatusbar: pwning the statusbar for you. | ||
|
||
Libstatusbar is chiefly a compatibility library for 3.x-like statusbar icon support under 4.x, but allows for a more advanced API for custom time strings and icon swapping. | ||
|
||
|
||
All icons should be placed in either: | ||
|
||
3.x style, does not support retina icons: | ||
Silver: /System/Library/CoreServices/SpringBoard/Default_<name>.png | ||
Black: /System/Library/CoreServices/SpringBoard/FSO_<name>.png | ||
|
||
4.x style, supports retina (@2x) icons: | ||
Silver: /System/Library/Frameworks/UIKit.framework/Silver_<name>.png | ||
Black: /System/Library/Frameworks/UIKit.framework/Black_<name>.png | ||
|
||
--- BASIC API --- | ||
|
||
3.x-style, simply add/remove items. These will appear in the right list. | ||
|
||
[UIApp addStatusBarImageNamed: (NSString*) name]; | ||
[UIApp removeStatusBarImageNamed: (NSString*) name]; | ||
|
||
--- ADVANCED API --- | ||
|
||
See LSStatusBarItem.h for the API and Testing.mm for example usage |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
|
||
#import "common.h" | ||
#import "defines.h" | ||
|
||
#import "classes.h" | ||
|
||
#import "LSStatusBarItem.h" | ||
|
||
|
||
LSStatusBarItem* playItem; | ||
|
||
void addPlay() | ||
{ | ||
playItem = [[LSStatusBarItem alloc] initWithIdentifier: @"libstatusbar.Play" alignment: StatusBarAlignmentLeft]; | ||
playItem.imageName = @"Play"; | ||
// [UIApp addStatusBarImageNamed: @"Bluetooth"]; | ||
} | ||
|
||
void playToBT() | ||
{ | ||
playItem.imageName = @"Bluetooth"; | ||
} | ||
|
||
LSStatusBarItem* centerItem; | ||
|
||
LSStatusBarItem* centerItem2; | ||
|
||
|
||
void addCenterText() | ||
{ | ||
centerItem = [[LSStatusBarItem alloc] initWithIdentifier: @"libstatusbar.Center" alignment: StatusBarAlignmentCenter]; | ||
centerItem.titleString = @"Test string"; | ||
|
||
centerItem2 = [[LSStatusBarItem alloc] initWithIdentifier: @"libstatusbar.Center2" alignment: StatusBarAlignmentCenter]; | ||
centerItem2.titleString = @"is a reallly long test string"; | ||
} | ||
|
||
void modifyCenterText() | ||
{ | ||
[playItem release]; | ||
|
||
centerItem2.titleString = @"is an even longer test string to fill the screen"; | ||
} | ||
|
||
|
||
void DelayedTesting() | ||
{ | ||
{ | ||
{ | ||
float delay = 4.0f; | ||
CFRunLoopTimerCallBack callback = (CFRunLoopTimerCallBack) addPlay; | ||
|
||
CFRunLoopTimerRef waitTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent()+delay, 0.0f, 0, 0, callback, NULL); | ||
CFRunLoopAddTimer(CFRunLoopGetMain(), waitTimer, kCFRunLoopCommonModes); | ||
} | ||
{ | ||
float delay = 16.0f; | ||
CFRunLoopTimerCallBack callback = (CFRunLoopTimerCallBack) playToBT; | ||
|
||
CFRunLoopTimerRef waitTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent()+delay, 0.0f, 0, 0, callback, NULL); | ||
CFRunLoopAddTimer(CFRunLoopGetMain(), waitTimer, kCFRunLoopCommonModes); | ||
} | ||
{ | ||
float delay = 2.0f; | ||
CFRunLoopTimerCallBack callback = (CFRunLoopTimerCallBack) addCenterText; | ||
|
||
CFRunLoopTimerRef waitTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent()+delay, 0.0f, 0, 0, callback, NULL); | ||
CFRunLoopAddTimer(CFRunLoopGetMain(), waitTimer, kCFRunLoopCommonModes); | ||
} | ||
|
||
{ | ||
float delay = 30.0f; | ||
CFRunLoopTimerCallBack callback = (CFRunLoopTimerCallBack) modifyCenterText; | ||
|
||
CFRunLoopTimerRef waitTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent()+delay, 0.0f, 0, 0, callback, NULL); | ||
CFRunLoopAddTimer(CFRunLoopGetMain(), waitTimer, kCFRunLoopCommonModes); | ||
} | ||
} | ||
} | ||
|
||
__attribute__((constructor)) void TestingStart() | ||
{ | ||
GETCLASS(MobileSafariWindow); | ||
if($MobileSafariWindow) | ||
{ | ||
DelayedTesting(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.