Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/trace remote keyboard window #116

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions Src/Main/Server/Category/UITextField+LookinServer.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,25 @@
// https://lookin.work
//

#import <objc/runtime.h>
#import "UITextField+LookinServer.h"
#import "LKS_WindowDiscovery.h"

@implementation UITextField (LookinServer)

+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method oriMethod = class_getInstanceMethod([self class], @selector(setInputView:));
Method newMethod = class_getInstanceMethod([self class], @selector(lks_setInputView:));
method_exchangeImplementations(oriMethod, newMethod);

oriMethod = class_getInstanceMethod([self class], @selector(setInputAccessoryView:));
newMethod = class_getInstanceMethod([self class], @selector(lks_setInputAccessoryView:));
method_exchangeImplementations(oriMethod, newMethod);
});
}

- (CGFloat)lks_fontSize {
return self.font.pointSize;
}
Expand All @@ -24,6 +39,16 @@ - (NSString *)lks_fontName {
return self.font.fontName;
}

- (void)lks_setInputView:(UIView *)inputView {
[self lks_setInputView:inputView];
[[LKS_WindowDiscovery sharedInstance] addCustomWindowWithView:inputView];
}

- (void)lks_setInputAccessoryView:(UIView *)inputAccessoryView {
[self lks_setInputAccessoryView:inputAccessoryView];
[[LKS_WindowDiscovery sharedInstance] addCustomWindowWithView:inputAccessoryView];
}

@end

#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
25 changes: 25 additions & 0 deletions Src/Main/Server/Category/UITextView+LookinServer.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,25 @@
// https://lookin.work
//

#import <objc/runtime.h>
#import "UITextView+LookinServer.h"
#import "LKS_WindowDiscovery.h"

@implementation UITextView (LookinServer)

+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method oriMethod = class_getInstanceMethod([self class], @selector(setInputView:));
Method newMethod = class_getInstanceMethod([self class], @selector(lks_setInputView:));
method_exchangeImplementations(oriMethod, newMethod);

oriMethod = class_getInstanceMethod([self class], @selector(setInputAccessoryView:));
newMethod = class_getInstanceMethod([self class], @selector(lks_setInputAccessoryView:));
method_exchangeImplementations(oriMethod, newMethod);
});
}

- (CGFloat)lks_fontSize {
return self.font.pointSize;
}
Expand All @@ -24,6 +39,16 @@ - (NSString *)lks_fontName {
return self.font.fontName;
}

- (void)lks_setInputView:(UIView *)inputView {
[self lks_setInputView:inputView];
[[LKS_WindowDiscovery sharedInstance] addCustomWindowWithView:inputView];
}

- (void)lks_setInputAccessoryView:(UIView *)inputAccessoryView {
[self lks_setInputAccessoryView:inputAccessoryView];
[[LKS_WindowDiscovery sharedInstance] addCustomWindowWithView:inputAccessoryView];
}

@end

#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
5 changes: 3 additions & 2 deletions Src/Main/Server/Category/UIView+LookinServer.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#import "LookinObject.h"
#import "LookinAutoLayoutConstraint.h"
#import "LookinServerDefines.h"
#import "LKS_WindowDiscovery.h"

@implementation UIView (LookinServer)

Expand Down Expand Up @@ -125,10 +126,10 @@ - (float)lks_horizontalContentCompressionResistancePriority {
}

+ (void)lks_rebuildGlobalInvolvedRawConstraints {
[[[UIApplication sharedApplication].windows copy] enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) {
[[[LKS_WindowDiscovery sharedInstance].windows copy] enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) {
[self lks_removeInvolvedRawConstraintsForViewsRootedByView:window];
}];
[[[UIApplication sharedApplication].windows copy] enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) {
[[[LKS_WindowDiscovery sharedInstance].windows copy] enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) {
[self lks_addInvolvedRawConstraintsForViewsRootedByView:window];
}];
}
Expand Down
3 changes: 2 additions & 1 deletion Src/Main/Server/Inspect/LKS_LocalInspectViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#import "UIImage+LookinServer.h"
#import "LookinServerDefines.h"
#import "UIColor+LookinServer.h"
#import "LKS_WindowDiscovery.h"
#import "LKSConfigManager.h"

static CGRect const kInvalidRect = (CGRect){-2, -2, 0, 0};
Expand Down Expand Up @@ -558,7 +559,7 @@ - (void)_handleEnterForegound {
- (UIView *)_targetViewAtPoint:(CGPoint)point {
__block UIView *targetView = nil;

[[UIApplication sharedApplication].windows enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) {
[[LKS_WindowDiscovery sharedInstance].windows enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) {
if (targetView) {
*stop = YES;
return;
Expand Down
3 changes: 2 additions & 1 deletion Src/Main/Server/Others/LKS_HierarchyDisplayItemsMaker.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@
#import "LKS_EventHandlerMaker.h"
#import "LookinServerDefines.h"
#import "UIColor+LookinServer.h"
#import "LKS_WindowDiscovery.h"
#import "LKSConfigManager.h"

@implementation LKS_HierarchyDisplayItemsMaker

+ (NSArray<LookinDisplayItem *> *)itemsWithScreenshots:(BOOL)hasScreenshots attrList:(BOOL)hasAttrList lowImageQuality:(BOOL)lowQuality includedWindows:(NSArray<UIWindow *> *)includedWindows excludedWindows:(NSArray<UIWindow *> *)excludedWindows {
[[LKS_TraceManager sharedInstance] reload];

NSArray<UIWindow *> *windows = [[UIApplication sharedApplication].windows copy];
NSArray<UIWindow *> *windows = [[LKS_WindowDiscovery sharedInstance].windows copy];
NSMutableArray *resultArray = [NSMutableArray arrayWithCapacity:windows.count];
[windows enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) {
if (includedWindows.count) {
Expand Down
3 changes: 2 additions & 1 deletion Src/Main/Server/Others/LKS_TraceManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#import "LookinIvarTrace.h"
#import "LookinServerDefines.h"
#import "LKS_LocalInspectManager.h"
#import "LKS_WindowDiscovery.h"

#ifdef LOOKIN_SERVER_SWIFT_ENABLED

Expand Down Expand Up @@ -50,7 +51,7 @@ - (void)reload {
// 把旧的先都清理掉
[NSObject lks_clearAllObjectsTraces];

[[[UIApplication sharedApplication].windows copy] enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) {
[[[LKS_WindowDiscovery sharedInstance].windows copy] enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) {
[self _addTraceForLayersRootedByLayer:window.layer];
}];
}
Expand Down
20 changes: 20 additions & 0 deletions Src/Main/Server/Others/LKS_WeakObjContainer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// LKS_WeakObjContainer.h
// LookinServer
//
// Created by andysheng on 2023/1/6.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface LKS_WeakObjContainer<__covariant ObjectType> : NSObject

@property (nonatomic, weak) ObjectType weakObj;

+ (instancetype)containerWithObj:(ObjectType)obj;

@end

NS_ASSUME_NONNULL_END
18 changes: 18 additions & 0 deletions Src/Main/Server/Others/LKS_WeakObjContainer.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// LKS_WeakObjContainer.m
// LookinServer
//
// Created by andysheng on 2023/1/6.
//

#import "LKS_WeakObjContainer.h"

@implementation LKS_WeakObjContainer

+ (instancetype)containerWithObj:(id)obj {
LKS_WeakObjContainer *container = [LKS_WeakObjContainer new];
container.weakObj = obj;
return container;
}

@end
29 changes: 29 additions & 0 deletions Src/Main/Server/Others/LKS_WindowDiscovery.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// LKS_WindowDiscovery.h
// LookinServer
//
// Created by andysheng on 2023/1/6.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@class UIWindow;
@interface LKS_WindowDiscovery : NSObject

/// combine different source of windows:
/// 1. [UIApplication sharedApplication].windows
/// 2. customWindow
/// 3. customView.window
@property (nonatomic, readonly) NSArray<UIWindow *> *windows;

+ (instancetype)sharedInstance;

- (void)addCustomWindow:(UIWindow *)window;

- (void)addCustomWindowWithView:(UIView *)view;

@end

NS_ASSUME_NONNULL_END
88 changes: 88 additions & 0 deletions Src/Main/Server/Others/LKS_WindowDiscovery.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//
// LKS_WindowDiscovery.m
// LookinServer
//
// Created by andysheng on 2023/1/6.
//

#import "LKS_WindowDiscovery.h"
#import "LKS_WeakObjContainer.h"

@interface LKS_WindowDiscovery ()

@property (nonatomic, strong) NSArray<LKS_WeakObjContainer<UIWindow *> *> *customWindows;
@property (nonatomic, strong) NSArray<LKS_WeakObjContainer<UIView *> *> *customViews;

@end

@implementation LKS_WindowDiscovery

+ (instancetype)sharedInstance {
static dispatch_once_t onceToken;
static LKS_WindowDiscovery *instance = nil;
dispatch_once(&onceToken, ^{
instance = [[super allocWithZone:NULL] init];
});
return instance;
}

- (void)addCustomWindow:(UIWindow *)window {
if (!window) {
return;
}
@synchronized (self) {
NSMutableArray<LKS_WeakObjContainer<UIWindow *> *> *mContainers = self.customWindows ? self.customWindows.mutableCopy : [NSMutableArray array];
[mContainers enumerateObjectsWithOptions:NSEnumerationReverse
usingBlock:^(LKS_WeakObjContainer * _Nonnull container, NSUInteger idx, BOOL * _Nonnull stop) {
if (!container.weakObj || container.weakObj == window) {
[mContainers removeObject:container];
}
}];
[mContainers addObject:[LKS_WeakObjContainer containerWithObj:window]];
self.customWindows = mContainers.copy;
}
}

- (void)addCustomWindowWithView:(UIView *)view {
if (!view) {
return;
}
@synchronized (self) {
NSMutableArray<LKS_WeakObjContainer<UIView *> *> *mContainers = self.customViews ? self.customViews.mutableCopy : NSMutableArray.array;
[mContainers enumerateObjectsWithOptions:NSEnumerationReverse
usingBlock:^(LKS_WeakObjContainer * _Nonnull container, NSUInteger idx, BOOL * _Nonnull stop) {
if (!container.weakObj || container.weakObj == view) {
[mContainers removeObject:container];
}
}];
[mContainers addObject:[LKS_WeakObjContainer containerWithObj:view]];
self.customViews = mContainers.copy;
}
}

- (NSArray<UIWindow *> *)windows {
NSMutableArray<UIWindow *> *retWindows = [[UIApplication sharedApplication].windows mutableCopy];
NSSet<UIWindow *> *windowSet = [NSSet setWithArray:retWindows];

NSMutableArray<UIWindow *> *candidateCustomWindows = [NSMutableArray array];
[self.customWindows enumerateObjectsUsingBlock:^(LKS_WeakObjContainer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
UIWindow *window = (UIWindow *)obj.weakObj;
if (window) {
[candidateCustomWindows addObject:window];
}
}];
[self.customViews enumerateObjectsUsingBlock:^(LKS_WeakObjContainer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
UIWindow *window = ((UIView *)obj.weakObj).window;
if (window) {
[candidateCustomWindows addObject:window];
}
}];
[candidateCustomWindows enumerateObjectsUsingBlock:^(UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) {
if (![windowSet containsObject:window]) {
[retWindows addObject:window];
}
}];
return retWindows;
}

@end