1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <UIKit/UIKit.h>
24 #include <osl/detail/ios-bootstrap.h>
25 #include "ios/iosinst.hxx"
26 #include "headless/svpdummies.hxx"
27 #include "generic/gendata.hxx"
29 #include <basebmp/scanlineformats.hxx>
30 #include <vcl/msgbox.hxx>
33 static int viewWidth
= 1, viewHeight
= 1;
35 class IosSalData
: public SalGenericData
38 IosSalData( SalInstance
*pInstance
) : SalGenericData( SAL_DATA_IOS
, pInstance
) {}
39 virtual void ErrorTrapPush() {}
40 virtual bool ErrorTrapPop( bool ) { return false; }
43 void IosSalInstance::damaged( IosSalFrame */
* frame */
,
44 const basegfx::B2IBox
& rDamageRect
)
46 lo_damaged( CGRectMake( rDamageRect
.getMinX(), rDamageRect
.getMinY(), rDamageRect
.getWidth(), rDamageRect
.getHeight() ));
49 void IosSalInstance::GetWorkArea( Rectangle
& rRect
)
51 rRect
= Rectangle( Point( 0, 0 ),
52 Size( viewWidth
, viewHeight
) );
56 * Try too hard to get a frame, in the absence of anything better to do
58 SalFrame
*IosSalInstance::getFocusFrame() const
60 SalFrame
*pFocus
= SvpSalFrame::GetFocusFrame();
62 const std::list
< SalFrame
* >& rFrames( getFrames() );
63 for( std::list
< SalFrame
* >::const_iterator it
= rFrames
.begin(); it
!= rFrames
.end(); ++it
)
65 SvpSalFrame
*pFrame
= const_cast<SvpSalFrame
*>(static_cast<const SvpSalFrame
*>(*it
));
66 if( pFrame
->IsVisible() )
77 IosSalInstance
*IosSalInstance::getInstance()
81 IosSalData
*pData
= static_cast<IosSalData
*>(ImplGetSVData()->mpSalData
);
84 return static_cast<IosSalInstance
*>(pData
->m_pInstance
);
87 IosSalInstance::IosSalInstance( SalYieldMutex
*pMutex
)
88 : SvpSalInstance( pMutex
)
92 rc
= pthread_cond_init( &m_aRenderCond
, NULL
);
93 SAL_WARN_IF( rc
!= 0, "vcl.ios", "pthread_cond_init failed: " << strerror( rc
) );
95 #if OSL_DEBUG_LEVEL > 0
96 pthread_mutexattr_t mutexattr
;
98 rc
= pthread_mutexattr_init( &mutexattr
);
99 SAL_WARN_IF( rc
!= 0, "vcl.ios", "pthread_mutexattr_init failed: " << strerror( rc
) );
101 rc
= pthread_mutexattr_settype( &mutexattr
, PTHREAD_MUTEX_ERRORCHECK
);
102 SAL_WARN_IF( rc
!= 0, "vcl.ios", "pthread_mutexattr_settype failed: " << strerror( rc
) );
104 rc
= pthread_mutex_init( &m_aRenderMutex
, &mutexattr
);
105 SAL_WARN_IF( rc
!= 0, "vcl.ios", "pthread_mutex_init failed: " << strerror( rc
) );
107 rc
= pthread_mutex_init( &m_aRenderMutex
, NULL
);
108 SAL_WARN_IF( rc
!= 0, "vcl.ios", "pthread_mutex_init failed: " << strerror( rc
) );
112 IosSalInstance::~IosSalInstance()
114 pthread_cond_destroy( &m_aRenderCond
);
115 pthread_mutex_destroy( &m_aRenderMutex
);
120 bool IosSalInstance::AnyInput( sal_uInt16 nType
)
122 if( (nType
& VCL_INPUT_TIMER
) != 0 )
123 return CheckTimeout( false );
125 // Unfortunately there is no way to check for a specific type of
126 // input being queued. That information is too hidden, sigh.
127 return SvpSalInstance::s_pDefaultInstance
->PostedEventsInQueue();
132 class IosSalSystem
: public SvpSalSystem
{
134 IosSalSystem() : SvpSalSystem() {}
135 virtual ~IosSalSystem() {}
136 virtual int ShowNativeDialog( const OUString
& rTitle
,
137 const OUString
& rMessage
,
138 const std::list
< OUString
>& rButtons
,
142 SalSystem
*IosSalInstance::CreateSalSystem()
144 return new IosSalSystem();
147 class IosSalFrame
: public SvpSalFrame
150 IosSalFrame( IosSalInstance
*pInstance
,
152 sal_uLong nSalFrameStyle
,
153 SystemParentData
*pSysParent
)
154 : SvpSalFrame( pInstance
, pParent
, nSalFrameStyle
,
155 true, basebmp::Format::THIRTYTWO_BIT_TC_MASK_RGBA
,
158 enableDamageTracker();
159 if (pParent
== NULL
&& viewWidth
> 1 && viewHeight
> 1)
160 SetPosSize(0, 0, viewWidth
, viewHeight
, SAL_FRAME_POSSIZE_WIDTH
| SAL_FRAME_POSSIZE_HEIGHT
);
163 virtual void GetWorkArea( Rectangle
& rRect
)
165 IosSalInstance::getInstance()->GetWorkArea( rRect
);
168 void ShowFullScreen( sal_Bool
, sal_Int32
)
170 SetPosSize( 0, 0, viewWidth
, viewHeight
,
171 SAL_FRAME_POSSIZE_WIDTH
| SAL_FRAME_POSSIZE_HEIGHT
);
174 virtual void damaged( const basegfx::B2IBox
& rDamageRect
)
176 if (rDamageRect
.isEmpty())
179 IosSalInstance::getInstance()->damaged( this, rDamageRect
);
182 virtual void UpdateSettings( AllSettings
&rSettings
)
184 // Clobber the UI fonts
185 Font
aFont( OUString( "Helvetica" ), Size( 0, 14 ) );
187 StyleSettings aStyleSet
= rSettings
.GetStyleSettings();
188 aStyleSet
.SetAppFont( aFont
);
189 aStyleSet
.SetHelpFont( aFont
);
190 aStyleSet
.SetMenuFont( aFont
);
191 aStyleSet
.SetToolFont( aFont
);
192 aStyleSet
.SetLabelFont( aFont
);
193 aStyleSet
.SetInfoFont( aFont
);
194 aStyleSet
.SetRadioCheckFont( aFont
);
195 aStyleSet
.SetPushButtonFont( aFont
);
196 aStyleSet
.SetFieldFont( aFont
);
197 aStyleSet
.SetIconFont( aFont
);
198 aStyleSet
.SetGroupFont( aFont
);
200 rSettings
.SetStyleSettings( aStyleSet
);
204 SalFrame
*IosSalInstance::CreateChildFrame( SystemParentData
* pParent
, sal_uLong nStyle
)
206 return new IosSalFrame( this, NULL
, nStyle
, pParent
);
209 SalFrame
*IosSalInstance::CreateFrame( SalFrame
* pParent
, sal_uLong nStyle
)
211 return new IosSalFrame( this, pParent
, nStyle
, NULL
);
215 // All the interesting stuff is slaved from the IosSalInstance
216 void InitSalData() {}
217 void DeInitSalData() {}
218 void InitSalMain() {}
220 void SalAbort( const OUString
& rErrorText
, bool bDumpCore
)
224 NSLog(@
"SalAbort: %s", OUStringToOString(rErrorText
, osl_getThreadTextEncoding()).getStr() );
227 const OUString
& SalGetDesktopEnvironment()
229 static OUString
aEnv( "iOS" );
245 // This is our main entry point:
246 SalInstance
*CreateSalInstance()
248 IosSalInstance
* pInstance
= new IosSalInstance( new SalYieldMutex() );
249 new IosSalData( pInstance
);
250 pInstance
->AcquireYieldMutex(1);
254 void DestroySalInstance( SalInstance
*pInst
)
256 pInst
->ReleaseYieldMutex();
260 int IosSalSystem::ShowNativeDialog( const OUString
& rTitle
,
261 const OUString
& rMessage
,
262 const std::list
< OUString
>& rButtons
,
268 if (IosSalInstance::getInstance() != NULL
)
272 ErrorBox
aVclErrBox( NULL
, WB_OK
, rTitle
);
273 aVclErrBox
.SetText( rMessage
);
274 aVclErrBox
.Execute();
280 IMPL_LINK( IosSalInstance
, DisplayConfigurationChanged
, void*, )
282 for( std::list
< SalFrame
* >::const_iterator it
= getFrames().begin();
283 it
!= getFrames().end();
285 (*it
)->Show( sal_False
, sal_False
);
286 (*it
)->CallCallback( SALEVENT_SETTINGSCHANGED
, 0 );
287 (*it
)->SetPosSize(0, 0, viewWidth
, viewHeight
, SAL_FRAME_POSSIZE_WIDTH
| SAL_FRAME_POSSIZE_HEIGHT
);
288 (*it
)->Show( sal_True
, sal_False
);
291 lo_damaged( CGRectMake( 0, 0, viewWidth
, viewHeight
) );
296 void lo_set_view_size(int width
, int height
)
298 int oldWidth
= viewWidth
;
304 // Inform about change in display size (well, just orientation
306 IosSalInstance
*pInstance
= IosSalInstance::getInstance();
308 if ( pInstance
== NULL
)
311 Application::PostUserEvent( LINK( pInstance
, IosSalInstance
, DisplayConfigurationChanged
), NULL
);
315 IMPL_LINK( IosSalInstance
, RenderWindows
, RenderWindowsArg
*, arg
)
319 rc
= pthread_mutex_lock( &m_aRenderMutex
);
320 SAL_WARN_IF( rc
!= 0, "vcl.ios", "pthread_mutex_lock failed: " << strerror( rc
) );
322 for( std::list
< SalFrame
* >::const_iterator it
= getFrames().begin();
323 it
!= getFrames().end();
325 SvpSalFrame
*pFrame
= static_cast<SvpSalFrame
*>(*it
);
326 SalFrameGeometry aGeom
= pFrame
->GetGeometry();
327 CGRect bbox
= CGRectMake( aGeom
.nX
, aGeom
.nY
, aGeom
.nWidth
, aGeom
.nHeight
);
328 if ( pFrame
->IsVisible() &&
329 CGRectIntersectsRect( arg
->rect
, bbox
) ) {
331 const basebmp::BitmapDeviceSharedPtr aDevice
= pFrame
->getDevice();
332 CGDataProviderRef provider
=
333 CGDataProviderCreateWithData( NULL
,
334 aDevice
->getBuffer().get(),
335 aDevice
->getSize().getY() * aDevice
->getScanlineStride(),
338 CGImageCreate( aDevice
->getSize().getX(), aDevice
->getSize().getY(),
339 8, 32, aDevice
->getScanlineStride(),
340 CGColorSpaceCreateDeviceRGB(),
341 kCGImageAlphaNoneSkipLast
,
345 kCGRenderingIntentDefault
);
346 CGContextDrawImage( arg
->context
, bbox
, image
);
352 rc
= pthread_cond_signal( &m_aRenderCond
);
353 SAL_WARN_IF( rc
!= 0, "vcl.ios", "pthread_cond_signal failed:" << strerror( rc
) );
355 rc
= pthread_mutex_unlock( &m_aRenderMutex
);
356 SAL_WARN_IF( rc
!= 0, "vcl.ios", "pthread_mutex_unlock failed: " << strerror( rc
) );
362 void lo_render_windows( CGContextRef context
, CGRect rect
)
365 IosSalInstance
*pInstance
= IosSalInstance::getInstance();
367 if ( pInstance
== NULL
)
370 rc
= pthread_mutex_lock( &pInstance
->m_aRenderMutex
);
372 SAL_WARN( "vcl.ios", "pthread_mutex_lock failed: " << strerror( rc
) );
376 IosSalInstance::RenderWindowsArg arg
= { false, context
, rect
};
377 Application::PostUserEvent( LINK( pInstance
, IosSalInstance
, RenderWindows
), &arg
);
380 rc
= pthread_cond_wait( &pInstance
->m_aRenderCond
, &pInstance
->m_aRenderMutex
);
381 SAL_WARN_IF( rc
!= 0, "vcl.ios", "pthread_cond_wait failed: " << strerror( rc
) );
384 rc
= pthread_mutex_unlock( &pInstance
->m_aRenderMutex
);
385 SAL_WARN_IF( rc
!= 0, "vcl.ios", "pthread_mutex_unlock failed: " << strerror( rc
) );
389 void lo_tap(int x
, int y
)
391 SalFrame
*pFocus
= IosSalInstance::getInstance()->getFocusFrame();
396 aEvent
= MouseEvent(Point(x
, y
), 1, MOUSE_SIMPLECLICK
, MOUSE_LEFT
);
397 nEvent
= VCLEVENT_WINDOW_MOUSEBUTTONDOWN
;
398 Application::PostMouseEvent(nEvent
, pFocus
->GetWindow(), &aEvent
);
400 nEvent
= VCLEVENT_WINDOW_MOUSEBUTTONUP
;
401 Application::PostMouseEvent(nEvent
, pFocus
->GetWindow(), &aEvent
);
406 void lo_pan(int x
, int y
)
408 SalFrame
*pFocus
= IosSalInstance::getInstance()->getFocusFrame();
410 SAL_INFO( "vcl.ios", "scroll: " << "(" << x
<< "," << y
<< ")" );
411 ScrollEvent
aEvent( x
, y
);
412 Application::PostScrollEvent(VCLEVENT_WINDOW_SCROLL
, pFocus
->GetWindow(), &aEvent
);
417 void lo_keyboard_input(int c
)
419 SalFrame
*pFocus
= IosSalInstance::getInstance()->getFocusFrame();
421 KeyEvent
aEvent(c
, c
, 0);
422 Application::PostKeyEvent(VCLEVENT_WINDOW_KEYINPUT
, pFocus
->GetWindow(), &aEvent
);
423 Application::PostKeyEvent(VCLEVENT_WINDOW_KEYUP
, pFocus
->GetWindow(), &aEvent
);
428 void lo_keyboard_did_hide()
430 // Tell LO it has lost "focus", which will cause it to stop
431 // displaying any text insertion cursor etc
433 SalFrame
*pFocus
= IosSalInstance::getInstance()->getFocusFrame();
437 aEvent
= MouseEvent(Point(0, 0), 0, MOUSE_LEAVEWINDOW
, MOUSE_LEFT
);
438 Application::PostMouseEvent(VCLEVENT_WINDOW_MOUSEMOVE
, pFocus
->GetWindow(), &aEvent
);
442 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */