Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Soh Satoh committed Jan 21, 2021
0 parents commit 73a9e7f
Show file tree
Hide file tree
Showing 8 changed files with 878 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.theos/
packages/
1 change: 1 addition & 0 deletions FreePIP.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ Filter = { Bundles = ( "com.apple.springboard" ); }; }
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

26 changes: 26 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
INSTALL_TARGET_PROCESSES = SpringBoard

include $(THEOS)/makefiles/common.mk

TWEAK_NAME = FreePIP

ifeq ($(simulator),1)
export TARGET = simulator:clang:13.7:8.0 # It may be required to change here
ARCHS = x86_64
else
ARCHS = arm64 arm64e
endif

FreePIP_FILES = Tweak.x
FreePIP_CFLAGS = -fobjc-arc

include $(THEOS_MAKE_PATH)/tweak.mk

ifneq (,$(filter x86_64 i386,$(ARCHS)))
setup:: clean all
@rm -f /opt/simject/$(TWEAK_NAME).dylib
@cp -v .theos/obj/iphone_simulator/debug/$(TWEAK_NAME).dylib /opt/simject/$(TWEAK_NAME).dylib
@codesign -f -s - /opt/simject/$(TWEAK_NAME).dylib
@cp -v $(PWD)/$(TWEAK_NAME).plist /opt/simject
@/usr/local/bin/resim
endif
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# FreePIP

FreePIP is a tweak to the iOS Picture-in-Picture to un-snap and scale the view unlimitedly.

## Features

- Snap / Un-snap the view by long-press the PiP view
- Unlimited scaling

## Support

- iOS 13: Tested on iX, iOS13.7
- iOS 14: Tested on Simulator / I wrote the code by "seeing" the SpringBoard.framework

## Build

Just build using Theos

If you are using simulator and simject, you can build and install this by using following command.

## License

MIT License

**If you use the code of this tweak, you are obliged to publish the code for both commercial and personal use**
10 changes: 10 additions & 0 deletions Tweak.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@interface PGPictureInPictureViewController : UIViewController
@end

@interface SBPIPContainerViewController : UIViewController
-(PGPictureInPictureViewController *)pictureInPictureViewController;
-(void)_handlePanGesture:(UIPanGestureRecognizer *)arg1;
-(void)_handleRotationGesture:(UIRotationGestureRecognizer *)arg1;
-(void)_handlePinchGesture:(UIPinchGestureRecognizer *)arg1;
-(void)loadView;
@end
131 changes: 131 additions & 0 deletions Tweak.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "Tweak.h"


// How this tweak works

// Originally, the PiP view is snapped to edges using NSLayoutConstraint.
// NSLayoutConstraint is difficult to hook because it is managed as an Ivar.
// Therefore, this tweak uses CGAffineTransform to unsnap it.
// It's not a pretty fix and there must be a better way.
// If you know a beautiful fix, please let me know.

// iOS 13 - Tested on iX, iOS 13.7
// iOS 14 - Tested on Simulator (not on real devices)


// Ref: https://stackoverflow.com/questions/36763415/how-would-you-presentviewcontroller-from-subview (This is kind of a hacky way though...)
#define UIViewParentController(__view) ({ \
UIResponder *__responder = __view; \
while ([__responder isKindOfClass:[UIView class]]) \
__responder = [__responder nextResponder]; \
(UIViewController *)__responder; \
})
// End Ref


static BOOL locked = YES;


%hook SBPIPContainerViewController
-(void)loadView {
%orig;

UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressGesture:)];
[self.pictureInPictureViewController.view addGestureRecognizer:longPressGesture];
self.pictureInPictureViewController.view.layer.borderWidth = 1.5;
}

%new
- (void)handleLongPressGesture: (UILongPressGestureRecognizer *)sender {
if (sender.state != UIGestureRecognizerStateBegan) return;

if(locked) self.pictureInPictureViewController.view.layer.borderColor = [UIColor clearColor].CGColor;
else self.pictureInPictureViewController.view.layer.borderColor = [UIColor redColor].CGColor;

locked = !locked; // Revert the value
}

// iOS13
-(void)_handlePanGesture: (UIPanGestureRecognizer *)sender {
if(locked) %orig;
else if(sender.state == UIGestureRecognizerStateChanged) {
// Change the position of the view using CGAffineTransform
CGPoint translation = [sender translationInView:self.pictureInPictureViewController.view];
self.pictureInPictureViewController.view.transform = CGAffineTransformTranslate(self.pictureInPictureViewController.view.transform, translation.x, translation.y);
[sender setTranslation:CGPointZero inView: self.pictureInPictureViewController.view];
}
}

-(void)_handlePinchGesture:(UIPinchGestureRecognizer *)sender {
if(locked) %orig;
else if(sender.state == UIGestureRecognizerStateChanged) {
// Change the scale of the view using CGAffineTransform
self.pictureInPictureViewController.view.transform = CGAffineTransformScale(self.pictureInPictureViewController.view.transform, sender.scale, sender.scale);
sender.scale = 1.0;
}
}
-(void)_handleRotationGesture:(UIRotationGestureRecognizer *)sender {
// Rotation gesture do nothing (at least as far as I've tried)
// Prevent updating layout by rotation gesture
if(locked) %orig;
}

-(void)setContentViewPadding:(UIEdgeInsets)arg1 animationDuration:(double)arg2 animationOptions:(unsigned long long)arg3 {
// Prevent updating padding when switching apps
if(locked) %orig;
}

// iOS14
-(void)setContentViewPadding:(UIEdgeInsets)arg1 {
// Prevent updating padding when switching apps
if(!locked) arg1 = UIEdgeInsetsZero;
%orig(arg1);
}
%end


// iOS14
// Here is using the same logic as in iOS13, but there seems to be a better way.
%hook SBPIPInteractionController
-(void)handlePanGesture: (UIPanGestureRecognizer *)sender {
if(locked) %orig;
else if(sender.state == UIGestureRecognizerStateChanged) {
// Change the position of the view using CGAffineTransform
UIViewController *pgpVC = UIViewParentController(sender.view);

CGPoint translation = [sender translationInView:pgpVC.view];
pgpVC.view.transform = CGAffineTransformTranslate(pgpVC.view.transform, translation.x, translation.y);
[sender setTranslation:CGPointZero inView: pgpVC.view];
}

}
-(void)handlePinchGesture:(UIPinchGestureRecognizer *)sender {
if(locked) %orig;
else if(sender.state == UIGestureRecognizerStateChanged) {
// Change the scale of the view using CGAffineTransform
UIViewController *pgpVC = UIViewParentController(sender.view);
pgpVC.view.transform = CGAffineTransformScale(pgpVC.view.transform, sender.scale, sender.scale);
sender.scale = 1.0;
}
}
-(void)handleRotationGesture:(UIRotationGestureRecognizer *)sender {
// Rotation gesture do nothing (at least as far as I've tried)
// Prevent updating layout by rotation gesture
if(locked) %orig;
}
%end


%ctor {
// Somehow, ifdef does not work here
#if TARGET_OS_SIMULATOR
NSLog(@"freepip - target is simulator");
#else
NSLog(@"frepip - target is a real device");
if(![[NSFileManager defaultManager] fileExistsAtPath:@"/var/lib/dpkg/info/jp.soh.freepip.list"]) return; // Prevent initializing the tweak if the tweak is malformed (Extremely easy to bypass it, but the pirate repos like HYI cannot bypass it lol)
#endif

%init; // initialize the tweak
}
9 changes: 9 additions & 0 deletions control
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Package: jp.soh.freepip
Name: FreePIP
Version: 0.0.1
Architecture: iphoneos-arm
Description: An awesome MobileSubstrate tweak!
Maintainer: Soh Satoh
Author: Soh Satoh
Section: Tweaks
Depends: mobilesubstrate (>= 0.9.5000)

0 comments on commit 73a9e7f

Please sign in to comment.