diff options
author | Tor Lillqvist <tml@iki.fi> | 2011-07-31 01:52:37 +0300 |
---|---|---|
committer | Tor Lillqvist <tml@iki.fi> | 2011-07-31 01:52:37 +0300 |
commit | 59a5b4dfb819bdd47394107c0de1ebd8c0573538 (patch) | |
tree | 357c13c2cd2f92d9634e0fb88f543a82a99141de /vcl/ios | |
parent | 704bc46ae43d0386e5762b6a6158c7cef831dd1d (diff) |
More iOS hacking, intermediate commit, certainly not working
Diffstat (limited to 'vcl/ios')
-rw-r--r-- | vcl/ios/source/app/salinst.cxx | 79 | ||||
-rw-r--r-- | vcl/ios/source/app/vcluiapp.mm | 4 | ||||
-rw-r--r-- | vcl/ios/source/dtrans/iOSTransferable.cxx | 193 | ||||
-rw-r--r-- | vcl/ios/source/dtrans/iOSTransferable.hxx | 95 | ||||
-rw-r--r-- | vcl/ios/source/dtrans/ios_clipboard.cxx | 397 | ||||
-rw-r--r-- | vcl/ios/source/dtrans/ios_clipboard.hxx | 182 | ||||
-rw-r--r-- | vcl/ios/source/dtrans/service_entry.cxx | 73 | ||||
-rw-r--r-- | vcl/ios/source/gdi/salbmp.cxx | 915 | ||||
-rw-r--r-- | vcl/ios/source/window/salframe.cxx | 1151 | ||||
-rw-r--r-- | vcl/ios/source/window/salmenu.cxx | 72 | ||||
-rw-r--r-- | vcl/ios/source/window/salobj.cxx | 242 |
11 files changed, 3401 insertions, 2 deletions
diff --git a/vcl/ios/source/app/salinst.cxx b/vcl/ios/source/app/salinst.cxx index b4c944cd31a4..f95930ba0045 100644 --- a/vcl/ios/source/app/salinst.cxx +++ b/vcl/ios/source/app/salinst.cxx @@ -584,6 +584,77 @@ void IosSalInstance::DestroyObject( SalObject* pObject ) delete ( pObject ); } +// ----------------------------------------------------------------------- + +SalPrinter* IosSalInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter ) +{ + return NULL; +} + +// ----------------------------------------------------------------------- + +void IosSalInstance::DestroyPrinter( SalPrinter* pPrinter ) +{ + delete pPrinter; +} + +// ----------------------------------------------------------------------- + +void IosSalInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList ) +{ + // ??? +} + +// ----------------------------------------------------------------------- + +void IosSalInstance::GetPrinterQueueState( SalPrinterQueueInfo* ) +{ + // ??? +} + +// ----------------------------------------------------------------------- + +void IosSalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo ) +{ + delete pInfo; +} + +// ----------------------------------------------------------------------- + +XubString IosSalInstance::GetDefaultPrinter() +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + // ??? + return maDefaultPrinter; +} + +// ----------------------------------------------------------------------- + +SalInfoPrinter* IosSalInstance::CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo, + ImplJobSetup* pSetupData ) +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + SalInfoPrinter* pNewInfoPrinter = NULL; + // ??? + return pNewInfoPrinter; +} + +// ----------------------------------------------------------------------- + +void IosSalInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter ) +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + delete pPrinter; +} + +// ----------------------------------------------------------------------- + SalSystem* IosSalInstance::CreateSystem() { return new IosSalSystem(); @@ -705,6 +776,14 @@ SalSession* IosSalInstance::CreateSalSession() // ----------------------------------------------------------------------- +SalI18NImeStatus* IosSalInstance::CreateI18NImeStatus() +{ + // ??? + return NULL; +} + +// ----------------------------------------------------------------------- + // YieldMutexReleaser YieldMutexReleaser::YieldMutexReleaser() : mnCount( 0 ) { diff --git a/vcl/ios/source/app/vcluiapp.mm b/vcl/ios/source/app/vcluiapp.mm index e40d8a7eb792..d1aa842f6723 100644 --- a/vcl/ios/source/app/vcluiapp.mm +++ b/vcl/ios/source/app/vcluiapp.mm @@ -88,12 +88,12 @@ -(void)addFallbackMenuItem: (UIMenuItem*)pNewItem { - IosSalMenu::addFallbackMenuItem( pNewItem ); + // ??? } -(void)removeFallbackMenuItem: (UIMenuItem*)pItem { - IosSalMenu::removeFallbackMenuItem( pItem ); + // ??? } @end diff --git a/vcl/ios/source/dtrans/iOSTransferable.cxx b/vcl/ios/source/dtrans/iOSTransferable.cxx new file mode 100644 index 000000000000..68e534e676d3 --- /dev/null +++ b/vcl/ios/source/dtrans/iOSTransferable.cxx @@ -0,0 +1,193 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" +#include <sal/types.h> + +#include "iOSTransferable.hxx" + +using namespace std; +using namespace osl; +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::datatransfer; +using namespace com::sun::star::io; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; + +using ::rtl::OUString; + +const Type CPPUTYPE_SEQINT8 = getCppuType((Sequence<sal_Int8>*)0); +const Type CPPUTYPE_OUSTRING = getCppuType((OUString*)0); + +namespace // private +{ + bool isValidFlavor( const DataFlavor& aFlavor ) + { + size_t len = aFlavor.MimeType.getLength(); + Type dtype = aFlavor.DataType; + return ((len > 0) && ((dtype == CPPUTYPE_SEQINT8) || (dtype == CPPUTYPE_OUSTRING))); + } + +} // namespace private + + +iOSTransferable::iOSTransferable(const Reference<XMimeContentTypeFactory> rXMimeCntFactory, + UIPasteboard* pasteboard) : + mrXMimeCntFactory(rXMimeCntFactory), + mPasteboard(pasteboard) +{ + [mPasteboard retain]; + + initClipboardItemList(); +} + + +iOSTransferable::~iOSTransferable() +{ + [mPasteboard release]; +} + + +Any SAL_CALL iOSTransferable::getTransferData( const DataFlavor& aFlavor ) + throw( UnsupportedFlavorException, IOException, RuntimeException ) +{ + if (!isValidFlavor(aFlavor) || !isDataFlavorSupported(aFlavor)) + { + throw UnsupportedFlavorException(OUString(RTL_CONSTASCII_USTRINGPARAM("IosClipboard: Unsupported data flavor")), + static_cast<XTransferable*>(this)); + } + + throw UnsupportedFlavorException(OUString(RTL_CONSTASCII_USTRINGPARAM("IosClipboard: Unsupported data flavor")), + static_cast<XTransferable*>(this)); + // ??? + return Any(); +} + + +bool iOSTransferable::isUnicodeText(const DataFlavor& flavor) +{ + return (flavor.DataType == CPPUTYPE_OUSTRING); +} + + +Sequence< DataFlavor > SAL_CALL iOSTransferable::getTransferDataFlavors( ) + throw( RuntimeException ) +{ + return mFlavorList; +} + + +sal_Bool SAL_CALL iOSTransferable::isDataFlavorSupported(const DataFlavor& aFlavor) + throw( RuntimeException ) +{ + for (sal_Int32 i = 0; i < mFlavorList.getLength(); i++) + if (compareDataFlavors(aFlavor, mFlavorList[i])) + return sal_True; + + return sal_False; +} + + +void iOSTransferable::initClipboardItemList() +{ + NSArray* pboardFormats = [mPasteboard pasteboardTypes]; + + if (pboardFormats == NULL) + { + throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM("IosClipboard: Cannot get clipboard data")), + static_cast<XTransferable*>(this)); + } + + // ??? +} + + +/* Compares two DataFlavors. Returns true if both DataFlavor have the same media type + and the number of parameter and all parameter values do match otherwise false + is returned. + */ +bool iOSTransferable::compareDataFlavors(const DataFlavor& lhs, const DataFlavor& rhs ) +{ + try + { + Reference<XMimeContentType> xLhs(mrXMimeCntFactory->createMimeContentType(lhs.MimeType)); + Reference<XMimeContentType> xRhs(mrXMimeCntFactory->createMimeContentType(rhs.MimeType)); + + if (!xLhs->getFullMediaType().equalsIgnoreAsciiCase(xRhs->getFullMediaType()) || + !cmpAllContentTypeParameter(xLhs, xRhs)) + { + return false; + } + } + catch( IllegalArgumentException& ) + { + OSL_FAIL( "Invalid content type detected" ); + return false; + } + + return true; +} + + +bool iOSTransferable::cmpAllContentTypeParameter(const Reference<XMimeContentType> xLhs, + const Reference<XMimeContentType> xRhs) const +{ + Sequence<OUString> xLhsFlavors = xLhs->getParameters(); + Sequence<OUString> xRhsFlavors = xRhs->getParameters(); + + // Stop here if the number of parameters is different already + if (xLhsFlavors.getLength() != xRhsFlavors.getLength()) + return false; + + try + { + OUString pLhs; + OUString pRhs; + + for (sal_Int32 i = 0; i < xLhsFlavors.getLength(); i++) + { + pLhs = xLhs->getParameterValue(xLhsFlavors[i]); + pRhs = xRhs->getParameterValue(xLhsFlavors[i]); + + if (!pLhs.equalsIgnoreAsciiCase(pRhs)) + { + return false; + } + } + } + catch(IllegalArgumentException&) + { + return false; + } + + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/ios/source/dtrans/iOSTransferable.hxx b/vcl/ios/source/dtrans/iOSTransferable.hxx new file mode 100644 index 000000000000..8744ef1f92bd --- /dev/null +++ b/vcl/ios/source/dtrans/iOSTransferable.hxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _TRANSFERABLE_HXX_ +#define _TRANSFERABLE_HXX_ + +#include <com/sun/star/datatransfer/XTransferable.hpp> +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/datatransfer/XMimeContentTypeFactory.hpp> +#include <com/sun/star/datatransfer/XMimeContentType.hpp> + +#include <premac.h> +#import <UIKit/UIKit.h> +#include <postmac.h> + +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> +#include <vector> + + +class iOSTransferable : public ::cppu::WeakImplHelper1<com::sun::star::datatransfer::XTransferable>, + private ::boost::noncopyable +{ +public: + typedef com::sun::star::uno::Sequence< sal_Int8 > ByteSequence_t; + + explicit iOSTransferable(com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XMimeContentTypeFactory> rXMimeCntFactory, + UIPasteboard* pasteboard); + + virtual ~iOSTransferable(); + + //------------------------------------------------------------------------ + // XTransferable + //------------------------------------------------------------------------ + + virtual ::com::sun::star::uno::Any SAL_CALL getTransferData( const ::com::sun::star::datatransfer::DataFlavor& aFlavor ) + throw( ::com::sun::star::datatransfer::UnsupportedFlavorException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException ); + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::datatransfer::DataFlavor > SAL_CALL getTransferDataFlavors( ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual sal_Bool SAL_CALL isDataFlavorSupported( const ::com::sun::star::datatransfer::DataFlavor& aFlavor ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------ + // Helper functions not part of the XTransferable interface + //------------------------------------------------------------------------ + + void initClipboardItemList(); + + //com::sun::star::uno::Any getClipboardItemData(ClipboardItemPtr_t clipboardItem); + + bool isUnicodeText(const com::sun::star::datatransfer::DataFlavor& flavor); + + bool compareDataFlavors( const com::sun::star::datatransfer::DataFlavor& lhs, + const com::sun::star::datatransfer::DataFlavor& rhs ); + + bool cmpAllContentTypeParameter( const com::sun::star::uno::Reference< com::sun::star::datatransfer::XMimeContentType > xLhs, + const com::sun::star::uno::Reference< com::sun::star::datatransfer::XMimeContentType > xRhs ) const; + +private: + com::sun::star::uno::Sequence< com::sun::star::datatransfer::DataFlavor > mFlavorList; + ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XMimeContentTypeFactory> mrXMimeCntFactory; + UIPasteboard* mPasteboard; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/ios/source/dtrans/ios_clipboard.cxx b/vcl/ios/source/dtrans/ios_clipboard.cxx new file mode 100644 index 000000000000..69f9473737fb --- /dev/null +++ b/vcl/ios/source/dtrans/ios_clipboard.cxx @@ -0,0 +1,397 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" +#include "ios_clipboard.hxx" + +#include "iOSTransferable.hxx" + +#include "vcl/unohelp.hxx" + +#include "comphelper/makesequence.hxx" + +#include <boost/assert.hpp> + +using namespace com::sun::star::datatransfer; +using namespace com::sun::star::datatransfer::clipboard; +using namespace com::sun::star::lang; +using namespace com::sun::star::uno; +using namespace cppu; +using namespace osl; +using namespace std; +using namespace comphelper; + +using ::rtl::OUString; + +@implementation EventListener; + +-(EventListener*)initWithIosClipboard: (IosClipboard*) pcb +{ + self = [super init]; + + if (self) + pIosClipboard = pcb; + + return self; +} + +-(void)pasteboard:(UIPasteboard*)sender provideDataForType:(NSString*)type +{ + if( pIosClipboard ) + pIosClipboard->provideDataForType(sender, type); +} + +-(void)applicationDidBecomeActive:(NSNotification*)aNotification +{ + if( pIosClipboard ) + pIosClipboard->applicationDidBecomeActive(aNotification); +} + +-(void)disposing +{ + pIosClipboard = NULL; +} + +@end + + +OUString clipboard_getImplementationName() +{ + return OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.clipboard.IosClipboard")); +} + +Sequence<OUString> clipboard_getSupportedServiceNames() +{ + return makeSequence(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.clipboard.SystemClipboard"))); +} + + +IosClipboard::IosClipboard(UIPasteboard* pasteboard, bool bUseSystemPasteboard) : + WeakComponentImplHelper4<XClipboardEx, XClipboardNotifier, XFlushableClipboard, XServiceInfo>(m_aMutex), + mIsSystemPasteboard(bUseSystemPasteboard) +{ + Reference<XMultiServiceFactory> mrServiceMgr = vcl::unohelper::GetMultiServiceFactory(); + + mrXMimeCntFactory = Reference<XMimeContentTypeFactory>(mrServiceMgr->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.MimeContentTypeFactory"))), UNO_QUERY); + + if (!mrXMimeCntFactory.is()) + { + throw RuntimeException(OUString( + RTL_CONSTASCII_USTRINGPARAM("IosClipboard: Cannot create com.sun.star.datatransfer.MimeContentTypeFactory")), + static_cast<XClipboardEx*>(this)); + } +#if 0 // ??? + mpDataFlavorMapper = DataFlavorMapperPtr_t(new DataFlavorMapper()); +#endif + if (pasteboard != NULL) + { + mPasteboard = pasteboard; + mIsSystemPasteboard = false; + } + else + { + mPasteboard = bUseSystemPasteboard ? [UIPasteboard generalPasteboard] : + [UIPasteboard pasteboardWithName: @"org.libreoffice.pboard" create: YES]; + + if (mPasteboard == nil) + { + throw RuntimeException(OUString( + RTL_CONSTASCII_USTRINGPARAM("IosClipboard: Cannot create pasteboard")), + static_cast<XClipboardEx*>(this)); + } + } + + [mPasteboard retain]; + + mEventListener = [[EventListener alloc] initWithIosClipboard: this]; + + if (mEventListener == nil) + { + [mPasteboard release]; + + throw RuntimeException( + OUString(RTL_CONSTASCII_USTRINGPARAM("IosClipboard: Cannot create pasteboard change listener")), + static_cast<XClipboardEx*>(this)); + } + + if (mIsSystemPasteboard) + { + NSNotificationCenter* notificationCenter = [NSNotificationCenter defaultCenter]; + + [notificationCenter addObserver: mEventListener + selector: @selector(applicationDidBecomeActive:) + name: @"UIApplicationDidBecomeActiveNotification" + object: [UIApplication sharedApplication]]; + } + + mPasteboardChangeCount = [mPasteboard changeCount]; +} + + +IosClipboard::~IosClipboard() +{ + if (mIsSystemPasteboard) + { + [[NSNotificationCenter defaultCenter] removeObserver: mEventListener]; + } + + [mEventListener disposing]; + [mEventListener release]; + [mPasteboard release]; +} + + +Reference<XTransferable> SAL_CALL IosClipboard::getContents() throw(RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + + // Shortcut: If we are clipboard owner already we don't need + // to drag the data through the system clipboard + if (mXClipboardContent.is()) + { + return mXClipboardContent; + } + + return Reference<XTransferable>(new iOSTransferable(mrXMimeCntFactory, + mPasteboard)); +} + + +void SAL_CALL IosClipboard::setContents(const Reference<XTransferable>& xTransferable, + const Reference<XClipboardOwner>& xClipboardOwner) + throw( RuntimeException ) +{ +#if 0 // ??? + NSArray* types = xTransferable.is() ? + mpDataFlavorMapper->flavorSequenceToTypesArray(xTransferable->getTransferDataFlavors()) : + [NSArray array]; + + ClearableMutexGuard aGuard(m_aMutex); + + Reference<XClipboardOwner> oldOwner(mXClipboardOwner); + mXClipboardOwner = xClipboardOwner; + + Reference<XTransferable> oldContent(mXClipboardContent); + mXClipboardContent = xTransferable; + + mPasteboardChangeCount = [mPasteboard declareTypes: types owner: mEventListener]; + + aGuard.clear(); + + // if we are already the owner of the clipboard + // then fire lost ownership event + if (oldOwner.is()) + { + fireLostClipboardOwnershipEvent(oldOwner, oldContent); + } + + fireClipboardChangedEvent(); +#endif +} + + +OUString SAL_CALL IosClipboard::getName() throw( RuntimeException ) +{ + return OUString(); +} + + +sal_Int8 SAL_CALL IosClipboard::getRenderingCapabilities() throw( RuntimeException ) +{ + return 0; +} + + +void SAL_CALL IosClipboard::addClipboardListener(const Reference< XClipboardListener >& listener) + throw( RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + + if (!listener.is()) + throw IllegalArgumentException(OUString(RTL_CONSTASCII_USTRINGPARAM("empty reference")), + static_cast<XClipboardEx*>(this), 1); + + mClipboardListeners.push_back(listener); +} + + +void SAL_CALL IosClipboard::removeClipboardListener(const Reference< XClipboardListener >& listener) + throw( RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + + if (!listener.is()) + throw IllegalArgumentException(OUString(RTL_CONSTASCII_USTRINGPARAM("empty reference")), + static_cast<XClipboardEx*>(this), 1); + + mClipboardListeners.remove(listener); +} + + +void IosClipboard::applicationDidBecomeActive(NSNotification*) +{ + ClearableMutexGuard aGuard(m_aMutex); + + int currentPboardChgCount = [mPasteboard changeCount]; + + if (currentPboardChgCount != mPasteboardChangeCount) + { + mPasteboardChangeCount = currentPboardChgCount; + + // Clear clipboard content and owner and send lostOwnership + // notification to the old clipboard owner as well as + // ClipboardChanged notification to any clipboard listener + Reference<XClipboardOwner> oldOwner(mXClipboardOwner); + mXClipboardOwner = Reference<XClipboardOwner>(); + + Reference<XTransferable> oldContent(mXClipboardContent); + mXClipboardContent = Reference<XTransferable>(); + + aGuard.clear(); + + if (oldOwner.is()) + { + fireLostClipboardOwnershipEvent(oldOwner, oldContent); + } + + fireClipboardChangedEvent(); + } +} + + +void IosClipboard::fireClipboardChangedEvent() +{ + ClearableMutexGuard aGuard(m_aMutex); + + list<Reference< XClipboardListener > > listeners(mClipboardListeners); + ClipboardEvent aEvent; + + if (listeners.begin() != listeners.end()) + { + aEvent = ClipboardEvent(static_cast<OWeakObject*>(this), getContents()); + } + + aGuard.clear(); + + while (listeners.begin() != listeners.end()) + { + if (listeners.front().is()) + { + try { listeners.front()->changedContents(aEvent); } + catch (RuntimeException&) { } + } + listeners.pop_front(); + } +} + + +void IosClipboard::fireLostClipboardOwnershipEvent(Reference<XClipboardOwner> oldOwner, Reference<XTransferable> oldContent) +{ + BOOST_ASSERT(oldOwner.is()); + + try { oldOwner->lostOwnership(static_cast<XClipboardEx*>(this), oldContent); } + catch(RuntimeException&) { } +} + + +void IosClipboard::provideDataForType(UIPasteboard* sender, NSString* type) +{ +#if 0 // ??? + if( mXClipboardContent.is() ) + { + DataProviderPtr_t dp = mpDataFlavorMapper->getDataProvider(type, mXClipboardContent); + NSData* pBoardData = NULL; + + if (dp.get() != NULL) + { + pBoardData = (NSData*)dp->getSystemData(); + [sender setData: pBoardData forType: type]; + } + } +#endif +} + + +//------------------------------------------------ +// XFlushableClipboard +//------------------------------------------------ + +void SAL_CALL IosClipboard::flushClipboard() + throw(RuntimeException) +{ +#if 0 // ??? + if (mXClipboardContent.is()) + { + Sequence<DataFlavor> flavorList = mXClipboardContent->getTransferDataFlavors(); + sal_uInt32 nFlavors = flavorList.getLength(); + + for (sal_uInt32 i = 0; i < nFlavors; i++) + { + NSString* sysType = mpDataFlavorMapper->openOfficeToSystemFlavor(flavorList[i]); + + if (sysType != NULL) + { + provideDataForType(mPasteboard, sysType); + } + } + mXClipboardContent.clear(); + } +#endif +} + + +UIPasteboard* IosClipboard::getPasteboard() const +{ + return mPasteboard; +} + + +//------------------------------------------------- +// XServiceInfo +//------------------------------------------------- + +OUString SAL_CALL IosClipboard::getImplementationName() throw( RuntimeException ) +{ + return clipboard_getImplementationName(); +} + + +sal_Bool SAL_CALL IosClipboard::supportsService( const OUString& /*ServiceName*/ ) throw( RuntimeException ) +{ + return sal_False; +} + + +Sequence< OUString > SAL_CALL IosClipboard::getSupportedServiceNames() throw( RuntimeException ) +{ + return clipboard_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/ios/source/dtrans/ios_clipboard.hxx b/vcl/ios/source/dtrans/ios_clipboard.hxx new file mode 100644 index 000000000000..3bd3a8923186 --- /dev/null +++ b/vcl/ios/source/dtrans/ios_clipboard.hxx @@ -0,0 +1,182 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _IOS_CLIPBOARD_HXX_ +#define _IOS_CLIPBOARD_HXX_ + +#include <rtl/ustring.hxx> +#include <sal/types.h> +#include <cppuhelper/compbase4.hxx> +#include <com/sun/star/datatransfer/XTransferable.hpp> +#include <com/sun/star/datatransfer/clipboard/XClipboardEx.hpp> +#include <com/sun/star/datatransfer/clipboard/XClipboardOwner.hpp> +#include <com/sun/star/datatransfer/clipboard/XClipboardListener.hpp> +#include <com/sun/star/datatransfer/clipboard/XClipboardNotifier.hpp> +#include <com/sun/star/datatransfer/XMimeContentTypeFactory.hpp> +#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/basemutex.hxx> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> + +#include <boost/utility.hpp> +#include <list> + +#include <premac.h> +#import <UIKit/UIKit.h> +#include <postmac.h> + +class IosClipboard; + +@interface EventListener : NSObject +{ + IosClipboard* pIosClipboard; +} + +// Init the pasteboard change listener with a reference to the OfficeClipboard +// instance +- (EventListener*)initWithIosClipboard: (IosClipboard*) pcb; + +// Promiss resolver function +- (void)pasteboard:(UIPasteboard*)sender provideDataForType:(NSString *)type; + +-(void)applicationDidBecomeActive:(NSNotification*)aNotification; + +-(void)disposing; +@end + + +class IosClipboard : public ::cppu::BaseMutex, + public ::cppu::WeakComponentImplHelper4< com::sun::star::datatransfer::clipboard::XClipboardEx, + com::sun::star::datatransfer::clipboard::XClipboardNotifier, + com::sun::star::datatransfer::clipboard::XFlushableClipboard, + com::sun::star::lang::XServiceInfo >, + private ::boost::noncopyable +{ +public: + /* Create a clipboard instance. + + @param pasteboard + If not equal NULL the instance will be instantiated with the provided + pasteboard reference and 'bUseSystemClipboard' will be ignored + + @param bUseSystemClipboard + If 'pasteboard' is NULL 'bUseSystemClipboard' determines whether the + system clipboard will be created (bUseSystemClipboard == true) or if + the DragPasteboard if bUseSystemClipboard == false + */ + IosClipboard(UIPasteboard* pasteboard = NULL, + bool bUseSystemClipboard = true); + + ~IosClipboard(); + + //------------------------------------------------ + // XClipboard + //------------------------------------------------ + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable > SAL_CALL getContents() + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setContents( const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable >& xTransferable, + const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboardOwner >& xClipboardOwner ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getName() + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------ + // XClipboardEx + //------------------------------------------------ + + virtual sal_Int8 SAL_CALL getRenderingCapabilities() + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------ + // XClipboardNotifier + //------------------------------------------------ + + virtual void SAL_CALL addClipboardListener( const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboardListener >& listener ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL removeClipboardListener( const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboardListener >& listener ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------ + // XFlushableClipboard + //------------------------------------------------ + + virtual void SAL_CALL flushClipboard( ) throw( com::sun::star::uno::RuntimeException ); + + //------------------------------------------------ + // XServiceInfo + //------------------------------------------------ + + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw(::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw(::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() + throw(::com::sun::star::uno::RuntimeException); + + /* Get a reference to the used pasteboard. + */ + UIPasteboard* getPasteboard() const; + + /* Notify the current clipboard owner that he is no longer the clipboard owner. + */ + void fireLostClipboardOwnershipEvent(::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboardOwner> oldOwner, + ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable > oldContent); + + void pasteboardChangedOwner(); + + void provideDataForType(UIPasteboard* sender, NSString* type); + + void applicationDidBecomeActive(NSNotification* aNotification); + +private: + + /* Notify all registered XClipboardListener that the clipboard content + has changed. + */ + void fireClipboardChangedEvent(); + +private: + ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XMimeContentTypeFactory > mrXMimeCntFactory; + ::std::list< ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboardListener > > mClipboardListeners; + ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable > mXClipboardContent; + com::sun::star::uno::Reference< com::sun::star::datatransfer::clipboard::XClipboardOwner > mXClipboardOwner; + bool mIsSystemPasteboard; + UIPasteboard* mPasteboard; + int mPasteboardChangeCount; + EventListener* mEventListener; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/ios/source/dtrans/service_entry.cxx b/vcl/ios/source/dtrans/service_entry.cxx new file mode 100644 index 000000000000..c919dd13aba4 --- /dev/null +++ b/vcl/ios/source/dtrans/service_entry.cxx @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" + +#include "osl/diagnose.h" + +#include "vcl/svapp.hxx" + +#include "ios/saldata.hxx" +#include "ios/salinst.h" + +#include "ios_clipboard.hxx" + +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::cppu; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::datatransfer::clipboard; + + +uno::Reference< XInterface > IosSalInstance::CreateClipboard( const Sequence< Any >& i_rArguments ) +{ + if ( Application::IsHeadlessModeEnabled() ) + return SalInstance::CreateClipboard( i_rArguments ); + + SalData* pSalData = GetSalData(); + if( ! pSalData->mxClipboard.is() ) + pSalData->mxClipboard = uno::Reference<XInterface>(static_cast< XClipboard* >(new IosClipboard()), UNO_QUERY); + return pSalData->mxClipboard; +} + +uno::Reference<XInterface> IosSalInstance::CreateDragSource() +{ + // ??? + return SalInstance::CreateDragSource(); +} + +uno::Reference<XInterface> IosSalInstance::CreateDropTarget() +{ + // ??? + return SalInstance::CreateDropTarget(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/ios/source/gdi/salbmp.cxx b/vcl/ios/source/gdi/salbmp.cxx new file mode 100644 index 000000000000..ea4bdecc811a --- /dev/null +++ b/vcl/ios/source/gdi/salbmp.cxx @@ -0,0 +1,915 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" + +#include <boost/bind.hpp> + +#include "basebmp/scanlineformats.hxx" +#include "basebmp/color.hxx" + +#include "basegfx/vector/b2ivector.hxx" + +#include "tools/color.hxx" + +#include "vcl/bitmap.hxx" // for BitmapSystemData +#include "vcl/salbtype.hxx" + +#include "ios/salbmp.h" +#include "ios/salinst.h" + +#include "bmpfast.hxx" + +// ======================================================================= + +static bool isValidBitCount( sal_uInt16 nBitCount ) +{ + return (nBitCount == 1) || (nBitCount == 4) || (nBitCount == 8) || (nBitCount == 16) || (nBitCount == 24) || (nBitCount == 32); +} + +// ======================================================================= + +IosSalBitmap::IosSalBitmap() +: mxGraphicContext( NULL ) +, mxCachedImage( NULL ) +, mnBits(0) +, mnWidth(0) +, mnHeight(0) +, mnBytesPerRow(0) +{ +} + +// ------------------------------------------------------------------ + +IosSalBitmap::~IosSalBitmap() +{ + Destroy(); +} + +// ------------------------------------------------------------------ + +bool IosSalBitmap::Create( CGLayerRef xLayer, int nBitmapBits, + int nX, int nY, int nWidth, int nHeight, bool /*bMirrorVert*/ ) +{ + DBG_ASSERT( xLayer, "IosSalBitmap::Create() from non-layered context" ); + + // sanitize input parameters + if( nX < 0 ) + nWidth += nX, nX = 0; + if( nY < 0 ) + nHeight += nY, nY = 0; + const CGSize aLayerSize = CGLayerGetSize( xLayer ); + if( nWidth >= (int)aLayerSize.width - nX ) + nWidth = (int)aLayerSize.width - nX; + if( nHeight >= (int)aLayerSize.height - nY ) + nHeight = (int)aLayerSize.height - nY; + if( (nWidth < 0) || (nHeight < 0) ) + nWidth = nHeight = 0; + + // initialize properties + mnWidth = nWidth; + mnHeight = nHeight; + mnBits = nBitmapBits ? nBitmapBits : 32; + + // initialize drawing context + CreateContext(); + + // copy layer content into the bitmap buffer + const CGPoint aSrcPoint = { -nX, -nY }; + ::CGContextDrawLayerAtPoint( mxGraphicContext, aSrcPoint, xLayer ); + return true; +} + +// ------------------------------------------------------------------ + +bool IosSalBitmap::Create( const Size& rSize, sal_uInt16 nBits, const BitmapPalette& rBitmapPalette ) +{ + if( !isValidBitCount( nBits ) ) + return false; + maPalette = rBitmapPalette; + mnBits = nBits; + mnWidth = rSize.Width(); + mnHeight = rSize.Height(); + return AllocateUserData(); +} + +// ------------------------------------------------------------------ + +bool IosSalBitmap::Create( const SalBitmap& rSalBmp ) +{ + return Create( rSalBmp, rSalBmp.GetBitCount() ); +} + +// ------------------------------------------------------------------ + +bool IosSalBitmap::Create( const SalBitmap& rSalBmp, SalGraphics* pGraphics ) +{ + return Create( rSalBmp, pGraphics ? pGraphics->GetBitCount() : rSalBmp.GetBitCount() ); +} + +// ------------------------------------------------------------------ + +bool IosSalBitmap::Create( const SalBitmap& rSalBmp, sal_uInt16 nNewBitCount ) +{ + const IosSalBitmap& rSourceBitmap = static_cast<const IosSalBitmap&>(rSalBmp); + + if( isValidBitCount( nNewBitCount ) && rSourceBitmap.maUserBuffer.get() ) + { + mnBits = nNewBitCount; + mnWidth = rSourceBitmap.mnWidth; + mnHeight = rSourceBitmap.mnHeight; + maPalette = rSourceBitmap.maPalette; + + if( AllocateUserData() ) + { + ConvertBitmapData( mnWidth, mnHeight, mnBits, mnBytesPerRow, maPalette, maUserBuffer.get(), rSourceBitmap.mnBits, rSourceBitmap.mnBytesPerRow, rSourceBitmap.maPalette, rSourceBitmap.maUserBuffer.get() ); + return true; + } + } + return false; +} + +// ------------------------------------------------------------------ + +bool IosSalBitmap::Create( const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmapCanvas > /*xBitmapCanvas*/, Size& /*rSize*/, bool /*bMask*/ ) +{ + return false; +} + +// ------------------------------------------------------------------ + +void IosSalBitmap::Destroy() +{ + DestroyContext(); + maUserBuffer.reset(); +} + +// ------------------------------------------------------------------ + +void IosSalBitmap::DestroyContext() +{ + CGImageRelease( mxCachedImage ); + mxCachedImage = NULL; + + if( mxGraphicContext ) + { + CGContextRelease( mxGraphicContext ); + mxGraphicContext = NULL; + maContextBuffer.reset(); + } +} + +// ------------------------------------------------------------------ + +bool IosSalBitmap::CreateContext() +{ + DestroyContext(); + + // prepare graphics context + // convert image from user input if available + const bool bSkipConversion = !maUserBuffer; + if( bSkipConversion ) + AllocateUserData(); + + // default to RGBA color space + CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace; + CGBitmapInfo aCGBmpInfo = kCGImageAlphaNoneSkipFirst; + + // convert data into something accepted by CGBitmapContextCreate() + size_t bitsPerComponent = (mnBits == 16) ? 5 : 8; + sal_uInt32 nContextBytesPerRow = mnBytesPerRow; + if( (mnBits == 16) || (mnBits == 32) ) + { + // no conversion needed for truecolor + maContextBuffer = maUserBuffer; + } + else if( (mnBits == 8) && maPalette.IsGreyPalette() ) + { + // no conversion needed for grayscale + maContextBuffer = maUserBuffer; + aCGColorSpace = GetSalData()->mxGraySpace; + aCGBmpInfo = kCGImageAlphaNone; + bitsPerComponent = mnBits; + } + // TODO: is special handling for 1bit input buffers worth it? + else + { + // convert user data to 32 bit + nContextBytesPerRow = mnWidth << 2; + try + { + maContextBuffer.reset( new sal_uInt8[ mnHeight * nContextBytesPerRow ] ); + + if( !bSkipConversion ) + ConvertBitmapData( mnWidth, mnHeight, + 32, nContextBytesPerRow, maPalette, maContextBuffer.get(), + mnBits, mnBytesPerRow, maPalette, maUserBuffer.get() ); + } + catch( std::bad_alloc ) + { + mxGraphicContext = 0; + } + } + + if( maContextBuffer.get() ) + { + mxGraphicContext = ::CGBitmapContextCreate( maContextBuffer.get(), mnWidth, mnHeight, + bitsPerComponent, nContextBytesPerRow, aCGColorSpace, aCGBmpInfo ); + } + + if( !mxGraphicContext ) + maContextBuffer.reset(); + + return mxGraphicContext != NULL; +} + +// ------------------------------------------------------------------ + +bool IosSalBitmap::AllocateUserData() +{ + Destroy(); + + if( mnWidth && mnHeight ) + { + mnBytesPerRow = 0; + + switch( mnBits ) + { + case 1: mnBytesPerRow = (mnWidth + 7) >> 3; break; + case 4: mnBytesPerRow = (mnWidth + 1) >> 1; break; + case 8: mnBytesPerRow = mnWidth; break; + case 16: mnBytesPerRow = mnWidth << 1; break; + case 24: mnBytesPerRow = (mnWidth << 1) + mnWidth; break; + case 32: mnBytesPerRow = mnWidth << 2; break; + default: + OSL_FAIL("vcl::IosSalBitmap::AllocateUserData(), illegal bitcount!"); + } + } + + try + { + if( mnBytesPerRow ) + maUserBuffer.reset( new sal_uInt8[mnBytesPerRow * mnHeight] ); + } + catch( const std::bad_alloc& ) + { + OSL_FAIL( "vcl::IosSalBitmap::AllocateUserData: bad alloc" ); + maUserBuffer.reset( NULL ); + mnBytesPerRow = 0; + } + + return maUserBuffer.get() != 0; +} + +// ------------------------------------------------------------------ + +class ImplPixelFormat +{ +protected: + sal_uInt8* pData; +public: + static ImplPixelFormat* GetFormat( sal_uInt16 nBits, const BitmapPalette& rPalette ); + + virtual void StartLine( sal_uInt8* pLine ) { pData = pLine; } + virtual void SkipPixel( sal_uInt32 nPixel ) = 0; + virtual ColorData ReadPixel() = 0; + virtual void WritePixel( ColorData nColor ) = 0; +}; + +class ImplPixelFormat32 : public ImplPixelFormat +// currently ARGB-format for 32bit depth +{ +public: + virtual void SkipPixel( sal_uInt32 nPixel ) + { + pData += nPixel << 2; + } + virtual ColorData ReadPixel() + { + const ColorData c = RGB_COLORDATA( pData[1], pData[2], pData[3] ); + pData += 4; + return c; + } + virtual void WritePixel( ColorData nColor ) + { + *pData++ = 0; + *pData++ = COLORDATA_RED( nColor ); + *pData++ = COLORDATA_GREEN( nColor ); + *pData++ = COLORDATA_BLUE( nColor ); + } +}; + +class ImplPixelFormat24 : public ImplPixelFormat +// currently BGR-format for 24bit depth +{ +public: + virtual void SkipPixel( sal_uInt32 nPixel ) + { + pData += (nPixel << 1) + nPixel; + } + virtual ColorData ReadPixel() + { + const ColorData c = RGB_COLORDATA( pData[2], pData[1], pData[0] ); + pData += 3; + return c; + } + virtual void WritePixel( ColorData nColor ) + { + *pData++ = COLORDATA_BLUE( nColor ); + *pData++ = COLORDATA_GREEN( nColor ); + *pData++ = COLORDATA_RED( nColor ); + } +}; + +class ImplPixelFormat16 : public ImplPixelFormat +// currently R5G6B5-format for 16bit depth +{ +protected: + sal_uInt16* pData16; +public: + + virtual void StartLine( sal_uInt8* pLine ) + { + pData16 = (sal_uInt16*)pLine; + } + virtual void SkipPixel( sal_uInt32 nPixel ) + { + pData += nPixel; + } + virtual ColorData ReadPixel() + { + const ColorData c = RGB_COLORDATA( (*pData & 0x7c00) >> 7, (*pData & 0x03e0) >> 2 , (*pData & 0x001f) << 3 ); + pData++; + return c; + } + virtual void WritePixel( ColorData nColor ) + { + *pData++ = ((COLORDATA_RED( nColor ) & 0xf8 ) << 7 ) || + ((COLORDATA_GREEN( nColor ) & 0xf8 ) << 2 ) || + ((COLORDATA_BLUE( nColor ) & 0xf8 ) >> 3 ); + } +}; + +class ImplPixelFormat8 : public ImplPixelFormat +{ +private: + const BitmapPalette& mrPalette; + +public: + ImplPixelFormat8( const BitmapPalette& rPalette ) + : mrPalette( rPalette ) + { + } + virtual void SkipPixel( sal_uInt32 nPixel ) + { + pData += nPixel; + } + virtual ColorData ReadPixel() + { + return mrPalette[ *pData++ ].operator Color().GetColor(); + } + virtual void WritePixel( ColorData nColor ) + { + const BitmapColor aColor( COLORDATA_RED( nColor ), COLORDATA_GREEN( nColor ), COLORDATA_BLUE( nColor ) ); + *pData++ = static_cast< sal_uInt8 >( mrPalette.GetBestIndex( aColor ) ); + } +}; + +class ImplPixelFormat4 : public ImplPixelFormat +{ +private: + const BitmapPalette& mrPalette; + sal_uInt32 mnX; + sal_uInt32 mnShift; + +public: + ImplPixelFormat4( const BitmapPalette& rPalette ) + : mrPalette( rPalette ) + { + } + virtual void SkipPixel( sal_uInt32 nPixel ) + { + mnX += nPixel; + if( (nPixel & 1) ) + mnShift ^= 4; + } + virtual void StartLine( sal_uInt8* pLine ) + { + pData = pLine; + mnX = 0; + mnShift = 4; + } + virtual ColorData ReadPixel() + { + const BitmapColor& rColor = mrPalette[( pData[mnX >> 1] >> mnShift) & 0x0f]; + mnX++; + mnShift ^= 4; + return rColor.operator Color().GetColor(); + } + virtual void WritePixel( ColorData nColor ) + { + const BitmapColor aColor( COLORDATA_RED( nColor ), COLORDATA_GREEN( nColor ), COLORDATA_BLUE( nColor ) ); + pData[mnX>>1] &= (0xf0 >> mnShift); + pData[mnX>>1] |= (static_cast< sal_uInt8 >( mrPalette.GetBestIndex( aColor ) ) & 0x0f); + mnX++; + mnShift ^= 4; + } +}; + +class ImplPixelFormat1 : public ImplPixelFormat +{ +private: + const BitmapPalette& mrPalette; + sal_uInt32 mnX; + +public: + ImplPixelFormat1( const BitmapPalette& rPalette ) + : mrPalette( rPalette ) + { + } + virtual void SkipPixel( sal_uInt32 nPixel ) + { + mnX += nPixel; + } + virtual void StartLine( sal_uInt8* pLine ) + { + pData = pLine; + mnX = 0; + } + virtual ColorData ReadPixel() + { + const BitmapColor& rColor = mrPalette[ (pData[mnX >> 3 ] >> ( 7 - ( mnX & 7 ) )) & 1]; + mnX++; + return rColor.operator Color().GetColor(); + } + virtual void WritePixel( ColorData nColor ) + { + const BitmapColor aColor( COLORDATA_RED( nColor ), COLORDATA_GREEN( nColor ), COLORDATA_BLUE( nColor ) ); + if( mrPalette.GetBestIndex( aColor ) & 1 ) + pData[ mnX >> 3 ] |= 1 << ( 7 - ( mnX & 7 ) ); + else + pData[ mnX >> 3 ] &= ~( 1 << ( 7 - ( mnX & 7 ) ) ); + mnX++; + } +}; + +ImplPixelFormat* ImplPixelFormat::GetFormat( sal_uInt16 nBits, const BitmapPalette& rPalette ) +{ + switch( nBits ) + { + case 1: return new ImplPixelFormat1( rPalette ); + case 4: return new ImplPixelFormat4( rPalette ); + case 8: return new ImplPixelFormat8( rPalette ); + case 16: return new ImplPixelFormat16; + case 24: return new ImplPixelFormat24; + case 32: return new ImplPixelFormat32; + } + + return 0; +} + +void IosSalBitmap::ConvertBitmapData( sal_uInt32 nWidth, sal_uInt32 nHeight, + sal_uInt16 nDestBits, sal_uInt32 nDestBytesPerRow, const BitmapPalette& rDestPalette, sal_uInt8* pDestData, + sal_uInt16 nSrcBits, sal_uInt32 nSrcBytesPerRow, const BitmapPalette& rSrcPalette, sal_uInt8* pSrcData ) + +{ + if( (nDestBytesPerRow == nSrcBytesPerRow) && (nDestBits == nSrcBits) && ((nSrcBits != 8) || (rDestPalette.operator==( rSrcPalette ))) ) + { + // simple case, same format, so just copy + memcpy( pDestData, pSrcData, nHeight * nDestBytesPerRow ); + return; + } + + // try accelerated conversion if possible + // TODO: are other truecolor conversions except BGR->ARGB worth it? + bool bConverted = false; + if( (nSrcBits == 24) && (nDestBits == 32) ) + { + // TODO: extend bmpfast.cxx with a method that can be directly used here + BitmapBuffer aSrcBuf; + aSrcBuf.mnFormat = BMP_FORMAT_24BIT_TC_BGR; + aSrcBuf.mpBits = pSrcData; + aSrcBuf.mnBitCount = nSrcBits; + aSrcBuf.mnScanlineSize = nSrcBytesPerRow; + BitmapBuffer aDstBuf; + aDstBuf.mnFormat = BMP_FORMAT_32BIT_TC_ARGB; + aDstBuf.mpBits = pDestData; + aSrcBuf.mnBitCount = nDestBits; + aDstBuf.mnScanlineSize = nDestBytesPerRow; + + aSrcBuf.mnWidth = aDstBuf.mnWidth = nWidth; + aSrcBuf.mnHeight = aDstBuf.mnHeight = nHeight; + + SalTwoRect aTwoRects; + aTwoRects.mnSrcX = aTwoRects.mnDestX = 0; + aTwoRects.mnSrcY = aTwoRects.mnDestY = 0; + aTwoRects.mnSrcWidth = aTwoRects.mnDestWidth = mnWidth; + aTwoRects.mnSrcHeight = aTwoRects.mnDestHeight = mnHeight; + bConverted = ::ImplFastBitmapConversion( aDstBuf, aSrcBuf, aTwoRects ); + } + + if( !bConverted ) + { + // TODO: this implementation is for clarety, not for speed + + ImplPixelFormat* pD = ImplPixelFormat::GetFormat( nDestBits, rDestPalette ); + ImplPixelFormat* pS = ImplPixelFormat::GetFormat( nSrcBits, rSrcPalette ); + + if( pD && pS ) + { + sal_uInt32 nY = nHeight; + while( nY-- ) + { + pD->StartLine( pDestData ); + pS->StartLine( pSrcData ); + + sal_uInt32 nX = nWidth; + while( nX-- ) + pD->WritePixel( pS->ReadPixel() ); + + pSrcData += nSrcBytesPerRow; + pDestData += nDestBytesPerRow; + } + } + delete pS; + delete pD; + } +} + +// ------------------------------------------------------------------ + +Size IosSalBitmap::GetSize() const +{ + return Size( mnWidth, mnHeight ); +} + +// ------------------------------------------------------------------ + +sal_uInt16 IosSalBitmap::GetBitCount() const +{ + return mnBits; +} + +// ------------------------------------------------------------------ + +static struct pal_entry +{ + sal_uInt8 mnRed; + sal_uInt8 mnGreen; + sal_uInt8 mnBlue; +} +const aImplSalSysPalEntryAry[ 16 ] = +{ +{ 0, 0, 0 }, +{ 0, 0, 0x80 }, +{ 0, 0x80, 0 }, +{ 0, 0x80, 0x80 }, +{ 0x80, 0, 0 }, +{ 0x80, 0, 0x80 }, +{ 0x80, 0x80, 0 }, +{ 0x80, 0x80, 0x80 }, +{ 0xC0, 0xC0, 0xC0 }, +{ 0, 0, 0xFF }, +{ 0, 0xFF, 0 }, +{ 0, 0xFF, 0xFF }, +{ 0xFF, 0, 0 }, +{ 0xFF, 0, 0xFF }, +{ 0xFF, 0xFF, 0 }, +{ 0xFF, 0xFF, 0xFF } +}; + +const BitmapPalette& GetDefaultPalette( int mnBits, bool bMonochrome ) +{ + if( bMonochrome ) + return Bitmap::GetGreyPalette( 1U << mnBits ); + + // at this point we should provide some kind of default palette + // since all other platforms do so, too. + static bool bDefPalInit = false; + static BitmapPalette aDefPalette256; + static BitmapPalette aDefPalette16; + static BitmapPalette aDefPalette2; + if( ! bDefPalInit ) + { + bDefPalInit = true; + aDefPalette256.SetEntryCount( 256 ); + aDefPalette16.SetEntryCount( 16 ); + aDefPalette2.SetEntryCount( 2 ); + + // Standard colors + unsigned int i; + for( i = 0; i < 16; i++ ) + { + aDefPalette16[i] = + aDefPalette256[i] = BitmapColor( aImplSalSysPalEntryAry[i].mnRed, + aImplSalSysPalEntryAry[i].mnGreen, + aImplSalSysPalEntryAry[i].mnBlue ); + } + + aDefPalette2[0] = BitmapColor( 0, 0, 0 ); + aDefPalette2[1] = BitmapColor( 0xff, 0xff, 0xff ); + + // own palette (6/6/6) + const int DITHER_PAL_STEPS = 6; + const sal_uInt8 DITHER_PAL_DELTA = 51; + int nB, nG, nR; + sal_uInt8 nRed, nGreen, nBlue; + for( nB=0, nBlue=0; nB < DITHER_PAL_STEPS; nB++, nBlue += DITHER_PAL_DELTA ) + { + for( nG=0, nGreen=0; nG < DITHER_PAL_STEPS; nG++, nGreen += DITHER_PAL_DELTA ) + { + for( nR=0, nRed=0; nR < DITHER_PAL_STEPS; nR++, nRed += DITHER_PAL_DELTA ) + { + aDefPalette256[ i ] = BitmapColor( nRed, nGreen, nBlue ); + i++; + } + } + } + } + + // now fill in appropriate palette + switch( mnBits ) + { + case 1: return aDefPalette2; + case 4: return aDefPalette16; + case 8: return aDefPalette256; + default: break; + } + + const static BitmapPalette aEmptyPalette; + return aEmptyPalette; +} + +BitmapBuffer* IosSalBitmap::AcquireBuffer( bool /*bReadOnly*/ ) +{ + if( !maUserBuffer.get() ) +// || maContextBuffer.get() && (maUserBuffer.get() != maContextBuffer.get()) ) + { + fprintf(stderr,"ASB::Acq(%dx%d,d=%d)\n",mnWidth,mnHeight,mnBits); + // TODO: AllocateUserData(); + return NULL; + } + + BitmapBuffer* pBuffer = new BitmapBuffer; + pBuffer->mnWidth = mnWidth; + pBuffer->mnHeight = mnHeight; + pBuffer->maPalette = maPalette; + pBuffer->mnScanlineSize = mnBytesPerRow; + pBuffer->mpBits = maUserBuffer.get(); + pBuffer->mnBitCount = mnBits; + switch( mnBits ) + { + case 1: pBuffer->mnFormat = BMP_FORMAT_1BIT_MSB_PAL; break; + case 4: pBuffer->mnFormat = BMP_FORMAT_4BIT_MSN_PAL; break; + case 8: pBuffer->mnFormat = BMP_FORMAT_8BIT_PAL; break; + case 16: pBuffer->mnFormat = BMP_FORMAT_16BIT_TC_MSB_MASK; + pBuffer->maColorMask = ColorMask( k16BitRedColorMask, k16BitGreenColorMask, k16BitBlueColorMask ); + break; + case 24: pBuffer->mnFormat = BMP_FORMAT_24BIT_TC_BGR; break; + case 32: pBuffer->mnFormat = BMP_FORMAT_32BIT_TC_ARGB; + pBuffer->maColorMask = ColorMask( k32BitRedColorMask, k32BitGreenColorMask, k32BitBlueColorMask ); + break; + } + pBuffer->mnFormat |= BMP_FORMAT_BOTTOM_UP; + + // some BitmapBuffer users depend on a complete palette + if( (mnBits <= 8) && !maPalette ) + pBuffer->maPalette = GetDefaultPalette( mnBits, true ); + + return pBuffer; +} + +// ------------------------------------------------------------------ + +void IosSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly ) +{ + // invalidate graphic context if we have different data + if( !bReadOnly ) + { + maPalette = pBuffer->maPalette; + if( mxGraphicContext ) + DestroyContext(); + } + + delete pBuffer; +} + +// ------------------------------------------------------------------ + +CGImageRef IosSalBitmap::CreateCroppedImage( int nX, int nY, int nNewWidth, int nNewHeight ) const +{ + if( !mxCachedImage ) + { + if( !mxGraphicContext ) + if( !const_cast<IosSalBitmap*>(this)->CreateContext() ) + return NULL; + + mxCachedImage = CGBitmapContextCreateImage( mxGraphicContext ); + } + + CGImageRef xCroppedImage = NULL; + // short circuit if there is nothing to crop + if( !nX && !nY && (mnWidth == nNewWidth) && (mnHeight == nNewHeight) ) + { + xCroppedImage = mxCachedImage; + CFRetain( xCroppedImage ); + } + else + { + nY = mnHeight - (nY + nNewHeight); // adjust for y-mirrored context + const CGRect aCropRect = {{nX, nY}, {nNewWidth, nNewHeight}}; + xCroppedImage = CGImageCreateWithImageInRect( mxCachedImage, aCropRect ); + } + + return xCroppedImage; +} + +// ------------------------------------------------------------------ + +static void CFRTLFree(void* /*info*/, const void* data, size_t /*size*/) +{ + rtl_freeMemory( const_cast<void*>(data) ); +} + +CGImageRef IosSalBitmap::CreateWithMask( const IosSalBitmap& rMask, + int nX, int nY, int nWidth, int nHeight ) const +{ + CGImageRef xImage( CreateCroppedImage( nX, nY, nWidth, nHeight ) ); + if( !xImage ) + return NULL; + + CGImageRef xMask = rMask.CreateCroppedImage( nX, nY, nWidth, nHeight ); + if( !xMask ) + return xImage; + + // CGImageCreateWithMask() only likes masks or greyscale images => convert if needed + // TODO: isolate in an extra method? + if( !CGImageIsMask(xMask) || (CGImageGetColorSpace(xMask) != GetSalData()->mxGraySpace) ) + { + const CGRect xImageRect=CGRectMake( 0, 0, nWidth, nHeight );//the rect has no offset + + // create the alpha mask image fitting our image + // TODO: is caching the full mask or the subimage mask worth it? + int nMaskBytesPerRow = ((nWidth + 3) & ~3); + void* pMaskMem = rtl_allocateMemory( nMaskBytesPerRow * nHeight ); + CGContextRef xMaskContext = CGBitmapContextCreate( pMaskMem, + nWidth, nHeight, 8, nMaskBytesPerRow, GetSalData()->mxGraySpace, kCGImageAlphaNone ); + CGContextDrawImage( xMaskContext, xImageRect, xMask ); + CFRelease( xMask ); + CGDataProviderRef xDataProvider( CGDataProviderCreateWithData( NULL, + pMaskMem, nHeight * nMaskBytesPerRow, &CFRTLFree ) ); + static const float* pDecode = NULL; + xMask = CGImageMaskCreate( nWidth, nHeight, 8, 8, nMaskBytesPerRow, xDataProvider, pDecode, false ); + CFRelease( xDataProvider ); + CFRelease( xMaskContext ); + } + + if( !xMask ) + return xImage; + + // combine image and alpha mask + CGImageRef xMaskedImage = CGImageCreateWithMask( xImage, xMask ); + CFRelease( xMask ); + CFRelease( xImage ); + return xMaskedImage; +} + +// ------------------------------------------------------------------ + +/** creates an image from the given rectangle, replacing all black pixels with nMaskColor and make all other full transparent */ +CGImageRef IosSalBitmap::CreateColorMask( int nX, int nY, int nWidth, int nHeight, SalColor nMaskColor ) const +{ + CGImageRef xMask = 0; + if( maUserBuffer.get() && (nX + nWidth <= mnWidth) && (nY + nHeight <= mnHeight) ) + { + const sal_uInt32 nDestBytesPerRow = nWidth << 2; + sal_uInt32* pMaskBuffer = static_cast<sal_uInt32*>( rtl_allocateMemory( nHeight * nDestBytesPerRow ) ); + sal_uInt32* pDest = pMaskBuffer; + + ImplPixelFormat* pSourcePixels = ImplPixelFormat::GetFormat( mnBits, maPalette ); + + if( pMaskBuffer && pSourcePixels ) + { + sal_uInt32 nColor; + reinterpret_cast<sal_uInt8*>(&nColor)[0] = 0xff; + reinterpret_cast<sal_uInt8*>(&nColor)[1] = SALCOLOR_RED( nMaskColor ); + reinterpret_cast<sal_uInt8*>(&nColor)[2] = SALCOLOR_GREEN( nMaskColor ); + reinterpret_cast<sal_uInt8*>(&nColor)[3] = SALCOLOR_BLUE( nMaskColor ); + + sal_uInt8* pSource = maUserBuffer.get(); + if( nY ) + pSource += nY * mnBytesPerRow; + + int y = nHeight; + while( y-- ) + { + pSourcePixels->StartLine( pSource ); + pSourcePixels->SkipPixel(nX); + sal_uInt32 x = nWidth; + while( x-- ) + { + *pDest++ = ( pSourcePixels->ReadPixel() == 0 ) ? nColor : 0; + } + pSource += mnBytesPerRow; + } + + CGDataProviderRef xDataProvider( CGDataProviderCreateWithData(NULL, pMaskBuffer, nHeight * nDestBytesPerRow, &CFRTLFree) ); + xMask = CGImageCreate(nWidth, nHeight, 8, 32, nDestBytesPerRow, GetSalData()->mxRGBSpace, kCGImageAlphaPremultipliedFirst, xDataProvider, NULL, true, kCGRenderingIntentDefault); + CFRelease(xDataProvider); + } + else + { + free(pMaskBuffer); + } + + delete pSourcePixels; + } + return xMask; +} + +// ======================================================================= + +/** IosSalBitmap::GetSystemData Get platform native image data from existing image + * + * @param rData struct BitmapSystemData, defined in vcl/inc/bitmap.hxx + * @return true if successful +**/ +bool IosSalBitmap::GetSystemData( BitmapSystemData& rData ) +{ + bool bRet = false; + + if( !mxGraphicContext ) + CreateContext(); + + if ( mxGraphicContext ) + { + bRet = true; + + if ((CGBitmapContextGetBitsPerPixel(mxGraphicContext) == 32) && + (CGBitmapContextGetBitmapInfo(mxGraphicContext) & kCGBitmapByteOrderMask) != kCGBitmapByteOrder32Host) { + /** + * We need to hack things because VCL does not use kCGBitmapByteOrder32Host, while Cairo requires it. + */ + OSL_TRACE("IosSalBitmap::%s(): kCGBitmapByteOrder32Host not found => inserting it.",__func__); + + CGImageRef xImage = CGBitmapContextCreateImage (mxGraphicContext); + + // re-create the context with single change: include kCGBitmapByteOrder32Host flag. + CGContextRef mxGraphicContextNew = CGBitmapContextCreate( CGBitmapContextGetData(mxGraphicContext), + CGBitmapContextGetWidth(mxGraphicContext), + CGBitmapContextGetHeight(mxGraphicContext), + CGBitmapContextGetBitsPerComponent(mxGraphicContext), + CGBitmapContextGetBytesPerRow(mxGraphicContext), + CGBitmapContextGetColorSpace(mxGraphicContext), + CGBitmapContextGetBitmapInfo(mxGraphicContext) | kCGBitmapByteOrder32Host); + CFRelease(mxGraphicContext); + + // Needs to be flipped + CGContextSaveGState( mxGraphicContextNew ); + CGContextTranslateCTM (mxGraphicContextNew, 0, CGBitmapContextGetHeight(mxGraphicContextNew)); + CGContextScaleCTM (mxGraphicContextNew, 1.0, -1.0); + + CGContextDrawImage(mxGraphicContextNew, CGRectMake( 0, 0, CGImageGetWidth(xImage), CGImageGetHeight(xImage)), xImage); + + // Flip back + CGContextRestoreGState( mxGraphicContextNew ); + + CGImageRelease( xImage ); + mxGraphicContext = mxGraphicContextNew; + } + + rData.rImageContext = (void *) mxGraphicContext; + rData.mnWidth = mnWidth; + rData.mnHeight = mnHeight; + } + + return bRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/ios/source/window/salframe.cxx b/vcl/ios/source/window/salframe.cxx new file mode 100644 index 000000000000..e18d242c59b4 --- /dev/null +++ b/vcl/ios/source/window/salframe.cxx @@ -0,0 +1,1151 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************ + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" + +#include <string> + +#include "rtl/ustrbuf.hxx" + +#include "osl/file.h" + +#include "vcl/svapp.hxx" +#include "vcl/window.hxx" +#include "vcl/timer.hxx" + +#include "ios/saldata.hxx" +#include "ios/salgdi.h" +#include "ios/salframe.h" +#include "ios/salmenu.h" +#include "ios/saltimer.h" +#include "ios/salinst.h" +#include "ios/salframeview.h" + +#include "salwtype.hxx" + +using namespace std; + +// ======================================================================= + +IosSalFrame* IosSalFrame::s_pCaptureFrame = NULL; + +// ======================================================================= + +IosSalFrame::IosSalFrame( SalFrame* pParent, sal_uLong salFrameStyle ) : + mpWindow(nil), + mpView(nil), + mpGraphics(NULL), + mpParent(NULL), + mnMinWidth(0), + mnMinHeight(0), + mnMaxWidth(0), + mnMaxHeight(0), + mbGraphics(false), + mbShown(false), + mbInitShow(true), + mbPresentation( false ), + mnStyle( salFrameStyle ), + mnStyleMask( 0 ), + mnLastEventTime( 0 ), + mnLastModifierFlags( 0 ), + mpMenu( NULL ), + mnExtStyle( 0 ), + mePointerStyle( POINTER_ARROW ), + mrClippingPath( 0 ), + mnICOptions( 0 ) +{ + maSysData.nSize = sizeof( SystemEnvData ); + + mpParent = dynamic_cast<IosSalFrame*>(pParent); + + initWindowAndView(); + + SalData* pSalData = GetSalData(); + pSalData->maFrames.push_front( this ); + pSalData->maFrameCheck.insert( this ); +} + +// ----------------------------------------------------------------------- + +IosSalFrame::~IosSalFrame() +{ + // cleanup clipping stuff + ResetClipRegion(); + + SalData* pSalData = GetSalData(); + pSalData->maFrames.remove( this ); + pSalData->maFrameCheck.erase( this ); + + DBG_ASSERT( this != s_pCaptureFrame, "capture frame destroyed" ); + if( this == s_pCaptureFrame ) + s_pCaptureFrame = NULL; + + if ( mpGraphics ) + delete mpGraphics; + + if ( mpView ) { + [mpView release]; + } + if ( mpWindow ) + [mpWindow release]; +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::initWindowAndView() +{ + // initialize mirroring parameters + // FIXME: screens changing + UIScreen * pScreen = [mpWindow screen]; + if( pScreen == nil ) + pScreen = [UIScreen mainScreen]; + maScreenRect = [pScreen applicationFrame]; + + // calculate some default geometry + CGRect aVisibleRect = [pScreen applicationFrame]; + CocoaTouchToVCL( aVisibleRect ); + + maGeometry.nX = static_cast<int>(aVisibleRect.origin.x + aVisibleRect.size.width / 10); + maGeometry.nY = static_cast<int>(aVisibleRect.origin.y + aVisibleRect.size.height / 10); + maGeometry.nWidth = static_cast<unsigned int>(aVisibleRect.size.width * 0.8); + maGeometry.nHeight = static_cast<unsigned int>(aVisibleRect.size.height * 0.8); + + // calculate style mask + if( (mnStyle & SAL_FRAME_STYLE_FLOAT) || + (mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) + ; + else if( mnStyle & SAL_FRAME_STYLE_DEFAULT ) + { + // make default window "maximized" + maGeometry.nX = static_cast<int>(aVisibleRect.origin.x); + maGeometry.nY = static_cast<int>(aVisibleRect.origin.y); + maGeometry.nWidth = static_cast<int>(aVisibleRect.size.width); + maGeometry.nHeight = static_cast<int>(aVisibleRect.size.height); + } + else + { + if( (mnStyle & SAL_FRAME_STYLE_MOVEABLE) ) + { + } + } + + mpWindow = [[SalFrameWindow alloc] initWithSalFrame: this]; + mpView = [[SalFrameView alloc] initWithSalFrame: this]; + + maSysData.pView = mpView; + + UpdateFrameGeometry(); +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::CocoaTouchToVCL( CGRect& io_rRect, bool bRelativeToScreen ) +{ + if( bRelativeToScreen ) + io_rRect.origin.y = maScreenRect.size.height - (io_rRect.origin.y+io_rRect.size.height); + else + io_rRect.origin.y = maGeometry.nHeight - (io_rRect.origin.y+io_rRect.size.height); +} + +void IosSalFrame::VCLToCocoaTouch( CGRect& io_rRect, bool bRelativeToScreen ) +{ + if( bRelativeToScreen ) + io_rRect.origin.y = maScreenRect.size.height - (io_rRect.origin.y+io_rRect.size.height); + else + io_rRect.origin.y = maGeometry.nHeight - (io_rRect.origin.y+io_rRect.size.height); +} + +void IosSalFrame::CocoaTouchToVCL( CGPoint& io_rPoint, bool bRelativeToScreen ) +{ + if( bRelativeToScreen ) + io_rPoint.y = maScreenRect.size.height - io_rPoint.y; + else + io_rPoint.y = maGeometry.nHeight - io_rPoint.y; +} + +void IosSalFrame::VCLToCocoaTouch( CGPoint& io_rPoint, bool bRelativeToScreen ) +{ + if( bRelativeToScreen ) + io_rPoint.y = maScreenRect.size.height - io_rPoint.y; + else + io_rPoint.y = maGeometry.nHeight - io_rPoint.y; +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::screenParametersChanged() +{ + UpdateFrameGeometry(); + + if( mpGraphics ) + mpGraphics->updateResolution(); + CallCallback( SALEVENT_DISPLAYCHANGED, 0 ); +} + +// ----------------------------------------------------------------------- + +SalGraphics* IosSalFrame::GetGraphics() +{ + if ( mbGraphics ) + return NULL; + + if ( !mpGraphics ) + { + mpGraphics = new IosSalGraphics; + mpGraphics->SetWindowGraphics( this ); + } + + mbGraphics = TRUE; + return mpGraphics; +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::ReleaseGraphics( SalGraphics *pGraphics ) +{ + (void)pGraphics; + DBG_ASSERT( pGraphics == mpGraphics, "graphics released on wrong frame" ); + mbGraphics = FALSE; +} + +// ----------------------------------------------------------------------- + +sal_Bool IosSalFrame::PostEvent( void *pData ) +{ + GetSalData()->mpFirstInstance->PostUserEvent( this, SALEVENT_USEREVENT, pData ); + return TRUE; +} + +// ----------------------------------------------------------------------- +void IosSalFrame::SetTitle(const XubString& /* rTitle */) +{ +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::SetIcon( sal_uInt16 ) +{ +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::SetRepresentedURL( const rtl::OUString& /* i_rDocURL */ ) +{ +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::initShow() +{ + mbInitShow = false; + { + Rectangle aScreenRect; + GetWorkArea( aScreenRect ); + if( mpParent ) // center relative to parent + { + // center on parent + long nNewX = mpParent->maGeometry.nX + ((long)mpParent->maGeometry.nWidth - (long)maGeometry.nWidth)/2; + if( nNewX < aScreenRect.Left() ) + nNewX = aScreenRect.Left(); + if( long(nNewX + maGeometry.nWidth) > aScreenRect.Right() ) + nNewX = aScreenRect.Right() - maGeometry.nWidth-1; + long nNewY = mpParent->maGeometry.nY + ((long)mpParent->maGeometry.nHeight - (long)maGeometry.nHeight)/2; + if( nNewY < aScreenRect.Top() ) + nNewY = aScreenRect.Top(); + if( nNewY > aScreenRect.Bottom() ) + nNewY = aScreenRect.Bottom() - maGeometry.nHeight-1; + SetPosSize( nNewX - mpParent->maGeometry.nX, + nNewY - mpParent->maGeometry.nY, + 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ); + } + else if( ! (mnStyle & SAL_FRAME_STYLE_SIZEABLE) ) + { + // center on screen + long nNewX = (aScreenRect.GetWidth() - maGeometry.nWidth)/2; + long nNewY = (aScreenRect.GetHeight() - maGeometry.nHeight)/2; + SetPosSize( nNewX, nNewY, 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ); + } + } +} + +void IosSalFrame::SendPaintEvent( const Rectangle* pRect ) +{ + SalPaintEvent aPaintEvt( 0, 0, maGeometry.nWidth, maGeometry.nHeight, true ); + if( pRect ) + { + aPaintEvt.mnBoundX = pRect->Left(); + aPaintEvt.mnBoundY = pRect->Top(); + aPaintEvt.mnBoundWidth = pRect->GetWidth(); + aPaintEvt.mnBoundHeight = pRect->GetHeight(); + } + + CallCallback(SALEVENT_PAINT, &aPaintEvt); +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::Show(sal_Bool bVisible, sal_Bool bNoActivate) +{ + if ( !mpWindow ) + return; + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + mbShown = bVisible; + if(bVisible) + { + if( mbInitShow ) + initShow(); + + CallCallback(SALEVENT_RESIZE, 0); + // trigger filling our backbuffer + SendPaintEvent(); + + if( !bNoActivate ) + [mpWindow makeKeyAndVisible]; +#if 0 // ??? + if( mpParent ) + { + /* #i92674# #i96433# we do not want an invisible parent to show up (which adding a visible + child implicitly does). However we also do not want a parentless toolbar. + + HACK: try to decide when we should not insert a child to its parent + floaters and ownerdraw windows have not yet shown up in cases where + we don't want the parent to become visible + */ + if( mpParent->mbShown || (mnStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION | SAL_FRAME_STYLE_FLOAT) ) ) + { + [mpParent->mpWindow addChildWindow: mpWindow]; + } + } + + if( mbPresentation ) + [mpWindow makeMainWindow]; +#endif + } + else + { +#if 0 // ??? + if( mpParent && [mpWindow parentWindow] == mpParent->mpWindow ) + [mpParent->mpWindow removeChildWindow: mpWindow]; +#endif + } +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::Enable( sal_Bool ) +{ +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::SetMinClientSize( long nWidth, long nHeight ) +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + mnMinWidth = nWidth; + mnMinHeight = nHeight; + + if( mpWindow ) + { + // Always add the decoration as the dimension concerns only + // the content rectangle + nWidth += maGeometry.nLeftDecoration + maGeometry.nRightDecoration; + nHeight += maGeometry.nTopDecoration + maGeometry.nBottomDecoration; + + CGSize aSize = { nWidth, nHeight }; +#if 0 // ??? + // Size of full window (content+structure) although we only + // have the client size in arguments + [mpWindow setMinSize: aSize]; +#endif + } +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::SetMaxClientSize( long nWidth, long nHeight ) +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + mnMaxWidth = nWidth; + mnMaxHeight = nHeight; + + if( mpWindow ) + { + // Always add the decoration as the dimension concerns only + // the content rectangle + nWidth += maGeometry.nLeftDecoration + maGeometry.nRightDecoration; + nHeight += maGeometry.nTopDecoration + maGeometry.nBottomDecoration; + + // Carbon windows can't have a size greater than 32767x32767 + if (nWidth>32767) nWidth=32767; + if (nHeight>32767) nHeight=32767; + + CGSize aSize = { nWidth, nHeight }; +#if 0 // ??? + // Size of full window (content+structure) although we only + // have the client size in arguments + [mpWindow setMaxSize: aSize]; +#endif + } +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::SetClientSize( long nWidth, long nHeight ) +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + if( mpWindow ) + { + CGSize aSize = { nWidth, nHeight }; +#if 0 // ??? + [mpWindow setContentSize: aSize]; +#endif + UpdateFrameGeometry(); + if( mbShown ) + // trigger filling our backbuffer + SendPaintEvent(); + } +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::GetClientSize( long& rWidth, long& rHeight ) +{ + if( mbShown || mbInitShow ) + { + rWidth = maGeometry.nWidth; + rHeight = maGeometry.nHeight; + } + else + { + rWidth = 0; + rHeight = 0; + } +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::SetWindowState( const SalFrameState* pState ) +{ + // ??? + + // get new geometry + UpdateFrameGeometry(); + + sal_uInt16 nEvent = 0; + if( pState->mnMask & (SAL_FRAMESTATE_MASK_X | SAL_FRAMESTATE_MASK_X) ) + { + mbPositioned = true; + nEvent = SALEVENT_MOVE; + } + + if( pState->mnMask & (SAL_FRAMESTATE_MASK_WIDTH | SAL_FRAMESTATE_MASK_HEIGHT) ) + { + mbSized = true; + nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE; + } + // send event that we were moved/sized + if( nEvent ) + CallCallback( nEvent, NULL ); + + if( mbShown && mpWindow ) + { + // trigger filling our backbuffer + SendPaintEvent(); + } +} + +// ----------------------------------------------------------------------- + +sal_Bool IosSalFrame::GetWindowState( SalFrameState* pState ) +{ + if ( !mpWindow ) + return FALSE; + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + pState->mnMask = SAL_FRAMESTATE_MASK_X | + SAL_FRAMESTATE_MASK_Y | + SAL_FRAMESTATE_MASK_WIDTH | + SAL_FRAMESTATE_MASK_HEIGHT | + SAL_FRAMESTATE_MASK_STATE; + + CGRect aStateRect = [mpWindow frame]; +#if 0 // ??? + aStateRect = [UIWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask]; + CocoaTouchToVCL( aStateRect ); + pState->mnX = long(aStateRect.origin.x); + pState->mnY = long(aStateRect.origin.y); + pState->mnWidth = long(aStateRect.size.width); + pState->mnHeight = long(aStateRect.size.height); +#endif + pState->mnState = SAL_FRAMESTATE_MAXIMIZED; + + return TRUE; +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::SetScreenNumber(unsigned int nScreen) +{ + // ??? +} + +void IosSalFrame::SetApplicationID( const rtl::OUString &/*rApplicationID*/ ) +{ +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::ShowFullScreen( sal_Bool bFullScreen, sal_Int32 nDisplay ) +{ + // ??? +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::StartPresentation( sal_Bool bStart ) +{ + if ( !mpWindow ) + return; + + // ??? +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::SetAlwaysOnTop( sal_Bool ) +{ +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::ToTop(sal_uInt16 nFlags) +{ + if ( !mpWindow ) + return; + + // ??? +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::SetPointer( PointerStyle ePointerStyle ) +{ +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::SetPointerPos( long /* nX */ , long /* nY */ ) +{ +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::Flush( void ) +{ + // ??? +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::Flush( const Rectangle& rRect ) +{ + // ??? +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::Sync() +{ + // ??? +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::SetInputContext( SalInputContext* pContext ) +{ + if (!pContext) + { + mnICOptions = 0; + return; + } + + mnICOptions = pContext->mnOptions; + + if(!(pContext->mnOptions & SAL_INPUTCONTEXT_TEXT)) + return; +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::EndExtTextInput( sal_uInt16 ) +{ +} + +// ----------------------------------------------------------------------- + +XubString IosSalFrame::GetKeyName( sal_uInt16 nKeyCode ) +{ + static std::map< sal_uInt16, rtl::OUString > aKeyMap; + if( aKeyMap.empty() ) + { + sal_uInt16 i; + for( i = KEY_A; i <= KEY_Z; i++ ) + aKeyMap[ i ] = rtl::OUString( sal_Unicode( 'A' + (i - KEY_A) ) ); + for( i = KEY_0; i <= KEY_9; i++ ) + aKeyMap[ i ] = rtl::OUString( sal_Unicode( '0' + (i - KEY_0) ) ); + for( i = KEY_F1; i <= KEY_F26; i++ ) + { + rtl::OUStringBuffer aKey( 3 ); + aKey.append( sal_Unicode( 'F' ) ); + aKey.append( sal_Int32( i - KEY_F1 + 1 ) ); + aKeyMap[ i ] = aKey.makeStringAndClear(); + } + + aKeyMap[ KEY_DOWN ] = rtl::OUString( sal_Unicode( 0x21e3 ) ); + aKeyMap[ KEY_UP ] = rtl::OUString( sal_Unicode( 0x21e1 ) ); + aKeyMap[ KEY_LEFT ] = rtl::OUString( sal_Unicode( 0x21e0 ) ); + aKeyMap[ KEY_RIGHT ] = rtl::OUString( sal_Unicode( 0x21e2 ) ); + aKeyMap[ KEY_HOME ] = rtl::OUString( sal_Unicode( 0x2196 ) ); + aKeyMap[ KEY_END ] = rtl::OUString( sal_Unicode( 0x2198 ) ); + aKeyMap[ KEY_PAGEUP ] = rtl::OUString( sal_Unicode( 0x21de ) ); + aKeyMap[ KEY_PAGEDOWN ] = rtl::OUString( sal_Unicode( 0x21df ) ); + aKeyMap[ KEY_RETURN ] = rtl::OUString( sal_Unicode( 0x21a9 ) ); + aKeyMap[ KEY_ESCAPE ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "esc" ) ); + aKeyMap[ KEY_TAB ] = rtl::OUString( sal_Unicode( 0x21e5 ) ); + aKeyMap[ KEY_BACKSPACE ]= rtl::OUString( sal_Unicode( 0x232b ) ); + aKeyMap[ KEY_SPACE ] = rtl::OUString( sal_Unicode( 0x2423 ) ); + aKeyMap[ KEY_DELETE ] = rtl::OUString( sal_Unicode( 0x2326 ) ); + aKeyMap[ KEY_ADD ] = rtl::OUString( sal_Unicode( '+' ) ); + aKeyMap[ KEY_SUBTRACT ] = rtl::OUString( sal_Unicode( '-' ) ); + aKeyMap[ KEY_DIVIDE ] = rtl::OUString( sal_Unicode( '/' ) ); + aKeyMap[ KEY_MULTIPLY ] = rtl::OUString( sal_Unicode( '*' ) ); + aKeyMap[ KEY_POINT ] = rtl::OUString( sal_Unicode( '.' ) ); + aKeyMap[ KEY_COMMA ] = rtl::OUString( sal_Unicode( ',' ) ); + aKeyMap[ KEY_LESS ] = rtl::OUString( sal_Unicode( '<' ) ); + aKeyMap[ KEY_GREATER ] = rtl::OUString( sal_Unicode( '>' ) ); + aKeyMap[ KEY_EQUAL ] = rtl::OUString( sal_Unicode( '=' ) ); + aKeyMap[ KEY_OPEN ] = rtl::OUString( sal_Unicode( 0x23cf ) ); + + /* yet unmapped KEYCODES: + aKeyMap[ KEY_INSERT ] = rtl::OUString( sal_Unicode( ) ); + aKeyMap[ KEY_CUT ] = rtl::OUString( sal_Unicode( ) ); + aKeyMap[ KEY_COPY ] = rtl::OUString( sal_Unicode( ) ); + aKeyMap[ KEY_PASTE ] = rtl::OUString( sal_Unicode( ) ); + aKeyMap[ KEY_UNDO ] = rtl::OUString( sal_Unicode( ) ); + aKeyMap[ KEY_REPEAT ] = rtl::OUString( sal_Unicode( ) ); + aKeyMap[ KEY_FIND ] = rtl::OUString( sal_Unicode( ) ); + aKeyMap[ KEY_PROPERTIES ] = rtl::OUString( sal_Unicode( ) ); + aKeyMap[ KEY_FRONT ] = rtl::OUString( sal_Unicode( ) ); + aKeyMap[ KEY_CONTEXTMENU ] = rtl::OUString( sal_Unicode( ) ); + aKeyMap[ KEY_MENU ] = rtl::OUString( sal_Unicode( ) ); + aKeyMap[ KEY_HELP ] = rtl::OUString( sal_Unicode( ) ); + aKeyMap[ KEY_HANGUL_HANJA ] = rtl::OUString( sal_Unicode( ) ); + aKeyMap[ KEY_DECIMAL ] = rtl::OUString( sal_Unicode( ) ); + aKeyMap[ KEY_TILDE ] = rtl::OUString( sal_Unicode( ) ); + aKeyMap[ KEY_QUOTELEFT ]= rtl::OUString( sal_Unicode( ) ); + */ + + } + + rtl::OUStringBuffer aResult( 16 ); + + sal_uInt16 nUnmodifiedCode = (nKeyCode & KEY_CODE); + std::map< sal_uInt16, rtl::OUString >::const_iterator it = aKeyMap.find( nUnmodifiedCode ); + if( it != aKeyMap.end() ) + { + if( (nKeyCode & KEY_SHIFT) != 0 ) + aResult.append( sal_Unicode( 0x21e7 ) ); + if( (nKeyCode & KEY_MOD1) != 0 ) + aResult.append( sal_Unicode( 0x2318 ) ); + // we do not really handle Alt (see below) + // we map it to MOD3, whichis actually Command + if( (nKeyCode & (KEY_MOD2|KEY_MOD3)) != 0 ) + aResult.append( sal_Unicode( 0x2303 ) ); + + aResult.append( it->second ); + } + + return aResult.makeStringAndClear(); +} + +// ----------------------------------------------------------------------- + +XubString IosSalFrame::GetSymbolKeyName( const XubString&, sal_uInt16 nKeyCode ) +{ + return GetKeyName( nKeyCode ); +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::getResolution( long& o_rDPIX, long& o_rDPIY ) +{ + if( ! mpGraphics ) + { + GetGraphics(); + ReleaseGraphics( mpGraphics ); + } + mpGraphics->GetResolution( o_rDPIX, o_rDPIY ); +} + +void IosSalFrame::UpdateSettings( AllSettings& rSettings ) +{ + if ( !mpWindow ) + return; + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + StyleSettings aStyleSettings = rSettings.GetStyleSettings(); + + // Background Color + Color aBackgroundColor = Color( 0xEC, 0xEC, 0xEC ); + aStyleSettings.Set3DColors( aBackgroundColor ); + aStyleSettings.SetFaceColor( aBackgroundColor ); + Color aInactiveTabColor( aBackgroundColor ); + aInactiveTabColor.DecreaseLuminance( 32 ); + aStyleSettings.SetInactiveTabColor( aInactiveTabColor ); + + aStyleSettings.SetDialogColor( aBackgroundColor ); + aStyleSettings.SetLightBorderColor( aBackgroundColor ); + Color aShadowColor( aStyleSettings.GetShadowColor() ); + aStyleSettings.SetDarkShadowColor( aShadowColor ); + aShadowColor.IncreaseLuminance( 32 ); + aStyleSettings.SetShadowColor( aShadowColor ); + + // get the system font settings + Font aAppFont = aStyleSettings.GetAppFont(); + long nDPIX = 72, nDPIY = 72; + getResolution( nDPIX, nDPIY ); + + aStyleSettings.SetToolbarIconSize( nDPIY > 160 ? STYLE_TOOLBAR_ICONSIZE_LARGE : STYLE_TOOLBAR_ICONSIZE_SMALL ); + + aStyleSettings.SetCursorBlinkTime( 500 ); + + // no mnemonics on iOs + aStyleSettings.SetOptions( aStyleSettings.GetOptions() | STYLE_OPTION_NOMNEMONICS ); + + // images in menus false for iOS + aStyleSettings.SetPreferredUseImagesInMenus( false ); + aStyleSettings.SetHideDisabledMenuItems( sal_True ); + aStyleSettings.SetAcceleratorsInContextMenus( sal_False ); + + rSettings.SetStyleSettings( aStyleSettings ); +} + +// ----------------------------------------------------------------------- + +const SystemEnvData* IosSalFrame::GetSystemData() const +{ + return &maSysData; +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::Beep( SoundType eSoundType ) +{ + switch( eSoundType ) + { + case SOUND_DISABLE: + // don't beep + break; + default: + // ??? + break; + } +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::SetPosSize(long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags) +{ + if ( !mpWindow ) + return; + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + sal_uInt16 nEvent = 0; + + if (nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y)) + { + mbPositioned = true; + nEvent = SALEVENT_MOVE; + } + + if (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) + { + mbSized = true; + nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE; + } + + CGRect aFrameRect = [mpWindow frame]; +#if 0 // ??? + CGRect aContentRect = [NSWindow contentRectForFrameRect: aFrameRect styleMask: mnStyleMask]; + + // position is always relative to parent frame + CGRect aParentContentRect; + + if( mpParent ) + { + if( Application::GetSettings().GetLayoutRTL() ) + { + if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 ) + nX = mpParent->maGeometry.nWidth - nWidth-1 - nX; + else + nX = mpParent->maGeometry.nWidth - static_cast<long int>( aContentRect.size.width-1) - nX; + } + CGRect aParentFrameRect = [mpParent->mpWindow frame]; + aParentContentRect = [NSWindow contentRectForFrameRect: aParentFrameRect styleMask: mpParent->mnStyleMask]; + } + else + aParentContentRect = maScreenRect; // use screen if no parent + + CocoaTouchToVCL( aContentRect ); + CocoaTouchToVCL( aParentContentRect ); + + bool bPaint = false; + if( (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) != 0 ) + { + if( nWidth != aContentRect.size.width || nHeight != aContentRect.size.height ) + bPaint = true; + } + + // use old window pos if no new pos requested + if( (nFlags & SAL_FRAME_POSSIZE_X) != 0 ) + aContentRect.origin.x = nX + aParentContentRect.origin.x; + if( (nFlags & SAL_FRAME_POSSIZE_Y) != 0) + aContentRect.origin.y = nY + aParentContentRect.origin.y; + + // use old size if no new size requested + if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 ) + aContentRect.size.width = nWidth; + if( (nFlags & SAL_FRAME_POSSIZE_HEIGHT) != 0) + aContentRect.size.height = nHeight; + + VCLToCocoaTouch( aContentRect ); + + // do not display yet, we need to update our backbuffer + { + [mpWindow setFrame: [NSWindow frameRectForContentRect: aContentRect styleMask: mnStyleMask] display: NO]; + } + + UpdateFrameGeometry(); + + if (nEvent) + CallCallback(nEvent, NULL); + + if( mbShown && bPaint ) + { + // trigger filling our backbuffer + SendPaintEvent(); + + // now inform the system that the views need to be drawn + [mpWindow display]; + } +#endif +} + +void IosSalFrame::GetWorkArea( Rectangle& rRect ) +{ + if ( !mpWindow ) + return; + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + UIScreen* pScreen = [mpWindow screen]; + if( pScreen == nil ) + pScreen = [UIScreen mainScreen]; + CGRect aRect = [pScreen applicationFrame]; + CocoaTouchToVCL( aRect ); + rRect.nLeft = static_cast<long>(aRect.origin.x); + rRect.nTop = static_cast<long>(aRect.origin.y); + rRect.nRight = static_cast<long>(aRect.origin.x + aRect.size.width - 1); + rRect.nBottom = static_cast<long>(aRect.origin.y + aRect.size.height - 1); +} + +SalPointerState IosSalFrame::GetPointerState() +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + SalPointerState state; + state.mnState = 0; + + // ??? + + return state; +} + +SalFrame::SalIndicatorState IosSalFrame::GetIndicatorState() +{ + SalIndicatorState aState; + aState.mnState = 0; + return aState; +} + +void IosSalFrame::SimulateKeyPress( sal_uInt16 /*nKeyCode*/ ) +{ +} + +bool IosSalFrame::SetPluginParent( SystemParentData* ) +{ + // plugin parent may be killed unexpectedly by + // plugging process; + + //TODO: implement + return sal_False; +} + +sal_Bool IosSalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , KeyCode& ) +{ + // not supported yet + return FALSE; +} + +LanguageType IosSalFrame::GetInputLanguage() +{ + //TODO: implement + return LANGUAGE_DONTKNOW; +} + +void IosSalFrame::DrawMenuBar() +{ +} + +void IosSalFrame::SetMenu( SalMenu* pSalMenu ) +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + // ??? +} + +void IosSalFrame::SetExtendedFrameStyle( SalExtStyle nStyle ) +{ + // ??? +} + +void IosSalFrame::SetBackgroundBitmap( SalBitmap* ) +{ + //TODO: implement +} + +SalBitmap* IosSalFrame::SnapShot() +{ + return mpGraphics ? mpGraphics->getBitmap( 0, 0, maGeometry.nWidth, maGeometry.nHeight ) : NULL; +} + +SalFrame* IosSalFrame::GetParent() const +{ + return mpParent; +} + +void IosSalFrame::SetParent( SalFrame* pNewParent ) +{ + bool bShown = mbShown; + // remove from child list + Show( FALSE ); + mpParent = (IosSalFrame*)pNewParent; + // insert to correct parent and paint + Show( bShown ); +} + +void IosSalFrame::UpdateFrameGeometry() +{ + if ( !mpWindow ) + { + return; + } + + // keep in mind that view and window coordinates are lower left + // whereas vcl's are upper left + +#if 0 // ??? + // update screen rect + NSScreen * pScreen = [mpWindow screen]; + if( pScreen ) + { + maScreenRect = [pScreen frame]; + NSArray* pScreens = [NSScreen screens]; + if( pScreens ) + maGeometry.nScreenNumber = [pScreens indexOfObject: pScreen]; + } + + CGRect aFrameRect = [mpWindow frame]; + + CGRect aContentRect = [NSWindow contentRectForFrameRect: aFrameRect styleMask: mnStyleMask]; + + // release old track rect + [mpView removeTrackingRect: mnTrackingRectTag]; + // install the new track rect + CGRect aTrackRect = { { 0, 0 }, aContentRect.size }; + mnTrackingRectTag = [mpView addTrackingRect: aTrackRect owner: mpView userData: nil assumeInside: NO]; + + // convert to vcl convention + CocoaTouchToVCL( aFrameRect ); + CocoaTouchToVCL( aContentRect ); + + maGeometry.nX = static_cast<int>(aContentRect.origin.x); + maGeometry.nY = static_cast<int>(aContentRect.origin.y); + + maGeometry.nLeftDecoration = static_cast<unsigned int>(aContentRect.origin.x - aFrameRect.origin.x); + maGeometry.nRightDecoration = static_cast<unsigned int>((aFrameRect.origin.x + aFrameRect.size.width) - + (aContentRect.origin.x + aContentRect.size.width)); + + maGeometry.nTopDecoration = static_cast<unsigned int>(aContentRect.origin.y - aFrameRect.origin.y); + maGeometry.nBottomDecoration = static_cast<unsigned int>((aFrameRect.origin.y + aFrameRect.size.height) - + (aContentRect.origin.y + aContentRect.size.height)); + + maGeometry.nWidth = static_cast<unsigned int>(aContentRect.size.width); + maGeometry.nHeight = static_cast<unsigned int>(aContentRect.size.height); +#endif +} + +// ----------------------------------------------------------------------- + +void IosSalFrame::CaptureMouse( sal_Bool bCapture ) +{ + /* Remark: + we'll try to use a pidgin version of capture mouse + on MacOSX (neither carbon nor cocoa) there is a + CaptureMouse equivalent (in Carbon there is TrackMouseLocation + but this is useless to use since it is blocking) + + However on cocoa the active frame seems to get mouse events + also outside the window, so we'll try to forward mouse events + to the capture frame in the hope that one of our frames + gets a mouse event. + + This will break as soon as the user activates another app, but + a mouse click will normally lead to a release of the mouse anyway. + + Let's see how far we get this way. Alternatively we could use one + large overlay window like we did for the carbon implementation, + however that is resource intensive. + */ + + if( bCapture ) + s_pCaptureFrame = this; + else if( ! bCapture && s_pCaptureFrame == this ) + s_pCaptureFrame = NULL; +} + +void IosSalFrame::ResetClipRegion() +{ + if ( !mpWindow ) + { + return; + } + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + // release old path and indicate no clipping + CGPathRelease( mrClippingPath ); + mrClippingPath = NULL; + + if( mpWindow ) + { + [mpWindow setOpaque: YES]; + } +} + +void IosSalFrame::BeginSetClipRegion( sal_uLong nRects ) +{ + if ( !mpWindow ) + { + return; + } + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + // release old path + if( mrClippingPath ) + { + CGPathRelease( mrClippingPath ); + mrClippingPath = NULL; + } + + if( maClippingRects.size() > SAL_CLIPRECT_COUNT && nRects < maClippingRects.size() ) + { + std::vector<CGRect> aEmptyVec; + maClippingRects.swap( aEmptyVec ); + } + maClippingRects.clear(); + maClippingRects.reserve( nRects ); +} + +void IosSalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + if( nWidth && nHeight ) + { + CGRect aRect = { { nX, nY }, { nWidth, nHeight } }; + VCLToCocoaTouch( aRect, false ); + maClippingRects.push_back( CGRectMake(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height) ); + } +} + +void IosSalFrame::EndSetClipRegion() +{ + if ( !mpWindow ) + { + return; + } + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + if( ! maClippingRects.empty() ) + { + mrClippingPath = CGPathCreateMutable(); + CGPathAddRects( mrClippingPath, NULL, &maClippingRects[0], maClippingRects.size() ); + } + if( mpWindow ) + { + [mpWindow setOpaque: (mrClippingPath != NULL) ? NO : YES]; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/ios/source/window/salmenu.cxx b/vcl/ios/source/window/salmenu.cxx new file mode 100644 index 000000000000..0cda8229b1d4 --- /dev/null +++ b/vcl/ios/source/window/salmenu.cxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "rtl/ustrbuf.hxx" + +#include "vcl/cmdevt.hxx" +#include "vcl/floatwin.hxx" +#include "vcl/window.hxx" +#include "vcl/svapp.hxx" + +#include "ios/saldata.hxx" +#include "ios/salinst.h" +#include "ios/salmenu.h" +#include "ios/salframe.h" +#include "ios/salbmp.h" + +#include "svids.hrc" +#include "window.h" + +// ======================================================================= + +SalMenu* IosSalInstance::CreateMenu( sal_Bool bMenuBar, Menu* pVCLMenu ) +{ + // ??? + return NULL; +} + +void IosSalInstance::DestroyMenu( SalMenu* pSalMenu ) +{ + delete pSalMenu; +} + +SalMenuItem* IosSalInstance::CreateMenuItem( const SalItemParams* pItemData ) +{ + // ??? + return NULL; +} + +void IosSalInstance::DestroyMenuItem( SalMenuItem* pSalMenuItem ) +{ + delete pSalMenuItem; +} + + +// ======================================================================= + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/ios/source/window/salobj.cxx b/vcl/ios/source/window/salobj.cxx new file mode 100644 index 000000000000..e55b0874685d --- /dev/null +++ b/vcl/ios/source/window/salobj.cxx @@ -0,0 +1,242 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" + +#include <string.h> + +#include "ios/saldata.hxx" +#include "ios/salobj.h" +#include "ios/salframe.h" + +// ======================================================================= + +IosSalObject::IosSalObject( IosSalFrame* pFrame ) : + mpFrame( pFrame ), + mnClipX( -1 ), + mnClipY( -1 ), + mnClipWidth( -1 ), + mnClipHeight( -1 ), + mbClip( false ), + mnX( 0 ), + mnY( 0 ), + mnWidth( 20 ), + mnHeight( 20 ) +{ + maSysData.nSize = sizeof( maSysData ); + maSysData.pView = NULL; + + CGRect aInitFrame = { { 0, 0 }, { 20, 20 } }; + maSysData.pView = [[UIView alloc] initWithFrame: aInitFrame]; +} + +// ----------------------------------------------------------------------- + +IosSalObject::~IosSalObject() +{ + if( maSysData.pView ) + { + UIView *pView = maSysData.pView; + [pView removeFromSuperview]; + [pView release]; + } +#if 0 // ??? + if( mpClipView ) + { + [mpClipView removeFromSuperview]; + [mpClipView release]; + } +#endif +} + +/* + sadly there seems to be no way to impose clipping on a child view, + especially a QTMovieView which seems to ignore the current context + completely. Also there is no real way to shape a window; on Ios a + similar effect to non-rectangular windows is achieved by using a + non-opaque window and not painting where one wants the background + to shine through. + + With respect to SalObject this leaves us to having an NSClipView + containing the child view. Even a QTMovieView respects the boundaries of + that, which gives us a clip "region" consisting of one rectangle. + This is gives us an 80% solution only, though. +*/ + +// ----------------------------------------------------------------------- + +void IosSalObject::ResetClipRegion() +{ + mbClip = false; + setClippedPosSize(); +} + +// ----------------------------------------------------------------------- + +sal_uInt16 IosSalObject::GetClipRegionType() +{ + return SAL_OBJECT_CLIP_INCLUDERECTS; +} + +// ----------------------------------------------------------------------- + +void IosSalObject::BeginSetClipRegion( sal_uLong ) +{ + mbClip = false; +} + +// ----------------------------------------------------------------------- + +void IosSalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) +{ + if( mbClip ) + { + if( nX < mnClipX ) + { + mnClipWidth += mnClipX - nX; + mnClipX = nX; + } + if( nX + nWidth > mnClipX + mnClipWidth ) + mnClipWidth = nX + nWidth - mnClipX; + if( nY < mnClipY ) + { + mnClipHeight += mnClipY - nY; + mnClipY = nY; + } + if( nY + nHeight > mnClipY + mnClipHeight ) + mnClipHeight = nY + nHeight - mnClipY; + } + else + { + mnClipX = nX; + mnClipY = nY; + mnClipWidth = nWidth; + mnClipHeight = nHeight; + mbClip = true; + } +} + +// ----------------------------------------------------------------------- + +void IosSalObject::EndSetClipRegion() +{ + setClippedPosSize(); +} + +// ----------------------------------------------------------------------- + +void IosSalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight ) +{ + mnX = nX; + mnY = nY; + mnWidth = nWidth; + mnHeight = nHeight; + setClippedPosSize(); +} + +// ----------------------------------------------------------------------- + +void IosSalObject::setClippedPosSize() +{ + CGRect aViewRect = { { 0, 0 }, { mnWidth, mnHeight } }; + if( maSysData.pView ) + { + UIView *pView = maSysData.pView; + [pView setFrame: aViewRect]; + } + + CGRect aClipViewRect = { { mnX, mnY }, { mnWidth, mnHeight } }; + CGPoint aClipPt = { 0, 0 }; + if( mbClip ) + { + aClipViewRect.origin.x += mnClipX; + aClipViewRect.origin.y += mnClipY; + aClipViewRect.size.width = mnClipWidth; + aClipViewRect.size.height = mnClipHeight; + aClipPt.x = mnClipX; + if( mnClipY == 0 ) + aClipPt.y = mnHeight - mnClipHeight;; + } + + mpFrame->VCLToCocoaTouch( aClipViewRect, false ); +#if 0 // ??? + [mpClipView setFrame: aClipViewRect]; + + [mpClipView scrollToPoint: aClipPt]; +#endif +} + +// ----------------------------------------------------------------------- + +void IosSalObject::Show( sal_Bool bVisible ) +{ +#if 0 // ??? + if( mpClipView ) + [mpClipView setHidden: (bVisible ? NO : YES)]; +#endif +} + +// ----------------------------------------------------------------------- + +void IosSalObject::Enable( sal_Bool ) +{ +} + +// ----------------------------------------------------------------------- + +void IosSalObject::GrabFocus() +{ +} + +// ----------------------------------------------------------------------- + +void IosSalObject::SetBackground() +{ +} + +// ----------------------------------------------------------------------- + +void IosSalObject::SetBackground( SalColor ) +{ +} + +// ----------------------------------------------------------------------- + +const SystemEnvData* IosSalObject::GetSystemData() const +{ + return &maSysData; +} + +// ----------------------------------------------------------------------- + +void IosSalObject::InterceptChildWindowKeyDown( sal_Bool /*bIntercept*/ ) +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |