]> git.saurik.com Git - cydget.git/blame - CydgetLoader.mm
Update the iphone-api types for handleGesture:.
[cydget.git] / CydgetLoader.mm
CommitLineData
36228fbc 1/* Cydget - open-source AwayView plugin multiplexer
5bc15b17 2 * Copyright (C) 2009-2014 Jay Freeman (saurik)
e6cd4dee
JF
3*/
4
5bc15b17 5/* GNU General Public License, Version 3 {{{ */
e6cd4dee 6/*
5bc15b17
JF
7 * Cydia is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation, either version 3 of the License,
10 * or (at your option) any later version.
e6cd4dee 11 *
5bc15b17
JF
12 * Cydia is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
e6cd4dee 16 *
5bc15b17
JF
17 * You should have received a copy of the GNU General Public License
18 * along with Cydia. If not, see <http://www.gnu.org/licenses/>.
19**/
20/* }}} */
e6cd4dee 21
5bc15b17 22#include <CydiaSubstrate/CydiaSubstrate.h>
e6cd4dee
JF
23
24#include <Foundation/Foundation.h>
545370d8 25#include <UIKit/UIKit.h>
e6cd4dee
JF
26
27#import <SpringBoard/SBAwayController.h>
d86d4327 28#import <SpringBoard/SBAwayView.h>
e6cd4dee 29#import <SpringBoard/SBAwayWindow.h>
3a0081b3 30#import <SpringBoard/SpringBoard.h>
e6cd4dee 31
0c1e3ef0
JF
32#include "Handle.hpp"
33
5bc15b17
JF
34#define _trace() \
35 NSLog(@"_trace(%s:%u)@%s %zd", __FILE__, __LINE__, __FUNCTION__, active_)
36#define _not(type) \
37 static_cast<type>(~type())
38
39typedef void *GSEventRef;
40
41extern "C" void UIKeyboardEnableAutomaticAppearance();
42extern "C" void UIKeyboardDisableAutomaticAppearance();
43
e6cd4dee 44MSClassHook(SpringBoard)
fde9eca1 45
e6cd4dee
JF
46MSClassHook(SBAwayController)
47MSClassHook(SBAwayView)
3aa346e5 48MSClassHook(SBAwayWindow)
5bc15b17
JF
49MSClassHook(SBLockScreenManager)
50MSClassHook(SBLockScreenView)
51MSClassHook(SBLockScreenViewController)
52MSClassHook(SBScreenFadeAnimationController)
53MSClassHook(SBUserAgent)
54
55MSInitialize {
56 if (kCFCoreFoundationVersionNumber < 800) {
57 $SBUserAgent = $SBAwayController;
58 $SBLockScreenManager = $SBAwayController;
59 $SBLockScreenView = $SBAwayView;
60 }
61}
e6cd4dee
JF
62
63static bool menu_;
e6cd4dee 64
5bc15b17
JF
65static _H<NSDictionary> settings_;
66static _H<NSMutableArray> cydgets_;
3a0081b3 67static size_t active_;
3aa346e5 68static unsigned online_;
e6cd4dee 69
d8165c74
JF
70@interface CydgetController : NSObject {
71}
72
73+ (NSDictionary *) currentConfiguration;
74
75@end
76
77@implementation CydgetController
78
79+ (NSDictionary *) currentConfiguration {
d86d4327
JF
80 NSDictionary *cydget([cydgets_ objectAtIndex:active_]);
81 return [cydget objectForKey:@"CYConfiguration"] ?: [cydget objectForKey:@"Configuration"];
d8165c74
JF
82}
83
84@end
85
5bc15b17
JF
86@interface SBUserAgent : NSObject
87+ (SBUserAgent *) sharedUserAgent;
88- (void) enableLockScreenBundleNamed:(NSString *)bundle activationContext:(id)context;
89- (void) disableLockScreenBundleNamed:(NSString *)bundle deactivationContext:(id)context;
e6cd4dee
JF
90@end
91
57df9ddb
JF
92@interface UIPeripheralHost : NSObject
93+ (UIPeripheralHost *) sharedInstance;
94+ (void) _releaseSharedInstance;
57df9ddb
JF
95@end
96
97MSClassHook(UIPeripheralHost)
98
99@interface UITextEffectsWindow : UIWindow
100+ (UIWindow *) sharedTextEffectsWindow;
101@end
102
5bc15b17
JF
103@implementation NSDictionary (CydgetLoader)
104
105- (NSString *) cydget {
106 return [self objectForKey:@"CYPlugin"] ?: [self objectForKey:@"Plugin"];
107}
e6cd4dee 108
5bc15b17
JF
109- (void) enableCydget {
110 if (NSString *plugin = [self cydget]) {
fde9eca1 111 ++online_;
fde9eca1 112
1dad64a0
JF
113 if (kCFCoreFoundationVersionNumber < 600)
114 UIKeyboardEnableAutomaticAppearance();
57df9ddb 115
1dad64a0 116 [[UITextEffectsWindow sharedTextEffectsWindow] setWindowLevel:1000];
5bc15b17
JF
117
118 if (kCFCoreFoundationVersionNumber < 800)
119 [[$SBAwayController sharedAwayController] enableLockScreenBundleWithName:plugin];
120 else
121 [[$SBUserAgent sharedUserAgent] enableLockScreenBundleNamed:plugin activationContext:nil];
3aa346e5 122 }
e6cd4dee
JF
123}
124
5bc15b17
JF
125- (void) disableCydget {
126 if (NSString *plugin = [self cydget]) {
127 if (kCFCoreFoundationVersionNumber < 800)
128 [[$SBAwayController sharedAwayController] disableLockScreenBundleWithName:plugin];
129 else
130 [[$SBUserAgent sharedUserAgent] disableLockScreenBundleNamed:plugin deactivationContext:nil];
131
57df9ddb 132 [$UIPeripheralHost _releaseSharedInstance];
fde9eca1 133
1dad64a0
JF
134 if (kCFCoreFoundationVersionNumber < 600)
135 UIKeyboardDisableAutomaticAppearance();
136
fde9eca1 137 --online_;
3aa346e5 138 }
e6cd4dee
JF
139}
140
141@end
142
fde9eca1
JF
143// avoid rendering a keyboard onto the default SBAwayView while automatic keyboard is online
144MSInstanceMessageHook0(UIView *, SBAwayView, inputView) {
d373498d 145 // XXX: there is a conceptual error here
1dad64a0 146 if (online_ == 0 && false || kCFCoreFoundationVersionNumber > 600)
fde9eca1
JF
147 return MSOldCall();
148
149 return [[[UIView alloc] init] autorelease];
150}
151
152// by default, keyboard actions are redirected to SBAwayController and press menu button
57df9ddb 153MSInstanceMessageHook1(void, SpringBoard, handleKeyEvent, GSEventRef, event) {
1dad64a0 154 if (online_ == 0 || kCFCoreFoundationVersionNumber > 600)
fde9eca1
JF
155 return MSOldCall(event);
156
157 return MSSuperCall(event);
57df9ddb
JF
158}
159
5bc15b17 160MSInstanceMessageHook0(BOOL, SBLockScreenManager, handleMenuButtonTap) {
1b616711 161 if (!MSOldCall() && menu_) {
5bc15b17 162 [[cydgets_ objectAtIndex:active_] disableCydget];
3a0081b3 163 active_ = (active_ + 1) % [cydgets_ count];
5bc15b17 164 [[cydgets_ objectAtIndex:active_] enableCydget];
1b616711 165 }
e6cd4dee
JF
166
167 return YES;
168}
169
5bc15b17
JF
170void Activate_() {
171 menu_ = false;
172 [[cydgets_ objectAtIndex:active_] enableCydget];
173}
174
1a274bdf 175static void Undim_(SBAwayController *self) {
f83bba74 176 if ([self isDimmed]) {
5bc15b17 177 Activate_();
f83bba74
JF
178 [[[self awayView] window] makeKeyWindow];
179 }
1a274bdf 180}
f83bba74 181
5bc15b17
JF
182MSInstanceMessageHook1(void, SBLockScreenViewController, startLockScreenFadeInAnimationForSource, int, source) {
183 Activate_();
184 MSOldCall(source);
185}
186
1a274bdf
JF
187MSInstanceMessageHook0(void, SBAwayController, undimScreen) {
188 Undim_(self);
f83bba74 189 MSOldCall();
e6cd4dee
JF
190}
191
1a274bdf
JF
192MSInstanceMessageHook1(void, SBAwayController, undimScreen, BOOL, undim) {
193 Undim_(self);
194 MSOldCall(undim);
195}
196
5bc15b17
JF
197static void Deactivate_() {
198 [[cydgets_ objectAtIndex:active_] disableCydget];
3a0081b3 199 active_ = 0;
e6cd4dee
JF
200}
201
5bc15b17
JF
202MSHook(void, BKSDisplayServicesSetScreenBlanked, BOOL blanked) {
203 if (blanked)
204 Deactivate_();
205 _BKSDisplayServicesSetScreenBlanked(blanked);
206}
207
208MSInitialize {
209 MSHookFunction("_BKSDisplayServicesSetScreenBlanked", MSHake(BKSDisplayServicesSetScreenBlanked));
210}
211
212MSInstanceMessageHook1(void, SBUserAgent, dimScreen, BOOL, dim) {
213 Deactivate_();
1b616711 214 MSOldCall(dim);
e6cd4dee
JF
215}
216
5bc15b17
JF
217MSInstanceMessageHook1(void, SpringBoard, _menuButtonDown, GSEventRef, event) {
218 menu_ = true;
219 MSOldCall(event);
220}
221
f83bba74 222MSInstanceMessageHook1(void, SpringBoard, menuButtonDown, GSEventRef, event) {
e6cd4dee 223 menu_ = true;
3a0081b3 224 MSOldCall(event);
e6cd4dee
JF
225}
226
3a0081b3 227MSInstanceMessageHook1(void, SBAwayView, addGestureRecognizer, id, recognizer) {
1dad64a0 228 if (online_ == 0 || kCFCoreFoundationVersionNumber > 600)
fde9eca1 229 return MSOldCall(recognizer);
545370d8
JF
230}
231
3aa346e5 232MSInstanceMessageHook1(void, SBAwayWindow, sendGSEvent, GSEventRef, event) {
1dad64a0 233 if (online_ == 0 || kCFCoreFoundationVersionNumber > 600)
fde9eca1
JF
234 return MSOldCall(event);
235
236 return MSSuperCall(event);
3aa346e5
JF
237}
238
3a0081b3 239#define Cydgets_ @"/System/Library/LockCydgets"
545370d8 240
3a0081b3
JF
241static void CydgetSetup() {
242 NSString *plist([NSString stringWithFormat:@"%@/Library/Preferences/com.saurik.Cydget.plist", NSHomeDirectory()]);
243 settings_ = [NSMutableDictionary dictionaryWithContentsOfFile:plist] ?: [NSMutableDictionary dictionary];
545370d8 244
3a0081b3 245 NSArray *cydgets([settings_ objectForKey:@"LockCydgets"] ?: [NSArray arrayWithObjects:[NSDictionary dictionaryWithObjectsAndKeys:
3aa346e5 246 @"Welcome", @"Name", [NSNumber numberWithBool:YES], @"Active", nil
3a0081b3 247 ], [NSDictionary dictionaryWithObjectsAndKeys:
3aa346e5 248 @"AwayView", @"Name", [NSNumber numberWithBool:YES], @"Active", nil
3a0081b3 249 ], nil]);
545370d8 250
3a0081b3
JF
251 cydgets_ = [NSMutableArray arrayWithCapacity:4];
252 for (NSDictionary *cydget in cydgets)
253 if ([[cydget objectForKey:@"Active"] boolValue])
254 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/%@.cydget/Info.plist", Cydgets_, [cydget objectForKey:@"Name"]]])
255 [cydgets_ addObject:info];
81c3ce7d
JF
256
257 if ([cydgets_ count] == 0)
258 cydgets_ = nil;
545370d8
JF
259}
260
3a0081b3 261// XXX: this could happen while it is unlocked
5bc15b17 262MSInstanceMessageHook1(id, SBLockScreenView, initWithFrame, CGRect, frame) {
3a0081b3
JF
263 self = MSOldCall(frame);
264 CydgetSetup();
5bc15b17 265 [[cydgets_ objectAtIndex:active_] enableCydget];
3a0081b3 266 return self;
545370d8
JF
267}
268
3a0081b3
JF
269MSInstanceMessageHook1(void, SBAwayController, _finishedUnlockAttemptWithStatus, BOOL, status) {
270 if (status)
5bc15b17 271 Deactivate_();
3a0081b3 272 MSOldCall(status);
e6cd4dee 273}
d86d4327 274
672fa884
JF
275// this is called occasionally by -[SBAwayView updateInterface] and takes away our keyboard
276MSInstanceMessageHook0(void, SBAwayView, _fixupFirstResponder) {
277 if (online_ == 0)
278 return MSOldCall();
279}
280
d86d4327
JF
281MSInstanceMessageHook0(void, SBAwayView, updateInterface) {
282 MSOldCall();
283
284 NSDictionary *cydget([cydgets_ objectAtIndex:active_]);
285
286 NSString *background([cydget objectForKey:@"CYBackground"]);
287 if ([background isEqualToString:@"Wallpaper"]) {
288 MSIvarHook(UIView *, _backgroundView);
289 [_backgroundView setAlpha:1.0f];
290 }
291
292 if ([[cydget objectForKey:@"CYShowDateTime"] boolValue])
293 [self addDateView];
294}