Implement DMGestureRecognizer to start/stop directmanipluation on scrollveiwer#1305
Conversation
…llviewer so that other gestures attached to subviews inside UIScrollview can be properly triggered
| int count = (i == 0) ? gestureCount : dmGestureCount; | ||
| for (int k = 0; k < count; k++) { | ||
| UIGestureRecognizer* curgesture = recognizers[i]; | ||
| UIGestureRecognizer* curgesture = ( i==0 ) ? recognizers[k] : dmrecognizers[k]; |
| BOOL _isZooming; | ||
| BOOL _isZoomingToRect; | ||
|
|
||
| // Dimanip gesture recognizer, used for detecting if Dimanip should start or not |
There was a problem hiding this comment.
Dimanip [](start = 57, length = 7)
nit: Shouldn't these be DManip, not Dimanip? #Resolved
| - (void)dealloc { | ||
| _zoomView = nil; | ||
| _dmGesture = nil; | ||
|
|
There was a problem hiding this comment.
You do not need to set StrongId instances to nil. #Resolved
| return [_UIScrollViewCALayer class]; | ||
| } | ||
|
|
||
| void _setManipulationMode(UIScrollView* self, WUXIManipulationModes mode, BOOL recursive) { |
There was a problem hiding this comment.
_setManipulationMode [](start = 5, length = 20)
Make this static?
It could also be a method.. #Resolved
| while (toLayer.superlayer != nil) { | ||
| toLayer = toLayer.superlayer; | ||
| } | ||
| } |
There was a problem hiding this comment.
I thought you weren't including the changes to this file? #Pending
There was a problem hiding this comment.
i can revert the change here and wait for your change to come in. but this is going to leave corresponding issue hanging around a little longer given ux/uxe will probably take longer to arrive develop. On the other hand, for the merge conflicts that is going to occur if I leave this change here, you can just reject mine and accept yours when merging since you already have equivalent? Let me know what you think. I can do either.
In reply to: 86420400 [](ancestors = 86420400)
| }; | ||
|
|
||
| @interface UIPanGestureRecognizer() | ||
| -(const std::vector<TouchInfo>&)getTouches; |
There was a problem hiding this comment.
getTouches [](start = 36, length = 10)
shouldn't this be _getTouches since it's private/internal? #Resolved
| static const bool DEBUG_DELEGATE = DEBUG_ALL || false; | ||
| static const bool DEBUG_INSETS = DEBUG_ALL || false; | ||
| static const bool DEBUG_ZOOM = DEBUG_ALL || false; | ||
| static const bool DEBUG_DMGesture = DEBUG_ALL || false; |
There was a problem hiding this comment.
DEBUG_DMGesture [](start = 18, length = 15)
nit: nobody will know what 'dm' is when they come by later. Can we call this DEBUG_DMANIP_GESTURE? #Resolved
| BOOL _isZoomingToRect; | ||
|
|
||
| // Dimanip gesture recognizer, used for detecting if Dimanip should start or not | ||
| StrongId<_UIDMPanGestureRecognizer> _dmGesture; |
There was a problem hiding this comment.
_dmGesture [](start = 40, length = 10)
nit: _dManipGesture #Resolved
| _scrollViewer.minZoomFactor = 1.0f; | ||
| _scrollViewer.zoomMode = WXCZoomModeDisabled; | ||
|
|
||
| // setting transparent background |
There was a problem hiding this comment.
setting transparent background [](start = 7, length = 30)
...'so we can receive touch input' #Resolved
| #import "Starboard.h" | ||
| #import "UIGestureRecognizerInternal.h" | ||
| #import "UIPanGestureRecognizerInternal.h" | ||
| #import "_UIDMPanGestureRecognizer.h" |
There was a problem hiding this comment.
DM [](start = 12, length = 2)
Everywhere you use 'DM', can we use something more descriptive - maybe DManip? #Resolved
| } | ||
|
|
||
| static void commonInit(UIPanGestureRecognizer* self) { | ||
| [self _setDragSlack:7.0f]; |
There was a problem hiding this comment.
[self _setDragSlack:7.0f]; [](start = 1, length = 29)
why 7.0f? can you add a comment for this? #Resolved
| if (g_resetAllTrackingGestures) { | ||
| g_resetAllTrackingGestures = FALSE; | ||
| // Find gesture recognizers in the heirarchy, back-first | ||
| // Find gesture recognizers in the heirarchy, back-first |
There was a problem hiding this comment.
heirarchy [](start = 43, length = 9)
super-nit: hierarchy #Resolved
| const static int MAXIMUM_DMGESTURE_ALLOW = 16; | ||
|
|
||
| UIGestureRecognizer* recognizers[MAXIMUM_GESTURE_ALLOW]; | ||
| UIGestureRecognizer* dmrecognizers[MAXIMUM_DMGESTURE_ALLOW]; |
There was a problem hiding this comment.
dm [](start = 25, length = 2)
more use of 'dm' - could definitely use more descriptive names across all of these files/file names/etc. #Resolved
| if (dmGestureCount < MAXIMUM_DMGESTURE_ALLOW) { | ||
| dmrecognizers[dmGestureCount++] = curgesture; | ||
| } else { | ||
| TraceWarning(TAG, L"DMGestures exceed maxinum allowed, ignoring the rest"); |
There was a problem hiding this comment.
maxinum [](start = 54, length = 7)
nit: maximum #Resolved
|
Do we already have an existing test for this in XamlCatalog or WoCCatalog? #Resolved |
| for (int i = 0; i < viewDepth; i++) { | ||
| // sendTouch to gesture for state transiton | ||
| BOOL gestureOnGoing = NO; | ||
| for (int i = 0; i < gestureCount; i++) { |
There was a problem hiding this comment.
you should be able to do range-based for loops over both of these gesture arrays #Resolved
|
|
||
| // scanning DM Getures, if a gestures is on going, cancel DM Gestures | ||
| // otherwise, send Touch to DM gestures | ||
| for (int i = 0; i < dmGestureCount; i++) { |
There was a problem hiding this comment.
for (int i = 0; i < dmGestureCount; i++) { [](start = 3, length = 43)
nit: range-based for here, too #Resolved
| [dmGesture performSelector:eventName withObject:[NSMutableSet setWithObject:touch] withObject:event]; | ||
| if (DEBUG_GESTURES) { | ||
| TraceVerbose(TAG, L"Send Touch with phase=%d to DMGesture %hs.", touch.phase, object_getClassName(dmGesture)); | ||
| } |
There was a problem hiding this comment.
nit: why not move this into the above 'if' and ditch the 'send' variable? #WontFix
There was a problem hiding this comment.
the current form is actually better. notice default is true. If remove send, the conditional clause becomes much more complex and not clear.
In reply to: 86438414 [](ancestors = 86438414)
| UIGestureRecognizerState state = (UIGestureRecognizerState)[curgesture state]; | ||
| // Removed/reset failed/done gestures, including gestures and DMGestures | ||
| for (int i = 0; i < 2; i++) { | ||
| int count = (i == 0) ? gestureCount : dmGestureCount; |
There was a problem hiding this comment.
kind of strange; how about pulling this out into a shared function or lambda that gets called for both arrays? #Resolved
|
|
||
| // setting transparent background so we can receive touch input | ||
| WUColor* convertedColor = ConvertUIColorToWUColor([UIColor clearColor]); | ||
| WUXMSolidColorBrush* brush = [WUXMSolidColorBrush makeInstanceWithColor:convertedColor]; |
There was a problem hiding this comment.
how about just setting directly to the projected transparent brush rather than creating a UIColor only to convert to the projected type? Something like [WUXMSolidColorBrush makeInstanceWithColor:[WUColor transparent]] ? #Resolved
There was a problem hiding this comment.
at which point you could just do _contentCanvas.background = [WUXMSolidColorBrush makeInstanceWithColor:[WUColor transparent]]
In reply to: 86439907 [](ancestors = 86439907)
There was a problem hiding this comment.
| // get the backing xaml UIElement for toLayer | ||
| WXUIElement* toLayerElement = _getBackingXamlElementForCALayer(toLayer); | ||
|
|
||
| // set up transform from xaml elment in fromLayer to xaml element in toLayer |
There was a problem hiding this comment.
Typo - element #Resolved
| [self _setManipulationMode:WUXIManipulationModesSystem recursive:YES]; | ||
|
|
||
| const std::vector<TouchInfo>& pointers = [gesture _getTouches]; | ||
| for (size_t i = 0; i < pointers.size(); ++i) { |
There was a problem hiding this comment.
for (size_t i = 0; i < pointers.size(); ++i) { [](start = 2, length = 48)
range-based for #Resolved
| // start Direct manipuation only if active touch presents | ||
| if (touch.phase != UITouchPhaseCancelled && touch->_routedEventArgs.pointer.pointerDeviceType == WDIPointerDeviceTypeTouch) { | ||
| if (![WXFrameworkElement tryStartDirectManipulation:touch->_routedEventArgs.pointer]) { | ||
| TraceWarning(TAG, L"DManip didn't start"); |
There was a problem hiding this comment.
didn't [](start = 43, length = 6)
nit: 'failed to' might be more clear #Resolved
|
yes, we do. In WoCcatalog, the textview is a good example of gesture attached to subview get fired first and DM will be cancelled. and also, when DM gesture started, it can be chained to upper UIScrollview as well. In reply to: 258266383 [](ancestors = 258266383) |
| - (void)scrollViewDidZoom:(UIScrollView*)aScrollView { | ||
| // don't have to do anything special to centralize the imageView after zoom when zoomFactor is less than 1 | ||
| // xaml scrollview does that automatically now | ||
| CGFloat offsetX = (scrollView.bounds.size.width > scrollView.contentSize.width) ? |
There was a problem hiding this comment.
CGFloat [](start = 4, length = 7)
accidental, i will revert. #Resolved
| return didRecognize; | ||
| } | ||
|
|
||
| - (const std::vector<TouchInfo>&)_getTouches { |
There was a problem hiding this comment.
Out of interest, why is it a reference and not just a copy? #Resolved
There was a problem hiding this comment.
There was a problem hiding this comment.
However, if this case is it also why we need to keep the StrongId<> around? If we did make a copy are things cleaner? #Pending
There was a problem hiding this comment.
you mean StrongId _routedEventArgs;? StrongId here is to make sure UITouch has the same life time for routedEventArgs, as we see in multiple-finger gesture cases, routedEventArgs can be become invalid though UITouch is still valid. Still a mystery to figure out why. But copy won't solve this problem either plus add additional cost.
In reply to: 86604604 [](ancestors = 86604604)
| const std::vector<TouchInfo>& pointers = [gesture _getTouches]; | ||
| for (size_t i = 0; i < pointers.size(); ++i) { | ||
| UITouch* touch = pointers[i].touch; | ||
| // start Direct manipuation only if active touch presents |
There was a problem hiding this comment.
I'm really bad at this but my eyes are drawn to capitalization changes - direct manipulation is what you used above. #Resolved
| for (size_t i = 0; i < pointers.size(); ++i) { | ||
| UITouch* touch = pointers[i].touch; | ||
| // start Direct manipuation only if active touch presents | ||
| if (touch.phase != UITouchPhaseCancelled && touch->_routedEventArgs.pointer.pointerDeviceType == WDIPointerDeviceTypeTouch) { |
There was a problem hiding this comment.
Is _routedEventArgs.pointer guaranteed to be populated and non-null? #Resolved
There was a problem hiding this comment.
| g_curGesturesDict = [NSMutableDictionary new]; | ||
|
|
||
| UIGestureRecognizer* recognizers[128]; | ||
| const static int MAXIMUM_GESTURE_ALLOW = 128; |
There was a problem hiding this comment.
Super nit: MAXIMUM_GESTURE_ALLOWED #Resolved
| static const bool DEBUG_DELEGATE = DEBUG_ALL || false; | ||
| static const bool DEBUG_INSETS = DEBUG_ALL || false; | ||
| static const bool DEBUG_ZOOM = DEBUG_ALL || false; | ||
| static const bool DEBUG_DMANIP_GESTURE = DEBUG_ALL || true; |
There was a problem hiding this comment.
true [](start = 54, length = 4)
set back to false before pushing? #Resolved
There was a problem hiding this comment.
| const std::vector<TouchInfo>& pointers = [gesture _getTouches]; | ||
| for (auto const& pointer : pointers) { | ||
| UITouch* touch = pointer.touch; | ||
| // start Direct manipuation only if active touch presents |
There was a problem hiding this comment.
manipuation [](start = 24, length = 11)
nit: Typo #Resolved
| // setting it to 7.0 which is slightly larger than 6.0 which is used | ||
| // by PanGestureRecognizer, this is to ensure PanGestureRecognizer kicks | ||
| // in first before us. | ||
| [self _setDragSlack:7.0f]; |
There was a problem hiding this comment.
nit: maybe we should expose this off of a private UIPanGestureRecognizer property, so we can just +1 here? #Resolved
|
|
||
| #import <math.h> | ||
| #import <string> | ||
| #import <array> |
There was a problem hiding this comment.
remove? sorry for the noise! :/ #Resolved
|
|
Implement DMGestureRecognizer to start/stop direct manipluation on XAML Scrollveiwer so that gestures attached to subviews within a UIScrollview can be properly triggered. and at the same time, direct manipulation can be triggered if no other gestured are recognized.
This change is