- on screen button “folder” prototype

- overlapped buttons triggered at touch began
- memory management fixes
- reduce toolbox view & widget layout tool animation
- fast widget profile loading
- toolbox & widget profile selector quick dismiss
This commit is contained in:
True Zhuanjia
2026-01-29 10:06:04 +08:00
parent ab1d6bfa90
commit 8f8e86ab4f
45 changed files with 2038 additions and 865 deletions
@@ -26,6 +26,7 @@
#import "VoidLink-Swift.h"
#import "OSCProfilesManager.h"
#import "ThemeManager.h"
#import "NativeTouchPointer.h"
#include <sys/socket.h>
#include <netinet/in.h>
@@ -61,7 +62,6 @@
StreamView *_streamView;
UIScrollView *_scrollView;
BOOL _userIsInteracting;
bool viewJustLoaded;
bool viewIsBeingResized;
bool previousOnScreenWidgetEnabled;
CGSize _keyboardSize;
@@ -378,7 +378,7 @@
Connection.muteInBackground = _settings.muteInBackground;
if(!viewJustLoaded) [_controllerSupport updateControllerSupport:self.streamConfig delegate:self];
if(!_viewJustLoaded) [_controllerSupport updateControllerSupport:self.streamConfig delegate:self];
// reload controllerSupport obj, this is mandatory for OSC reload,especially when the stream view is launched without OSC
[_streamView setupStreamView:_controllerSupport interactionDelegate:self config:self.streamConfig streamFrameTopLayerView:self.view]; //reinitiate setupStreamView process.
// we got self.view passed to streamView class as the topLayerView, will be useful in many cases
@@ -387,7 +387,8 @@
bool onScreenWidgetSwitched = previousOnScreenWidgetEnabled != [_streamView isOnScreenWidgetEnabled];
bool needReload = onScreenWidgetSwitched && !previousOnScreenWidgetEnabled;
if(viewJustLoaded||reloadOnscreenWidgets||needReload) [_streamView reloadOnScreenWidgetViews]; //reload keyboard buttons here. the keyboard widget view will be added to the streamframe view instead streamview, the highest layer, which saves a lot of reengineering
[_streamView reloadOnScreenWidgetViews:_viewJustLoaded||reloadOnscreenWidgets||needReload]; //reload keyboard buttons here. the keyboard widget view will be added to the streamframe view instead streamview, the highest layer, which saves a lot of reengineering
if(onScreenWidgetSwitched && previousOnScreenWidgetEnabled) [_streamView clearOnScreenWidgets];
previousOnScreenWidgetEnabled = [_streamView isOnScreenWidgetEnabled];
@@ -444,13 +445,10 @@
[self startDisplayLink];
}
_motionHandler = [MotionHandler sharedInstance];
_motionHandler = [MotionHandler sharedWithProfile: nil];
_motionHandler.gyroBiasX = _settings.gyroBiasX.doubleValue;
_motionHandler.gyroBiasY = _settings.gyroBiasY.doubleValue;
_motionHandler.gyroBiasZ = _settings.gyroBiasZ.doubleValue;
_streamView.onScreenControls.instanceReceiverDelegate = _motionHandler;
[_streamView.onScreenControls sendInstance];
TouchPadGestureHandler.enablePinch = _settings.enablePinch;
TouchPadGestureHandler.ctrlDownForPinch = _settings.ctrlDownForPinch;
@@ -474,7 +472,7 @@
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
viewJustLoaded = false;
_viewJustLoaded = false;
_deviceWindow = self.view.window;
previousOnScreenWidgetEnabled = [_streamView isOnScreenWidgetEnabled];
if (@available(iOS 13.0, *)) {
@@ -499,6 +497,11 @@
}
self->_streamView.originalFrame = self->_streamView.frame;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5*NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"pausing...");
nil;
});
// check to see if external screen is connected/disconnected
@@ -583,7 +586,7 @@
- (void)viewDidLoad
{
viewJustLoaded = true;
_viewJustLoaded = true;
viewIsBeingResized = false;
[super viewDidLoad];
@@ -768,7 +771,7 @@
[self presentViewController:_layoutOnScreenControlsVC animated:YES completion:nil];
}
- (void)switchWidgetProfile{
- (void)openWidgetProfileTableWithPickProfile:(BOOL)pickProfile{
[_streamView saveRelocatedWidgetViews];
_streamView.widgetToolOpened = true;
[self->_streamView disableOnScreenControls];
@@ -777,7 +780,7 @@
_layoutOnScreenControlsVC.toolbarStackView.hidden = true;
_layoutOnScreenControlsVC.toolbarRootView.hidden = true;
[self presentViewController:_layoutOnScreenControlsVC animated:NO completion:^{
[self->_layoutOnScreenControlsVC presentProfilesTableView];
[self->_layoutOnScreenControlsVC presentProfilesTableViewWithPickProfile:pickProfile];
}];
}
@@ -799,8 +802,8 @@
[self->_streamView disableOnScreenControls]; // add this to get realtime back menu working.
[self->_streamView reloadOnScreenControlsWith:(ControllerSupport*)_controllerSupport
andConfig:(StreamConfiguration*)_streamConfig];
[self->_streamView showOnScreenControls];
[self->_streamView reloadOnScreenWidgetViews]; //update keyboard buttons here
// [self->_streamView reloadLegacyWidgets];
[self->_streamView reloadOnScreenWidgetViews:true]; //update keyboard buttons here
}
- (void)setUserInteractionEnabledForStreamView:(bool)enabled{
@@ -817,7 +820,8 @@
- (void)willMoveToParentViewController:(UIViewController *)parent {
// Only cleanup when we're being destroyed
if (parent == nil) {
//NSLog(@"gyro cleanup, count: %ld", _controller.count);
_streamView = nil;
[_streamView cleanUp];
[_controllerSupport cleanup];
[UIApplication sharedApplication].idleTimerDisabled = NO;
@@ -832,7 +836,11 @@
self.metalViewController = nil;
NSLog(@"Metal renderer stopped and cleaned up.");
}
[NativeTouchPointer cleanUpContext];
[[NSNotificationCenter defaultCenter] removeObserver:self];
for(UIView* view in self.view.subviews){
[view removeFromSuperview];
}
}
}
@@ -936,7 +944,7 @@
- (void) returnToMainFrame {
[_streamView clearOnScreenWidgets];
if(micHandler) [micHandler clean];
PencilHandler.sharedInstance = nil;
PencilHandler.shared = nil;
// Reset display mode back to default
[self updatePreferredDisplayMode:NO];
@@ -1188,7 +1196,7 @@
[self.view sendSubviewToBack:self->_streamView];
}
[self->_streamView showOnScreenControls];
// [self->_streamView showOnScreenControls];
[self->_controllerSupport connectionEstablished];
@@ -1609,6 +1617,28 @@
[_streamView disablePencilHover];
}
- (void)setAllowSingleTouchEnabled:(BOOL)enabled{
[_streamView setAllowSingleTouchEnabled:enabled];
}
- (void)replaceBrushWithShortcut:(NSString *)shortcut{
if(PencilHandler.shared){
[PencilHandler.shared replaceBrushWith:shortcut];
}
}
- (void)replaceEraserWithShortcut:(NSString *)shortcut{
if(PencilHandler.shared){
[PencilHandler.shared replaceEraserWith:shortcut];
}
}
- (void)presentPressureCurveVC{
PressureCurveViewController* pressureCurveVC = [[PressureCurveViewController alloc] init];
pressureCurveVC.modalPresentationStyle = UIModalPresentationOverFullScreen;
[self presentViewController:pressureCurveVC animated:YES completion:nil];
}
#if !TARGET_OS_TV
// Require a confirmation when streaming to activate a system gesture
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures {
@@ -1645,7 +1675,8 @@
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[self->_streamView saveRelocatedWidgetViews];
if (_isRestoringFromPiP) {
Log(LOG_I, @"View size changed during PiP restore, skipping redundant reconfiguration.");
return;
@@ -1668,6 +1699,7 @@
- (void)dealloc {
[self stopDisplayLink];
NSLog(@"dealloc StreamFrameViewController %f", CACurrentMediaTime());
}
- (void)setupDisplayLink {
@@ -1698,5 +1730,4 @@
});
}
@end