[Libreoffice-commits] core.git: include/osl include/touch ios/experimental sw/source vcl/ios vcl/source
ptyl at cloudon.com
ptyl at cloudon.com
Wed Oct 9 07:38:08 PDT 2013
include/osl/detail/ios-bootstrap.h | 3
include/touch/touch.h | 4
ios/experimental/LibreOffice/LibreOffice/View.m | 42 ++++++-
sw/source/ui/uiview/viewport.cxx | 104 +++++++++++++++++-
vcl/ios/iosinst.cxx | 17 ++-
vcl/source/window/window2.cxx | 133 ++++++++++++++++--------
vcl/source/window/winproc.cxx | 55 ++-------
7 files changed, 258 insertions(+), 100 deletions(-)
New commits:
commit 4e7495ac2cb6b015ad492def45fd24f4ba0f54f8
Author: ptyl at cloudon.com <ptyl at cloudon.com>
Date: Sun Sep 1 19:22:23 2013 +0300
Fix for iOS scroll by pixels, and pinch to zoom
Minor further changes by tml to match the coding style of surrounding
code mainly.
Change-Id: Ied6087a264f1c6b00763ea36fba9808329afede4
Reviewed-on: https://gerrit.libreoffice.org/5742
Tested-by: Tor Lillqvist <tml at collabora.com>
Reviewed-by: Tor Lillqvist <tml at collabora.com>
diff --git a/include/osl/detail/ios-bootstrap.h b/include/osl/detail/ios-bootstrap.h
index fa3d0c8..42c38e4 100644
--- a/include/osl/detail/ios-bootstrap.h
+++ b/include/osl/detail/ios-bootstrap.h
@@ -49,7 +49,8 @@ void lo_runMain();
void lo_set_view_size(int width, int height);
void lo_render_windows(CGContextRef context, CGRect rect);
void lo_tap(int x, int y);
-void lo_pan(int x, int y);
+void lo_pan(int deltaX, int deltaY);
+void lo_zoom(int x, int y, float scale);
void lo_keyboard_input(int c);
#ifdef __cplusplus
diff --git a/include/touch/touch.h b/include/touch/touch.h
index 8fa2dd1..2fd7a9a 100644
--- a/include/touch/touch.h
+++ b/include/touch/touch.h
@@ -14,6 +14,10 @@
#if !HAVE_FEATURE_DESKTOP
+#define MOBILE_MAX_ZOOM_IN 600
+#define MOBILE_MAX_ZOOM_OUT 80
+#define MOBILE_ZOOM_SCALE_MULTIPLIER 10000
+
// Functions to be implemented by the app-specifc upper or less
// app-specific but platform-specific medium layer on touch-based
// platforms. The same API is used on each such platform. There are
diff --git a/ios/experimental/LibreOffice/LibreOffice/View.m b/ios/experimental/LibreOffice/LibreOffice/View.m
index 8c490cb..4e347a2 100644
--- a/ios/experimental/LibreOffice/LibreOffice/View.m
+++ b/ios/experimental/LibreOffice/LibreOffice/View.m
@@ -50,21 +50,49 @@
{
if ([gestureRecognizer state] == UIGestureRecognizerStateEnded) {
CGPoint location = [gestureRecognizer locationInView: self];
+
NSLog(@"tapGesture: at: (%d,%d)", (int)location.x, (int)location.y);
+
lo_tap(location.x, location.y);
+
[self->textView becomeFirstResponder];
- } else
+ } else {
NSLog(@"tapGesture: %@", gestureRecognizer);
+ }
}
- (void)panGesture:(UIPanGestureRecognizer *)gestureRecognizer
{
- if ([gestureRecognizer state] == UIGestureRecognizerStateEnded) {
- CGPoint translation = [gestureRecognizer translationInView: self];
- NSLog(@"panGesture: pan: (%d,%d)", (int)translation.x, (int)translation.y);
- lo_pan(translation.x, translation.y);
- } else
- NSLog(@"panGesture: %@", gestureRecognizer);
+ static CGFloat previousX = 0.0f, previousY = 0.0f;
+
+ CGPoint translation = [gestureRecognizer translationInView: self];
+
+ if (gestureRecognizer.state != UIGestureRecognizerStateBegan) {
+ int deltaX = translation.x - previousX;
+ int deltaY = translation.y - previousY;
+
+ NSLog(@"panGesture: pan (delta): (%d,%d)", deltaX, deltaY);
+
+ lo_pan(deltaX, deltaY);
+ }
+
+ previousX = translation.x;
+ previousY = translation.y;
+}
+
+- (void)pinchGesture:(UIPinchGestureRecognizer *)gestureRecognizer
+{
+ CGPoint location = [gestureRecognizer locationInView: self];
+ CGFloat scale = gestureRecognizer.scale;
+
+ NSLog(@"pinchGesture: pinch: (%f) cords (%d,%d)", (float)scale, (int)location.x, (int)location.y );
+
+ lo_zoom((int)location.x, (int)location.y, (float)scale);
+
+ // to reset the gesture scaling
+ if (gestureRecognizer.state==UIGestureRecognizerStateEnded) {
+ lo_zoom(1, 1, 0.0f);
+ }
}
@end
diff --git a/sw/source/ui/uiview/viewport.cxx b/sw/source/ui/uiview/viewport.cxx
index c137db6..4f34f2a 100644
--- a/sw/source/ui/uiview/viewport.cxx
+++ b/sw/source/ui/uiview/viewport.cxx
@@ -17,6 +17,8 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
+#include <config_features.h>
+
#include "hintids.hxx"
#include <vcl/help.hxx>
#include <svx/ruler.hxx>
@@ -37,6 +39,7 @@
#include <pagedesc.hxx>
#include <workctrl.hxx>
#include <crsskip.hxx>
+#include <touch/touch.h>
#include <PostItMgr.hxx>
@@ -298,11 +301,12 @@ void SwView::SetVisArea( const Point &rPt, sal_Bool bUpdateScrollbar )
// (fix: Bild.de, 200%) It does not work completly without alignment
// Let's see how far we get with half BrushSize.
Point aPt( rPt );
-// const long nTmp = GetWrtShell().IsFrameView() ? BRUSH_SIZE/2 : BRUSH_SIZE;
- const long nTmp = GetWrtShell().IsFrameView() ? 4 : 8;
aPt = GetEditWin().LogicToPixel( aPt );
+#if HAVE_FEATURE_DESKTOP
+ const long nTmp = GetWrtShell().IsFrameView() ? 4 : 8;
aPt.X() -= aPt.X() % nTmp;
aPt.Y() -= aPt.Y() % nTmp;
+#endif
aPt = GetEditWin().PixelToLogic( aPt );
if ( aPt == m_aVisArea.TopLeft() )
@@ -1258,19 +1262,107 @@ sal_Bool SwView::HandleWheelCommands( const CommandEvent& rCEvt )
}
else if( COMMAND_WHEEL_ZOOM_SCALE == pWData->GetMode() )
{
- int newZoom = 100 * (m_pWrtShell->GetViewOptions()->GetZoom() / 100.0) * (pWData->GetDelta() / 100.0);
- SetZoom( SVX_ZOOM_PERCENT, std::max( 20, std::min( 600, newZoom ) ) );
+ // COMMAND_WHEEL_ZOOM_SCALE is de facto used only for Android and iOS, I think
+
+ // mobile touch zoom (pinch) section
+ // last location in pixels is defaulted to an illegal location
+ // (coordinates are always positive)
+ static Point lastLocationInPixels(0,0);
+ static const double NEW_ZOOM_START= -6666.66;
+ static double initialZoom = NEW_ZOOM_START;
+ static int rememberedZoom = 0;
+
+ // the target should remain the same in logic, regardless of eventual zoom
+ const Point & targetInLogic = GetEditWin().PixelToLogic(rCEvt.GetMousePosPixel());
+ double scale = double(pWData->GetDelta()) / double(MOBILE_ZOOM_SCALE_MULTIPLIER);
+
+ if( scale==0 )
+ {
+ // scale 0, means end of gesture, and zoom resets
+ rememberedZoom=0;
+ }
+ else
+ {
+ int preZoomByVCL = m_pWrtShell->GetViewOptions()->GetZoom();
+ bool isFirst = rememberedZoom != preZoomByVCL;
+
+ if( isFirst )
+ {
+ // If this is the start of a new zoom action, we take the value from VCL.
+ // Otherwise, we remeber the zoom from the previous action.
+ // This way we can be more accurate than VCL
+ initialZoom =(double) preZoomByVCL;
+ }
+
+ // each zooming event is scaling the initial zoom
+ int zoomTarget = int(initialZoom * scale);
+
+ // thresholding the zoom
+ zoomTarget = std::max( MOBILE_MAX_ZOOM_OUT, std::min( MOBILE_MAX_ZOOM_IN, zoomTarget ) );
+ long deltaX = 0, deltaY = 0;
+
+ // no point zooming if the target zoom is the same as the current zoom
+ if( zoomTarget != preZoomByVCL )
+ {
+
+ SetZoom( SVX_ZOOM_PERCENT, zoomTarget );
+
+ // getting the VCL post zoom
+ rememberedZoom = m_pWrtShell->GetViewOptions()->GetZoom();
+ }
+ else
+ {
+ rememberedZoom = preZoomByVCL;
+ }
+
+ // if there was no zoom
+ if( rememberedZoom == preZoomByVCL )
+ {
+ if( !isFirst )
+ {
+ // If this is not the first location of the zoom, there is a valid last location.
+ // Therefore, scroll the center of the gesture.
+ // Explanation: without a zoom transpiring, the view will not change.
+ // Therefore, we do a simple scrolll from screen center to screen center
+ deltaX = rCEvt.GetMousePosPixel().X() - lastLocationInPixels.X();
+ deltaY = rCEvt.GetMousePosPixel().Y() - lastLocationInPixels.Y();
+ }
+ }
+ else
+ {
+ // Otherwise, there was a zoom.
+ // Keep the on screen center of the pinch in the same on screen location
+ const Point & postZoomTargetInPixels = GetEditWin().LogicToPixel(targetInLogic);
+
+ deltaX = rCEvt.GetMousePosPixel().X() - postZoomTargetInPixels.X();
+ deltaY = rCEvt.GetMousePosPixel().Y() - postZoomTargetInPixels.Y();
+ }
+
+ if( (deltaX!=0) || (deltaY!=0) )
+ {
+ // Scrolling the deltaX deltaY
+ Point deltaPoint( deltaX, deltaY );
+ CommandWheelData cmd( 0, 0, 0, COMMAND_WHEEL_SCROLL, 0, 0, true);
+ CommandEvent event(deltaPoint , COMMAND_WHEEL, sal_True, &cmd );
+
+ m_pEditWin->HandleScrollCommand(event, m_pHScrollbar, m_pVScrollbar);
+ }
+
+ // store the last location
+ lastLocationInPixels = rCEvt.GetMousePosPixel();
+ }
+
bOk = sal_True;
}
else
{
- if(pWData->GetMode()==COMMAND_WHEEL_SCROLL)
+ if( pWData->GetMode()==COMMAND_WHEEL_SCROLL )
{
// This influences whether quick help is shown
m_bWheelScrollInProgress=true;
}
- if ((COMMAND_WHEEL_SCROLL==pWData->GetMode()) && (((sal_uLong)0xFFFFFFFF) == pWData->GetScrollLines()))
+ if( (COMMAND_WHEEL_SCROLL==pWData->GetMode()) && (((sal_uLong)0xFFFFFFFF) == pWData->GetScrollLines()) )
{
if (pWData->GetDelta()<0)
PhyPageDown();
diff --git a/vcl/ios/iosinst.cxx b/vcl/ios/iosinst.cxx
index dd92c6e..e7cec9f 100644
--- a/vcl/ios/iosinst.cxx
+++ b/vcl/ios/iosinst.cxx
@@ -426,17 +426,28 @@ void lo_tap(int x, int y)
}
extern "C"
-void lo_pan(int x, int y)
+void lo_pan(int deltaX, int deltaY)
{
SalFrame *pFocus = IosSalInstance::getInstance()->getFocusFrame();
if (pFocus) {
- SAL_INFO( "vcl.ios", "scroll: " << "(" << x << "," << y << ")" );
- ScrollEvent aEvent( x, y );
+ SAL_INFO( "vcl.ios", "pan delta: " << "(" << deltaX << "," << deltaY << ") ");
+ ScrollEvent aEvent( deltaX, deltaY );
Application::PostScrollEvent(VCLEVENT_WINDOW_SCROLL, pFocus->GetWindow(), &aEvent);
}
}
extern "C"
+void lo_zoom(int x, int y, float scale)
+{
+ SalFrame *pFocus = IosSalInstance::getInstance()->getFocusFrame();
+ if (pFocus) {
+ SAL_INFO( "vcl.ios", "pinch: " << "(" << scale << ") ");
+ ZoomEvent aEvent( Point(x,y), scale);
+ Application::PostZoomEvent(VCLEVENT_WINDOW_ZOOM, pFocus->GetWindow(), &aEvent);
+ }
+}
+
+extern "C"
void lo_keyboard_input(int c)
{
SalFrame *pFocus = IosSalInstance::getInstance()->getFocusFrame();
diff --git a/vcl/source/window/window2.cxx b/vcl/source/window/window2.cxx
index 475181c..49f7650 100644
--- a/vcl/source/window/window2.cxx
+++ b/vcl/source/window/window2.cxx
@@ -1111,6 +1111,38 @@ long Window::GetDrawPixel( OutputDevice* pDev, long nPixels ) const
// -----------------------------------------------------------------------
+static void lcl_HandleScrollHelper( ScrollBar* pScrl, long nN, bool isMultiplyByLineSize )
+{
+ if ( pScrl && nN && pScrl->IsEnabled() && pScrl->IsInputEnabled() && ! pScrl->IsInModalMode() )
+ {
+ long nNewPos = pScrl->GetThumbPos();
+
+ if ( nN == -LONG_MAX )
+ nNewPos += pScrl->GetPageSize();
+ else if ( nN == LONG_MAX )
+ nNewPos -= pScrl->GetPageSize();
+ else
+ {
+ // allowing both chunked and continuous scrolling
+ if(isMultiplyByLineSize){
+ nN*=pScrl->GetLineSize();
+ }
+
+ const double fVal = (double)(nNewPos - nN);
+
+ if ( fVal < LONG_MIN )
+ nNewPos = LONG_MIN;
+ else if ( fVal > LONG_MAX )
+ nNewPos = LONG_MAX;
+ else
+ nNewPos = (long)fVal;
+ }
+
+ pScrl->DoScroll( nNewPos );
+ }
+
+}
+
sal_Bool Window::HandleScrollCommand( const CommandEvent& rCmd,
ScrollBar* pHScrl, ScrollBar* pVScrl )
{
@@ -1152,24 +1184,70 @@ sal_Bool Window::HandleScrollCommand( const CommandEvent& rCmd,
if ( pData && (COMMAND_WHEEL_SCROLL == pData->GetMode()) )
{
- sal_uLong nScrollLines = pData->GetScrollLines();
- long nLines;
- if ( nScrollLines == COMMAND_WHEEL_PAGESCROLL )
+ if (!pData->IsDeltaPixel())
{
- if ( pData->GetDelta() < 0 )
- nLines = -LONG_MAX;
+ sal_uLong nScrollLines = pData->GetScrollLines();
+ long nLines;
+ if ( nScrollLines == COMMAND_WHEEL_PAGESCROLL )
+ {
+ if ( pData->GetDelta() < 0 )
+ nLines = -LONG_MAX;
+ else
+ nLines = LONG_MAX;
+ }
else
- nLines = LONG_MAX;
- }
- else
- nLines = pData->GetNotchDelta() * (long)nScrollLines;
- if ( nLines )
- {
- ImplHandleScroll( NULL,
+ nLines = pData->GetNotchDelta() * (long)nScrollLines;
+ if ( nLines )
+ {
+ ImplHandleScroll( NULL,
0L,
pData->IsHorz() ? pHScrl : pVScrl,
nLines );
- bRet = sal_True;
+ bRet = sal_True;
+ }
+ }
+ else
+ {
+ // Mobile / touch scrolling section
+ const Point & deltaPoint = rCmd.GetMousePosPixel();
+
+ double deltaXInPixels = double(deltaPoint.X());
+ double deltaYInPixels = double(deltaPoint.Y());
+
+ double visSizeX = double(pHScrl->GetVisibleSize());
+ double visSizeY = double(pVScrl->GetVisibleSize());
+
+ Size winSize = this->GetOutputSizePixel();
+
+ double ratioX = deltaXInPixels / double(winSize.getWidth());
+ double ratioY = deltaYInPixels / double(winSize.getHeight());
+
+ long deltaXInLogic = long(visSizeX * ratioX);
+ long deltaYInLogic = long(visSizeY * ratioY);
+
+ // Touch need to work by pixels. Did not apply this to
+ // Android, as android code may require adaptations
+ // to work with this scrolling code
+#ifndef IOS
+ long lineSizeX = pHScrl->GetLineSize();
+ long lineSizeY = pVScrl->GetLineSize();
+
+ deltaXInLogic /= lineSizeX;
+ deltaYInLogic /= lineSizeY;
+#endif
+
+ if ( deltaXInLogic || deltaYInLogic )
+ {
+#ifndef IOS
+ bool isMultiplyByLineSize = true;
+#else
+ bool isMultiplyByLineSize = false;
+#endif
+ lcl_HandleScrollHelper( pHScrl, deltaXInLogic, isMultiplyByLineSize );
+ lcl_HandleScrollHelper( pVScrl, deltaYInLogic, isMultiplyByLineSize );
+
+ bRet = sal_True;
+ }
}
}
}
@@ -1197,32 +1275,7 @@ sal_Bool Window::HandleScrollCommand( const CommandEvent& rCmd,
// -----------------------------------------------------------------------
-static void lcl_HandleScrollHelper( ScrollBar* pScrl, long nN )
-{
- if ( pScrl && nN && pScrl->IsEnabled() && pScrl->IsInputEnabled() && ! pScrl->IsInModalMode() )
- {
- long nNewPos = pScrl->GetThumbPos();
-
- if ( nN == -LONG_MAX )
- nNewPos += pScrl->GetPageSize();
- else if ( nN == LONG_MAX )
- nNewPos -= pScrl->GetPageSize();
- else
- {
- const double fVal = (double)nNewPos - ((double)nN * pScrl->GetLineSize());
-
- if ( fVal < LONG_MIN )
- nNewPos = LONG_MIN;
- else if ( fVal > LONG_MAX )
- nNewPos = LONG_MAX;
- else
- nNewPos = (long)fVal;
- }
-
- pScrl->DoScroll( nNewPos );
- }
-}
// Note that when called for COMMAND_WHEEL above, despite its name,
// pVScrl isn't necessarily the vertical scroll bar. Depending on
@@ -1233,8 +1286,8 @@ static void lcl_HandleScrollHelper( ScrollBar* pScrl, long nN )
void Window::ImplHandleScroll( ScrollBar* pHScrl, long nX,
ScrollBar* pVScrl, long nY )
{
- lcl_HandleScrollHelper( pHScrl, nX );
- lcl_HandleScrollHelper( pVScrl, nY );
+ lcl_HandleScrollHelper( pHScrl, nX, true );
+ lcl_HandleScrollHelper( pVScrl, nY, true );
}
DockingManager* Window::GetDockingManager()
diff --git a/vcl/source/window/winproc.cxx b/vcl/source/window/winproc.cxx
index 052395d..7a93680 100644
--- a/vcl/source/window/winproc.cxx
+++ b/vcl/source/window/winproc.cxx
@@ -35,6 +35,7 @@
#include <vcl/help.hxx>
#include <vcl/dockwin.hxx>
#include <vcl/menu.hxx>
+#include <touch/touch.h>
#include <svdata.hxx>
#include <dbggui.hxx>
@@ -2623,6 +2624,7 @@ long ImplWindowFrameProc( Window* pWindow, SalFrame* /*pFrame*/,
ImplHandleSurroundingTextSelectionChange( pWindow,
pEvt->mnStart,
pEvt->mnEnd );
+ // Fallthrough really intended?
}
case SALEVENT_STARTRECONVERSION:
ImplHandleStartReconversion( pWindow );
@@ -2631,14 +2633,12 @@ long ImplWindowFrameProc( Window* pWindow, SalFrame* /*pFrame*/,
{
ZoomEvent* pZoomEvent = (ZoomEvent*) pEvent;
SalWheelMouseEvent aSalWheelMouseEvent;
-
aSalWheelMouseEvent.mnTime = Time::GetSystemTicks();
aSalWheelMouseEvent.mnX = pZoomEvent->GetCenter().getX();
aSalWheelMouseEvent.mnY = pZoomEvent->GetCenter().getY();
-
- // Pass on the scale as a percentage of current zoom factor
- aSalWheelMouseEvent.mnDelta = (long) (pZoomEvent->GetScale() * 100);
-
+ // Pass on the scale as a percentage * 100 of current zoom factor
+ // so to assure zoom granularity
+ aSalWheelMouseEvent.mnDelta = long(double(pZoomEvent->GetScale()) * double(MOBILE_ZOOM_SCALE_MULTIPLIER));
// Other SalWheelMouseEvent fields ignored when the
// scaleDirectly parameter to ImplHandleWheelEvent() is
// true.
@@ -2649,49 +2649,18 @@ long ImplWindowFrameProc( Window* pWindow, SalFrame* /*pFrame*/,
{
ScrollEvent* pScrollEvent = (ScrollEvent*) pEvent;
SalWheelMouseEvent aSalWheelMouseEvent;
-
aSalWheelMouseEvent.mnTime = Time::GetSystemTicks();
- aSalWheelMouseEvent.mnX = 0; // ???
- aSalWheelMouseEvent.mnY = 0;
-
- // Note that it seems that the delta-is-pixels thing is
- // not actually implemented. The field is just passed on
- // but its value never tested and has no effect?
aSalWheelMouseEvent.mbDeltaIsPixel = sal_True;
-
- // First scroll vertically, then horizontally
- aSalWheelMouseEvent.mnDelta = (long) pScrollEvent->GetYOffset();
-
- // No way to figure out correct amount of "lines" to
- // scroll, and for touch devices (for which this
- // SALEVENBT_EXTERNALSCROLL was introduced) we don't even
- // display the scroll bars. This means that the scroll
- // bars (which still exist as objects, all the scrolling
- // action goes through them) apparently use some dummy
- // default values for range, line size and page size
- // anyway, not related to actual contents of scrolled
- // window. This all is very broken. I really wish the
- // delta-is-pixels feature (which would be exactly what
- // one wants for touch devices) would work.
- aSalWheelMouseEvent.mnScrollLines = aSalWheelMouseEvent.mnDelta;
-
- if (aSalWheelMouseEvent.mnDelta != 0)
+ // event location holds delta values instead
+ aSalWheelMouseEvent.mnX = long(pScrollEvent->GetXOffset());
+ aSalWheelMouseEvent.mnY = long(pScrollEvent->GetYOffset());
+ aSalWheelMouseEvent.mnScrollLines = 0;
+ if (aSalWheelMouseEvent.mnX != 0 || aSalWheelMouseEvent.mnY != 0)
{
- aSalWheelMouseEvent.mnNotchDelta = (aSalWheelMouseEvent.mnDelta < 0) ? -1 : 1;
- aSalWheelMouseEvent.mnCode = 0;
- aSalWheelMouseEvent.mbHorz = sal_False;
nRet = ImplHandleWheelEvent( pWindow, aSalWheelMouseEvent );
}
- aSalWheelMouseEvent.mnDelta = (long) pScrollEvent->GetXOffset();
- if (aSalWheelMouseEvent.mnDelta != 0)
- {
- aSalWheelMouseEvent.mnNotchDelta = (aSalWheelMouseEvent.mnDelta < 0) ? -1 : 1;
- aSalWheelMouseEvent.mnCode = 0;
- aSalWheelMouseEvent.mbHorz = sal_True;
- nRet = ImplHandleWheelEvent( pWindow, aSalWheelMouseEvent );
- }
- }
- break;
+ }
+ break;
case SALEVENT_QUERYCHARPOSITION:
ImplHandleSalQueryCharPosition( pWindow, (SalQueryCharPositionEvent*)pEvent );
break;
More information about the Libreoffice-commits
mailing list