summaryrefslogtreecommitdiff
path: root/SmartDeviceLink/SDLLockScreenPresenter.m
blob: 3162f8cc9f2cd06a039971134cfa702ffac32460 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//
//  SDLLockScreenPresenter.m
//  SmartDeviceLink-iOS
//
//  Created by Joel Fischer on 7/15/16.
//  Copyright © 2016 smartdevicelink. All rights reserved.
//

#import "SDLLockScreenPresenter.h"

#import "SDLLogMacros.h"
#import "SDLScreenshotViewController.h"
#import "SDLStreamingMediaManagerConstants.h"


NS_ASSUME_NONNULL_BEGIN

@interface SDLLockScreenPresenter ()

@property (strong, nonatomic) SDLScreenshotViewController *screenshotViewController;
@property (strong, nonatomic) UIWindow *lockWindow;

@end


@implementation SDLLockScreenPresenter

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

    CGRect screenFrame = [[UIScreen mainScreen] bounds];
    _lockWindow = [[UIWindow alloc] initWithFrame:screenFrame];
    _screenshotViewController = [[SDLScreenshotViewController alloc] init];
    _lockWindow.rootViewController = _screenshotViewController;

    return self;
}

- (void)present {
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.lockWindow.isKeyWindow) {
            SDLLogW(@"Attempted to present lock window when it is already presented");
            return;
        }

        NSArray* windows = [[UIApplication sharedApplication] windows];
        UIWindow *appWindow = nil;
        for (UIWindow *window in windows) {
            if (window != self.lockWindow) {
                appWindow = window;
                break;
            }
        }

        if (appWindow == nil) {
            SDLLogE(@"Unable to find the app's window");
            return;
        }

        // We let ourselves know that the lockscreen will present, because we have to pause streaming video for that 0.3 seconds or else it will be very janky.
        [[NSNotificationCenter defaultCenter] postNotificationName:SDLLockScreenManagerWillPresentLockScreenViewController object:nil];

        CGRect firstFrame = appWindow.frame;
        firstFrame.origin.x = CGRectGetWidth(firstFrame);
        appWindow.frame = firstFrame;

        // We then move the lockWindow to the original appWindow location.
        self.lockWindow.frame = appWindow.bounds;
        [self.screenshotViewController loadScreenshotOfWindow:appWindow];
        [self.lockWindow makeKeyAndVisible];

        // And present the lock screen.
        SDLLogD(@"Present lock screen window");
        [self.lockWindow.rootViewController presentViewController:self.lockViewController animated:YES completion:^{
            // Tell ourselves we are done.
            [[NSNotificationCenter defaultCenter] postNotificationName:SDLLockScreenManagerDidPresentLockScreenViewController object:nil];
        }];
    });
}

- (void)dismiss {
    dispatch_async(dispatch_get_main_queue(), ^{
        NSArray* windows = [[UIApplication sharedApplication] windows];
        UIWindow *appWindow = nil;
        for (UIWindow *window in windows) {
            if (window != self.lockWindow) {
                appWindow = window;
                break;
            }
        }

        if (appWindow == nil) {
            SDLLogE(@"Unable to find the app's window");
            return;
        } else if (appWindow.isKeyWindow) {
            SDLLogW(@"Attempted to dismiss lock screen, but it is already dismissed");
            return;
        } else if (self.lockViewController == nil) {
            SDLLogW(@"Attempted to dismiss lock screen, but lockViewController is not set");
            return;
        }

        // Let us know we are about to dismiss.
        [[NSNotificationCenter defaultCenter] postNotificationName:SDLLockScreenManagerWillDismissLockScreenViewController object:nil];

        // Dismiss the lockscreen
        SDLLogD(@"Dismiss lock screen window");
        [self.lockViewController dismissViewControllerAnimated:YES completion:^{
            CGRect lockFrame = self.lockWindow.frame;
            lockFrame.origin.x = CGRectGetWidth(lockFrame);
            self.lockWindow.frame = lockFrame;

            // Quickly move the map back, and make it the key window.
            appWindow.frame = self.lockWindow.bounds;
            [appWindow makeKeyAndVisible];

            // Tell ourselves we are done.
            [[NSNotificationCenter defaultCenter] postNotificationName:SDLLockScreenManagerDidDismissLockScreenViewController object:nil];
        }];
    });
}

- (BOOL)presented {
    __block BOOL isPresented = NO;
    if ([NSThread isMainThread]) {
        isPresented = [self sdl_presented];
    } else {
        dispatch_sync(dispatch_get_main_queue(), ^{
            isPresented = [self sdl_presented];
        });
    }

    return isPresented;
}

- (BOOL)sdl_presented {
    return (self.lockViewController.isViewLoaded && (self.lockViewController.view.window || self.lockViewController.isBeingPresented) && self.lockWindow.isKeyWindow);
}

@end

NS_ASSUME_NONNULL_END