FLEXWindow.m 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. //
  2. // FLEXWindow.m
  3. // Flipboard
  4. //
  5. // Created by Ryan Olson on 4/13/14.
  6. // Copyright (c) 2014 Flipboard. All rights reserved.
  7. //
  8. #import "FLEXWindow.h"
  9. #import "FLEXUtility.h"
  10. #import <objc/runtime.h>
  11. @implementation FLEXWindow
  12. - (id)initWithFrame:(CGRect)frame
  13. {
  14. self = [super initWithFrame:frame];
  15. if (self) {
  16. // Some apps have windows at UIWindowLevelStatusBar + n.
  17. // If we make the window level too high, we block out UIAlertViews.
  18. // There's a balance between staying above the app's windows and staying below alerts.
  19. // UIWindowLevelStatusBar + 100 seems to hit that balance.
  20. self.windowLevel = UIWindowLevelStatusBar + 100.0;
  21. }
  22. return self;
  23. }
  24. - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
  25. {
  26. BOOL pointInside = NO;
  27. if ([self.eventDelegate shouldHandleTouchAtPoint:point]) {
  28. pointInside = [super pointInside:point withEvent:event];
  29. }
  30. return pointInside;
  31. }
  32. - (BOOL)shouldAffectStatusBarAppearance
  33. {
  34. return [self isKeyWindow];
  35. }
  36. - (BOOL)canBecomeKeyWindow
  37. {
  38. return [self.eventDelegate canBecomeKeyWindow];
  39. }
  40. - (void)makeKeyWindow {
  41. _previousKeyWindow = FLEXUtility.appKeyWindow;
  42. [super makeKeyWindow];
  43. }
  44. - (void)resignKeyWindow {
  45. [super resignKeyWindow];
  46. _previousKeyWindow = nil;
  47. }
  48. + (void)initialize
  49. {
  50. // This adds a method (superclass override) at runtime which gives us the status bar behavior we want.
  51. // The FLEX window is intended to be an overlay that generally doesn't affect the app underneath.
  52. // Most of the time, we want the app's main window(s) to be in control of status bar behavior.
  53. // Done at runtime with an obfuscated selector because it is private API. But you shouldn't ship this to the App Store anyways...
  54. NSString *canAffectSelectorString = [@[@"_can", @"Affect", @"Status", @"Bar", @"Appearance"] componentsJoinedByString:@""];
  55. SEL canAffectSelector = NSSelectorFromString(canAffectSelectorString);
  56. Method shouldAffectMethod = class_getInstanceMethod(self, @selector(shouldAffectStatusBarAppearance));
  57. IMP canAffectImplementation = method_getImplementation(shouldAffectMethod);
  58. class_addMethod(self, canAffectSelector, canAffectImplementation, method_getTypeEncoding(shouldAffectMethod));
  59. // One more...
  60. NSString *canBecomeKeySelectorString = [NSString stringWithFormat:@"_%@", NSStringFromSelector(@selector(canBecomeKeyWindow))];
  61. SEL canBecomeKeySelector = NSSelectorFromString(canBecomeKeySelectorString);
  62. Method canBecomeKeyMethod = class_getInstanceMethod(self, @selector(canBecomeKeyWindow));
  63. IMP canBecomeKeyImplementation = method_getImplementation(canBecomeKeyMethod);
  64. class_addMethod(self, canBecomeKeySelector, canBecomeKeyImplementation, method_getTypeEncoding(canBecomeKeyMethod));
  65. }
  66. @end