diff options
Diffstat (limited to 'vcl/aqua')
34 files changed, 4405 insertions, 54 deletions
diff --git a/vcl/aqua/inc/saldata.hxx b/vcl/aqua/inc/saldata.hxx index dc629b9a3b8c..a84be1fc2c25 100644 --- a/vcl/aqua/inc/saldata.hxx +++ b/vcl/aqua/inc/saldata.hxx @@ -35,6 +35,8 @@ #include <Cocoa/Cocoa.h> #include "postmac.h" +#include "com/sun/star/uno/Reference.hxx" + #include "vcl/sv.h" #include "vcl/svdata.hxx" #include "vcl/salwtype.hxx" @@ -112,6 +114,9 @@ struct SalData long mnDPIX; // #i100617# read DPI only once per office life long mnDPIY; // #i100617# read DPI only once per office life + com::sun::star::uno::Reference< com::sun::star::uno::XInterface > + mxClipboard; + SalData(); ~SalData(); diff --git a/vcl/aqua/inc/salframe.h b/vcl/aqua/inc/salframe.h index aeabdefc72a5..1d1eb3cb6bd3 100644 --- a/vcl/aqua/inc/salframe.h +++ b/vcl/aqua/inc/salframe.h @@ -44,6 +44,8 @@ #include <utility> #include <stdexcept> +#include <boost/shared_ptr.hpp> + class AquaSalGraphics; class AquaSalFrame; class AquaSalTimer; @@ -60,47 +62,49 @@ typedef struct SalFrame::SalPointerState SalPointerState; class AquaSalFrame : public SalFrame { public: - NSWindow* mpWindow; // Cocoa window - NSView* mpView; // Cocoa view (actually a custom view, see below - NSMenuItem* mpDockMenuEntry; // entry in the dynamic dock menu - NSRect maScreenRect; // for mirroring purposes - AquaSalGraphics* mpGraphics; // current frame graphics - AquaSalFrame* mpParent; // pointer to parent frame - SystemEnvData maSysData; // system data - int mnMinWidth; // min. client width in pixels - int mnMinHeight; // min. client height in pixels - int mnMaxWidth; // max. client width in pixels - int mnMaxHeight; // max. client height in pixels - NSRect maFullScreenRect; // old window size when in FullScreen - bool mbGraphics:1; // is Graphics used? - bool mbFullScreen:1; // is Window in FullScreen? - bool mbShown:1; - bool mbInitShow:1; - bool mbPositioned:1; - bool mbSized:1; - bool mbPresentation:1; - - ULONG mnStyle; - unsigned int mnStyleMask; // our style mask from NSWindow creation - - ULONG mnLastEventTime; - unsigned int mnLastModifierFlags; - AquaSalMenu* mpMenu; - - SalExtStyle mnExtStyle; // currently document frames are marked this way - - PointerStyle mePointerStyle; // currently active pointer style - - NSTrackingRectTag mnTrackingRectTag; // used to get enter/leave messages - - CGMutablePathRef mrClippingPath; // used for "shaping" - std::vector< CGRect > maClippingRects; - - std::list<AquaBlinker*> maBlinkers; - - Rectangle maInvalidRect; - - ULONG mnICOptions; + NSWindow* mpWindow; // Cocoa window + NSView* mpView; // Cocoa view (actually a custom view, see below + NSMenuItem* mpDockMenuEntry; // entry in the dynamic dock menu + NSRect maScreenRect; // for mirroring purposes + AquaSalGraphics* mpGraphics; // current frame graphics + AquaSalFrame* mpParent; // pointer to parent frame + SystemEnvData maSysData; // system data + int mnMinWidth; // min. client width in pixels + int mnMinHeight; // min. client height in pixels + int mnMaxWidth; // max. client width in pixels + int mnMaxHeight; // max. client height in pixels + NSRect maFullScreenRect; // old window size when in FullScreen + bool mbGraphics:1; // is Graphics used? + bool mbFullScreen:1; // is Window in FullScreen? + bool mbShown:1; + bool mbInitShow:1; + bool mbPositioned:1; + bool mbSized:1; + bool mbPresentation:1; + + ULONG mnStyle; + unsigned int mnStyleMask; // our style mask from NSWindow creation + + ULONG mnLastEventTime; + unsigned int mnLastModifierFlags; + AquaSalMenu* mpMenu; + + SalExtStyle mnExtStyle; // currently document frames are marked this way + + PointerStyle mePointerStyle; // currently active pointer style + + NSTrackingRectTag mnTrackingRectTag; // used to get enter/leave messages + + CGMutablePathRef mrClippingPath; // used for "shaping" + std::vector< CGRect > maClippingRects; + + std::list<AquaBlinker*> maBlinkers; + + Rectangle maInvalidRect; + + ULONG mnICOptions; + + boost::shared_ptr< Timer > mpActivityTimer; // Timer to prevent system sleep during presentation public: /** Constructor diff --git a/vcl/aqua/inc/salinst.h b/vcl/aqua/inc/salinst.h index b2cbc83d9f79..5b1cf0d84562 100644 --- a/vcl/aqua/inc/salinst.h +++ b/vcl/aqua/inc/salinst.h @@ -143,9 +143,16 @@ public: virtual void DestroyMenuItem( SalMenuItem* ); virtual SalSession* CreateSalSession(); virtual void* GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes ); + virtual void AddToRecentDocumentList(const rtl::OUString& rFileUrl, const rtl::OUString& rMimeType); virtual void SetEventCallback( void* pInstance, bool(*pCallback)(void*,void*,int) ); virtual void SetErrorEventCallback( void* pInstance, bool(*pCallback)(void*,void*,int) ); + // dtrans implementation + virtual com::sun::star::uno::Reference< com::sun::star::uno::XInterface > + CreateClipboard( const com::sun::star::uno::Sequence< com::sun::star::uno::Any >& i_rArguments ); + virtual com::sun::star::uno::Reference< com::sun::star::uno::XInterface > CreateDragSource(); + virtual com::sun::star::uno::Reference< com::sun::star::uno::XInterface > CreateDropTarget(); + static void handleAppDefinedEvent( NSEvent* pEvent ); // check whether a particular string is passed on the command line diff --git a/vcl/aqua/inc/vclnsapp.h b/vcl/aqua/inc/vclnsapp.h index fc637ff75a31..622f1bfd6bcd 100755 --- a/vcl/aqua/inc/vclnsapp.h +++ b/vcl/aqua/inc/vclnsapp.h @@ -35,6 +35,8 @@ #include "Cocoa/Cocoa.h" #include "postmac.h" +class AquaSalFrame; + @interface CocoaThreadEnabler : NSObject { } @@ -64,6 +66,8 @@ -(void)applicationWillResignActive: (NSNotification *)pNotification; -(MacOSBOOL)applicationShouldHandleReopen: (NSApplication*)pApp hasVisibleWindows: (MacOSBOOL)bWinVisible; -(void)setDockIconClickHandler: (NSObject*)pHandler; +-(void)cycleFrameForward: (AquaSalFrame*)pCurFrame; +-(void)cycleFrameBackward: (AquaSalFrame*)pCurFrame; @end #endif diff --git a/vcl/aqua/source/a11y/aqua11yfactory.mm b/vcl/aqua/source/a11y/aqua11yfactory.mm index b660472d9bbe..a49bce957b3b 100644 --- a/vcl/aqua/source/a11y/aqua11yfactory.mm +++ b/vcl/aqua/source/a11y/aqua11yfactory.mm @@ -151,7 +151,18 @@ static bool enabled = false; } [ nativeRole release ]; [ aWrapper setActsAsRadioGroup: asRadioGroup ]; - if ( ! rxAccessibleContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::TRANSIENT ) ) { + #if 0 + /* #i102033# NSAccessibility does not seemt to know an equivalent for transient children. + That means we need to cache this, else e.g. tree list boxes are not accessible (moreover + it crashes by notifying dead objects - which would seemt o be another bug) + + FIXME: + Unfortunately this can increase memory consumption drastically until the non transient parent + is destroyed an finally all the transients are released. + */ + if ( ! rxAccessibleContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::TRANSIENT ) ) + #endif + { [ dAllWrapper setObject: aWrapper forKey: nKey ]; } } diff --git a/vcl/aqua/source/a11y/aqua11ywrapper.mm b/vcl/aqua/source/a11y/aqua11ywrapper.mm index 99bcbd20f698..64e0e9ef0308 100644 --- a/vcl/aqua/source/a11y/aqua11ywrapper.mm +++ b/vcl/aqua/source/a11y/aqua11ywrapper.mm @@ -109,7 +109,18 @@ static MacOSBOOL isPopupMenuOpen = NO; // XAccessibleMultiLineText mpReferenceWrapper -> rAccessibleMultiLineText = Reference < XAccessibleMultiLineText > ( rxAccessibleContext, UNO_QUERY ); // XAccessibleEventBroadcaster - if ( ! rxAccessibleContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::TRANSIENT ) ) { + #if 0 + /* #i102033# NSAccessibility does not seemt to know an equivalent for transient children. + That means we need to cache this, else e.g. tree list boxes are not accessible (moreover + it crashes by notifying dead objects - which would seemt o be another bug) + + FIXME: + Unfortunately this can increase memory consumption drastically until the non transient parent + is destroyed an finally all the transients are released. + */ + if ( ! rxAccessibleContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::TRANSIENT ) ) + #endif + { Reference< XAccessibleEventBroadcaster > xBroadcaster(rxAccessibleContext, UNO_QUERY); if( xBroadcaster.is() ) { /* diff --git a/vcl/aqua/source/app/makefile.mk b/vcl/aqua/source/app/makefile.mk index 2bf3641898f1..a90c95c74a6e 100644 --- a/vcl/aqua/source/app/makefile.mk +++ b/vcl/aqua/source/app/makefile.mk @@ -50,8 +50,6 @@ dummy: .ELSE # "$(GUIBASE)"!="aqua" -#CFLAGS+=-x objective-c++ - SLOFILES= $(SLO)$/salinst.obj \ $(SLO)$/saldata.obj \ $(SLO)$/vclnsapp.obj \ diff --git a/vcl/aqua/source/app/salinst.cxx b/vcl/aqua/source/app/salinst.cxx index 71bfb7953187..e4037df0c4aa 100644 --- a/vcl/aqua/source/app/salinst.cxx +++ b/vcl/aqua/source/app/salinst.cxx @@ -55,6 +55,14 @@ #include "saltimer.h" #include "vclnsapp.h" +#include <comphelper/processfactory.hxx> + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/uri/XExternalUriReferenceTranslator.hpp> +#include <com/sun/star/uri/ExternalUriReferenceTranslator.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + #include "premac.h" #include <Foundation/Foundation.h> #include <ApplicationServices/ApplicationServices.h> @@ -64,6 +72,7 @@ using namespace std; +using namespace ::com::sun::star; extern BOOL ImplSVMain(); @@ -815,6 +824,18 @@ bool AquaSalInstance::AnyInput( USHORT nType ) return false; } + if( nType & INPUT_TIMER ) + { + if( AquaSalTimer::pRunningTimer ) + { + NSDate* pDt = [AquaSalTimer::pRunningTimer fireDate]; + if( pDt && [pDt timeIntervalSinceNow] < 0 ) + { + return true; + } + } + } + unsigned/*NSUInteger*/ nEventMask = 0; if( nType & INPUT_MOUSE) nEventMask |= @@ -828,7 +849,7 @@ bool AquaSalInstance::AnyInput( USHORT nType ) nEventMask |= NSKeyDownMask | NSKeyUpMask | NSFlagsChangedMask; if( nType & INPUT_OTHER) nEventMask |= NSTabletPoint; - // TODO: INPUT_PAINT / INPUT_TIMER / more INPUT_OTHER + // TODO: INPUT_PAINT / more INPUT_OTHER if( !nType) return false; @@ -1017,6 +1038,83 @@ void* AquaSalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rRetur return (void*)""; } +// We need to re-encode file urls because osl_getFileURLFromSystemPath converts +// to UTF-8 before encoding non ascii characters, which is not what other apps expect. +static rtl::OUString translateToExternalUrl(const rtl::OUString& internalUrl) +{ + rtl::OUString extUrl; + + uno::Reference< lang::XMultiServiceFactory > sm = comphelper::getProcessServiceFactory(); + if (sm.is()) + { + uno::Reference< beans::XPropertySet > pset; + sm->queryInterface( getCppuType( &pset )) >>= pset; + if (pset.is()) + { + uno::Reference< uno::XComponentContext > context; + static const rtl::OUString DEFAULT_CONTEXT( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ); + pset->getPropertyValue(DEFAULT_CONTEXT) >>= context; + if (context.is()) + extUrl = uri::ExternalUriReferenceTranslator::create(context)->translateToExternal(internalUrl); + } + } + return extUrl; +} + +// #i104525# many versions of OSX have problems with some URLs: +// when an app requests OSX to add one of these URLs to the "Recent Items" list +// then this app gets killed (TextEdit, Preview, etc. and also OOo) +static bool isDangerousUrl( const rtl::OUString& rUrl ) +{ + // use a heuristic that detects all known cases since there is no official comment + // on the exact impact and root cause of the OSX bug + const int nLen = rUrl.getLength(); + const sal_Unicode* p = rUrl.getStr(); + for( int i = 0; i < nLen-3; ++i, ++p ) { + if( p[0] != '%' ) + continue; + // escaped percent? + if( (p[1] == '2') && (p[2] == '5') ) + return true; + // escapes are considered to be UTF-8 encoded + // => check for invalid UTF-8 leading byte + if( (p[1] != 'f') && (p[1] != 'F') ) + continue; + int cLowNibble = p[2]; + if( (cLowNibble >= '0' ) && (cLowNibble <= '9')) + return false; + if( cLowNibble >= 'a' ) + cLowNibble -= 'a' - 'A'; + if( (cLowNibble < 'A') || (cLowNibble >= 'C')) + return true; + } + + return false; +} + +void AquaSalInstance::AddToRecentDocumentList(const rtl::OUString& rFileUrl, const rtl::OUString& /*rMimeType*/) +{ + // Convert file URL for external use (see above) + rtl::OUString externalUrl = translateToExternalUrl(rFileUrl); + if( 0 == externalUrl.getLength() ) + externalUrl = rFileUrl; + + if( externalUrl.getLength() && !isDangerousUrl( externalUrl ) ) + { + NSString* pString = CreateNSString( externalUrl ); + NSURL* pURL = [NSURL URLWithString: pString]; + + if( pURL ) + { + NSDocumentController* pCtrl = [NSDocumentController sharedDocumentController]; + [pCtrl noteNewRecentDocumentURL: pURL]; + } + if( pString ) + [pString release]; + } +} + + // ----------------------------------------------------------------------- SalTimer* AquaSalInstance::CreateSalTimer() diff --git a/vcl/aqua/source/app/vclnsapp.mm b/vcl/aqua/source/app/vclnsapp.mm index 43d44c709c12..5a295b5e1171 100755 --- a/vcl/aqua/source/app/vclnsapp.mm +++ b/vcl/aqua/source/app/vclnsapp.mm @@ -104,6 +104,24 @@ return; } } + + // #i90083# handle frame switching + // FIXME: lousy workaround + if( (nModMask & (NSControlKeyMask|NSAlternateKeyMask)) == 0 ) + { + if( [[pEvent characters] isEqualToString: @"<"] || + [[pEvent characters] isEqualToString: @"~"] ) + { + [self cycleFrameForward: pFrame]; + return; + } + else if( [[pEvent characters] isEqualToString: @">"] || + [[pEvent characters] isEqualToString: @"`"] ) + { + [self cycleFrameBackward: pFrame]; + return; + } + } // get information whether the event was handled; keyDown returns nothing GetSalData()->maKeyEventAnswer[ pEvent ] = false; @@ -186,6 +204,84 @@ { [super sendEvent: pEvent]; } + +-(void)cycleFrameForward: (AquaSalFrame*)pCurFrame +{ + // find current frame in list + std::list< AquaSalFrame* >& rFrames( GetSalData()->maFrames ); + std::list< AquaSalFrame* >::iterator it = rFrames.begin(); + for( ; it != rFrames.end() && *it != pCurFrame; ++it ) + ; + if( it != rFrames.end() ) + { + // now find the next frame (or end) + do + { + ++it; + if( it != rFrames.end() ) + { + if( (*it)->mpDockMenuEntry != NULL && + (*it)->mbShown ) + { + [(*it)->getWindow() makeKeyAndOrderFront: NSApp]; + return; + } + } + } while( it != rFrames.end() ); + // cycle around, find the next up to pCurFrame + it = rFrames.begin(); + while( *it != pCurFrame ) + { + if( (*it)->mpDockMenuEntry != NULL && + (*it)->mbShown ) + { + [(*it)->getWindow() makeKeyAndOrderFront: NSApp]; + return; + } + ++it; + } + } +} + +-(void)cycleFrameBackward: (AquaSalFrame*)pCurFrame +{ + // do the same as cycleFrameForward only with a reverse iterator + + // find current frame in list + std::list< AquaSalFrame* >& rFrames( GetSalData()->maFrames ); + std::list< AquaSalFrame* >::reverse_iterator it = rFrames.rbegin(); + for( ; it != rFrames.rend() && *it != pCurFrame; ++it ) + ; + if( it != rFrames.rend() ) + { + // now find the next frame (or end) + do + { + ++it; + if( it != rFrames.rend() ) + { + if( (*it)->mpDockMenuEntry != NULL && + (*it)->mbShown ) + { + [(*it)->getWindow() makeKeyAndOrderFront: NSApp]; + return; + } + } + } while( it != rFrames.rend() ); + // cycle around, find the next up to pCurFrame + it = rFrames.rbegin(); + while( *it != pCurFrame ) + { + if( (*it)->mpDockMenuEntry != NULL && + (*it)->mbShown ) + { + [(*it)->getWindow() makeKeyAndOrderFront: NSApp]; + return; + } + ++it; + } + } +} -(NSMenu*)applicationDockMenu:(NSApplication *)sender { diff --git a/vcl/aqua/source/dtrans/DataFlavorMapping.cxx b/vcl/aqua/source/dtrans/DataFlavorMapping.cxx new file mode 100644 index 000000000000..af05f084a97e --- /dev/null +++ b/vcl/aqua/source/dtrans/DataFlavorMapping.cxx @@ -0,0 +1,711 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: DataFlavorMapping.cxx,v $ + * $Revision: 1.6 $ + * + * 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 "vcl/unohelp.hxx" +#include <DataFlavorMapping.hxx> +#include "HtmlFmtFlt.hxx" +#include "PictToBmpFlt.hxx" +#include "com/sun/star/datatransfer/UnsupportedFlavorException.hpp" +#include "com/sun/star/datatransfer/XMimeContentType.hpp" +#include "com/sun/star/lang/XMultiServiceFactory.hpp" +#include "com/sun/star/uno/Sequence.hxx" + +#include <rtl/ustring.hxx> +#include <rtl/memory.h> +#include <osl/endian.h> + +#include <vector> +#include <stdio.h> + +#include <premac.h> +#include <QuickTime/QuickTime.h> +#include <postmac.h> + +using namespace ::com::sun::star::datatransfer; +using namespace rtl; +using namespace ::com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace cppu; +using namespace std; + +namespace // private +{ + const Type CPPUTYPE_SEQINT8 = getCppuType((Sequence<sal_Int8>*)0); + const Type CPPUTYPE_OUSTRING = getCppuType( (OUString*)0 ); + + /* Determine whether or not a DataFlavor is valid. + */ + bool isValidFlavor(const DataFlavor& aFlavor) + { + size_t len = aFlavor.MimeType.getLength(); + Type dtype = aFlavor.DataType; + return ((len > 0) && ((dtype == CPPUTYPE_SEQINT8) || (dtype == CPPUTYPE_OUSTRING))); + } + + typedef vector<sal_Unicode> UnicodeBuffer; + + OUString NSStringToOUString(NSString* cfString) + { + BOOST_ASSERT(cfString && "Invalid parameter"); + + const char* utf8Str = [cfString UTF8String]; + unsigned int len = rtl_str_getLength(utf8Str); + + return OUString(utf8Str, len, RTL_TEXTENCODING_UTF8); + } + + NSString* OUStringToNSString(const OUString& ustring) + { + OString utf8Str = OUStringToOString(ustring, RTL_TEXTENCODING_UTF8); + return [NSString stringWithCString: utf8Str.getStr() encoding: NSUTF8StringEncoding]; + } + + + const NSString* PBTYPE_UT16 = @"CorePasteboardFlavorType 0x75743136"; + const NSString* PBTYPE_PICT = @"CorePasteboardFlavorType 0x50494354"; + const NSString* PBTYPE_HTML = @"CorePasteboardFlavorType 0x48544D4C"; + const NSString* PBTYPE_SODX = @"application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\""; + const NSString* PBTYPE_SESX = @"application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\""; + const NSString* PBTYPE_SLSDX = @"application/x-openoffice-linksrcdescriptor-xml;windows_formatname=\"Star Link Source Descriptor (XML)\""; + const NSString* PBTYPE_ESX = @"application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\""; + const NSString* PBTYPE_LSX = @"application/x-openoffice-link-source-xml;windows_formatname=\"Star Link Source (XML)\""; + const NSString* PBTYPE_EOX = @"application/x-openoffice-embedded-obj-xml;windows_formatname=\"Star Embedded Object (XML)\""; + const NSString* PBTYPE_SVXB = @"application/x-openoffice-svbx;windows_formatname=\"SVXB (StarView Bitmap/Animation)\""; + const NSString* PBTYPE_GDIMF = @"application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""; + const NSString* PBTYPE_WMF = @"application/x-openoffice-wmf;windows_formatname=\"Image WMF\""; + const NSString* PBTYPE_EMF = @"application/x-openoffice-emf;windows_formatname=\"Image EMF\""; + + const NSString* PBTYPE_DUMMY_INTERNAL = @"application/x-openoffice-internal"; + + const char* FLAVOR_SODX = "application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\""; + const char* FLAVOR_SESX = "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\""; + const char* FLAVOR_SLSDX = "application/x-openoffice-linksrcdescriptor-xml;windows_formatname=\"Star Link Source Descriptor (XML)\""; + const char* FLAVOR_ESX = "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\""; + const char* FLAVOR_LSX = "application/x-openoffice-link-source-xml;windows_formatname=\"Star Link Source (XML)\""; + const char* FLAVOR_EOX = "application/x-openoffice-embedded-obj-xml;windows_formatname=\"Star Embedded Object (XML)\""; + const char* FLAVOR_SVXB = "application/x-openoffice-svbx;windows_formatname=\"SVXB (StarView Bitmap/Animation)\""; + const char* FLAVOR_GDIMF = "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""; + const char* FLAVOR_WMF = "application/x-openoffice-wmf;windows_formatname=\"Image WMF\""; + const char* FLAVOR_EMF = "application/x-openoffice-emf;windows_formatname=\"Image EMF\""; + + const char* FLAVOR_DUMMY_INTERNAL = "application/x-openoffice-internal"; + + + struct FlavorMap + { + NSString* SystemFlavor; + const char* OOoFlavor; + const char* HumanPresentableName; + Type DataType; + }; + + /* At the moment it appears as if only MS Office pastes "public.html" to the clipboard. + */ + FlavorMap flavorMap[] = + { + { NSStringPboardType, "text/plain;charset=utf-16", "Unicode Text (UTF-16)", CPPUTYPE_OUSTRING }, + { NSRTFPboardType, "text/richtext", "Rich Text Format", CPPUTYPE_SEQINT8 }, + { NSPICTPboardType, "image/bmp", "Windows Bitmap", CPPUTYPE_SEQINT8 }, + { NSHTMLPboardType, "text/html", "Plain Html", CPPUTYPE_SEQINT8 }, + { NSFilenamesPboardType, "application/x-openoffice-filelist;windows_formatname=\"FileList\"", "FileList", CPPUTYPE_SEQINT8 }, + { PBTYPE_SESX, FLAVOR_SESX, "Star Embed Source (XML)", CPPUTYPE_SEQINT8 }, + { PBTYPE_SLSDX, FLAVOR_SLSDX, "Star Link Source Descriptor (XML)", CPPUTYPE_SEQINT8 }, + { PBTYPE_ESX, FLAVOR_ESX, "Star Embed Source (XML)", CPPUTYPE_SEQINT8 }, + { PBTYPE_LSX, FLAVOR_LSX, "Star Link Source (XML)", CPPUTYPE_SEQINT8 }, + { PBTYPE_EOX, FLAVOR_EOX, "Star Embedded Object (XML)", CPPUTYPE_SEQINT8 }, + { PBTYPE_SVXB, FLAVOR_SVXB, "SVXB (StarView Bitmap/Animation", CPPUTYPE_SEQINT8 }, + { PBTYPE_GDIMF, FLAVOR_GDIMF, "GDIMetaFile", CPPUTYPE_SEQINT8 }, + { PBTYPE_WMF, FLAVOR_WMF, "Windows MetaFile", CPPUTYPE_SEQINT8 }, + { PBTYPE_EMF, FLAVOR_EMF, "Windows Enhanced MetaFile", CPPUTYPE_SEQINT8 }, + { PBTYPE_SODX, FLAVOR_SODX, "Star Object Descriptor (XML)", CPPUTYPE_SEQINT8 }, + { PBTYPE_DUMMY_INTERNAL, FLAVOR_DUMMY_INTERNAL, "internal data",CPPUTYPE_SEQINT8 } + // { PBTYPE_UT16, "text/plain;charset=utf-16", "Unicode Text (UTF-16)", CPPUTYPE_OUSTRING } + // { kUTTypePICT, @"PICT", "image/x-macpict;windows_formatname=\"Mac Pict\"", "Mac Pict", CPPUTYPE_SEQINT8 } + // { kUTTypeHTML, @"HTML", "text/html", "Plain Html", CPPUTYPE_SEQINT8 } + }; + + + #define SIZE_FLAVOR_MAP (sizeof(flavorMap)/sizeof(FlavorMap)) + + + inline bool isByteSequenceType(const Type& theType) + { + return (theType == CPPUTYPE_SEQINT8); + } + + inline bool isOUStringType(const Type& theType) + { + return (theType == CPPUTYPE_OUSTRING); + } + +} // namespace private + + +//########################### + +/* A base class for other data provider. + */ +class DataProviderBaseImpl : public DataProvider +{ +public: + DataProviderBaseImpl(const Any& data); + DataProviderBaseImpl(id data); + virtual ~DataProviderBaseImpl(); + +protected: + Any mData; + //NSData* mSystemData; + id mSystemData; +}; + +DataProviderBaseImpl::DataProviderBaseImpl(const Any& data) : + mData(data), + mSystemData(nil) +{ +} + +DataProviderBaseImpl::DataProviderBaseImpl(id data) : + mSystemData(data) +{ + [mSystemData retain]; +} + + +DataProviderBaseImpl::~DataProviderBaseImpl() +{ + if (mSystemData) + { + [mSystemData release]; + } +} + +//################################# + +class UniDataProvider : public DataProviderBaseImpl +{ +public: + UniDataProvider(const Any& data); + + UniDataProvider(NSData* data); + + virtual NSData* getSystemData(); + + virtual Any getOOoData(); +}; + +UniDataProvider::UniDataProvider(const Any& data) : + DataProviderBaseImpl(data) +{ +} + +UniDataProvider::UniDataProvider(NSData* data) : + DataProviderBaseImpl(data) +{ +} + +NSData* UniDataProvider::getSystemData() +{ + OUString ustr; + mData >>= ustr; + + OString strUtf8; + ustr.convertToString(&strUtf8, RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS); + + return [NSData dataWithBytes: strUtf8.getStr() length: strUtf8.getLength()]; +} + +Any UniDataProvider::getOOoData() +{ + Any oOOData; + + if (mSystemData) + { + oOOData = makeAny(OUString(reinterpret_cast<const sal_Char*>([mSystemData bytes]), + [mSystemData length], + RTL_TEXTENCODING_UTF8)); + } + else + { + oOOData = mData; + } + + return oOOData; +} + +//########################### + +class ByteSequenceDataProvider : public DataProviderBaseImpl +{ +public: + ByteSequenceDataProvider(const Any& data); + + ByteSequenceDataProvider(NSData* data); + + virtual NSData* getSystemData(); + + virtual Any getOOoData(); +}; + +ByteSequenceDataProvider::ByteSequenceDataProvider(const Any& data) : + DataProviderBaseImpl(data) +{ +} + +ByteSequenceDataProvider::ByteSequenceDataProvider(NSData* data) : + DataProviderBaseImpl(data) +{ +} + + +NSData* ByteSequenceDataProvider::getSystemData() +{ + Sequence<sal_Int8> rawData; + mData >>= rawData; + + return [NSData dataWithBytes: rawData.getArray() length: rawData.getLength()]; +} + +Any ByteSequenceDataProvider::getOOoData() +{ + Any oOOData; + + if (mSystemData) + { + unsigned int flavorDataLength = [mSystemData length]; + Sequence<sal_Int8> byteSequence; + byteSequence.realloc(flavorDataLength); + memcpy(byteSequence.getArray(), [mSystemData bytes], flavorDataLength); + oOOData = makeAny(byteSequence); + } + else + { + oOOData = mData; + } + + return oOOData; +} + + +//########################### + +class HTMLFormatDataProvider : public DataProviderBaseImpl +{ +public: + HTMLFormatDataProvider(const Any& data); + + HTMLFormatDataProvider(NSData* data); + + virtual NSData* getSystemData(); + + virtual Any getOOoData(); +}; + +HTMLFormatDataProvider::HTMLFormatDataProvider(const Any& data) : + DataProviderBaseImpl(data) +{ +} + +HTMLFormatDataProvider::HTMLFormatDataProvider(NSData* data) : + DataProviderBaseImpl(data) +{ +} + +NSData* HTMLFormatDataProvider::getSystemData() +{ + Sequence<sal_Int8> textHtmlData; + mData >>= textHtmlData; + + Sequence<sal_Int8> htmlFormatData = TextHtmlToHTMLFormat(textHtmlData); + + return [NSData dataWithBytes: htmlFormatData.getArray() length: htmlFormatData.getLength()]; +} + +Any HTMLFormatDataProvider::getOOoData() +{ + Any oOOData; + + if (mSystemData) + { + unsigned int flavorDataLength = [mSystemData length]; + Sequence<sal_Int8> unkHtmlData; + + unkHtmlData.realloc(flavorDataLength); + memcpy(unkHtmlData.getArray(), [mSystemData bytes], flavorDataLength); + + Sequence<sal_Int8>* pPlainHtml = &unkHtmlData; + Sequence<sal_Int8> plainHtml; + + if (isHTMLFormat(unkHtmlData)) + { + plainHtml = HTMLFormatToTextHtml(unkHtmlData); + pPlainHtml = &plainHtml; + } + + oOOData = makeAny(*pPlainHtml); + } + else + { + oOOData = mData; + } + + return oOOData; +} + +//########################### + +class BMPDataProvider : public DataProviderBaseImpl +{ +public: + BMPDataProvider(const Any& data); + + BMPDataProvider(NSData* data); + + virtual NSData* getSystemData(); + + virtual Any getOOoData(); +}; + +BMPDataProvider::BMPDataProvider(const Any& data) : + DataProviderBaseImpl(data) +{ +} + +BMPDataProvider::BMPDataProvider(NSData* data) : + DataProviderBaseImpl(data) +{ +} + +NSData* BMPDataProvider::getSystemData() +{ + Sequence<sal_Int8> bmpData; + mData >>= bmpData; + + Sequence<sal_Int8> pictData; + NSData* sysData = NULL; + + if (BMPtoPICT(bmpData, pictData)) + { + sysData = [NSData dataWithBytes: pictData.getArray() length: pictData.getLength()]; + } + + return sysData; +} + +/* At the moment the OOo 'PCT' filter is not good enough to be used + and there is no flavor defined for exchanging 'PCT' with OOo so + we will at the moment convert 'PCT' to a Windows BMP and provide + this to OOo +*/ +Any BMPDataProvider::getOOoData() +{ + Any oOOData; + + if (mSystemData) + { + unsigned int flavorDataLength = [mSystemData length]; + Sequence<sal_Int8> pictData(flavorDataLength); + + memcpy(pictData.getArray(), [mSystemData bytes], flavorDataLength); + + Sequence<sal_Int8> bmpData; + + if (PICTtoBMP(pictData, bmpData)) + { + oOOData = makeAny(bmpData); + } + } + else + { + oOOData = mData; + } + + return oOOData; +} + +//###################### + +class FileListDataProvider : public DataProviderBaseImpl +{ +public: + FileListDataProvider(const Any& data); + FileListDataProvider(NSArray* data); + + virtual NSData* getSystemData(); + virtual Any getOOoData(); +}; + +FileListDataProvider::FileListDataProvider(const Any& data) : + DataProviderBaseImpl(data) +{ +} + +FileListDataProvider::FileListDataProvider(NSArray* data) : + DataProviderBaseImpl(data) +{ +} + +NSData* FileListDataProvider::getSystemData() +{ + return [NSData data]; +} + +Any FileListDataProvider::getOOoData() +{ + Any oOOData; + + if (mSystemData) + { + size_t length = [mSystemData count]; + size_t lenSeqRequired = 0; + + for (size_t i = 0; i < length; i++) + { + NSString* fname = [mSystemData objectAtIndex: i]; + lenSeqRequired += [fname maximumLengthOfBytesUsingEncoding: NSUnicodeStringEncoding] + sizeof(unichar); + } + + Sequence<sal_Int8> oOOFileList(lenSeqRequired); + unichar* pBuffer = reinterpret_cast<unichar*>(oOOFileList.getArray()); + rtl_zeroMemory(pBuffer, lenSeqRequired); + + for (size_t i = 0; i < length; i++) + { + NSString* fname = [mSystemData objectAtIndex: i]; + [fname getCharacters: pBuffer]; + size_t l = [fname length]; + pBuffer += l + 1; + } + + oOOData = makeAny(oOOFileList); + } + else + { + oOOData = mData; + } + + return oOOData; +} + +//########################### + +DataFlavorMapper::DataFlavorMapper() +{ + Reference<XMultiServiceFactory> mrServiceManager = vcl::unohelper::GetMultiServiceFactory(); + mrXMimeCntFactory = Reference<XMimeContentTypeFactory>(mrServiceManager->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.MimeContentTypeFactory"))), UNO_QUERY); + + if (!mrXMimeCntFactory.is()) + throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Cannot create com.sun.star.datatransfer.MimeContentTypeFactory")), NULL); +} + +DataFlavor DataFlavorMapper::systemToOpenOfficeFlavor(NSString* systemDataFlavor) const +{ + DataFlavor oOOFlavor; + + for (size_t i = 0; i < SIZE_FLAVOR_MAP; i++) + { + if ([systemDataFlavor caseInsensitiveCompare: flavorMap[i].SystemFlavor] == NSOrderedSame) + { + oOOFlavor.MimeType = OUString::createFromAscii(flavorMap[i].OOoFlavor); + oOOFlavor.HumanPresentableName = OUString(RTL_CONSTASCII_USTRINGPARAM(flavorMap[i].HumanPresentableName)); + oOOFlavor.DataType = flavorMap[i].DataType; + return oOOFlavor; + } + } // for + + return oOOFlavor; +} + +NSString* DataFlavorMapper::openOfficeToSystemFlavor(const DataFlavor& oOOFlavor) const +{ + NSString* sysFlavor = NULL; + + for (size_t i = 0; i < SIZE_FLAVOR_MAP; i++) + { + if (oOOFlavor.MimeType.compareToAscii(flavorMap[i].OOoFlavor, strlen(flavorMap[i].OOoFlavor)) == 0) + { + sysFlavor = flavorMap[i].SystemFlavor; + } + } + + return sysFlavor; +} + +DataProviderPtr_t DataFlavorMapper::getDataProvider(NSString* systemFlavor, Reference<XTransferable> rTransferable) const +{ + DataProviderPtr_t dp; + + try + { + DataFlavor oOOFlavor = systemToOpenOfficeFlavor(systemFlavor); + + Any data = rTransferable->getTransferData(oOOFlavor); + + if (isByteSequenceType(data.getValueType())) + { + if ([systemFlavor caseInsensitiveCompare: NSHTMLPboardType] == NSOrderedSame) + { + dp = DataProviderPtr_t(new HTMLFormatDataProvider(data)); + } + else if ([systemFlavor caseInsensitiveCompare: NSPICTPboardType] == NSOrderedSame) + { + dp = DataProviderPtr_t(new BMPDataProvider(data)); + } + else if ([systemFlavor caseInsensitiveCompare: NSFilenamesPboardType] == NSOrderedSame) + { + dp = DataProviderPtr_t(new FileListDataProvider(data)); + } + else + { + dp = DataProviderPtr_t(new ByteSequenceDataProvider(data)); + } + } + else // Must be OUString type + { + BOOST_ASSERT(isOUStringType(data.getValueType())); + dp = DataProviderPtr_t(new UniDataProvider(data)); + } + } + catch(UnsupportedFlavorException&) + { + // Somebody violates the contract of the clipboard + // interface @see XTransferable + } + + return dp; +} + +DataProviderPtr_t DataFlavorMapper::getDataProvider(const NSString* systemFlavor, NSArray* systemData) const +{ + return DataProviderPtr_t(new FileListDataProvider(systemData)); +} + +DataProviderPtr_t DataFlavorMapper::getDataProvider(const NSString* systemFlavor, NSData* systemData) const +{ + DataProviderPtr_t dp; + + if ([systemFlavor caseInsensitiveCompare: NSStringPboardType] == NSOrderedSame) + { + dp = DataProviderPtr_t(new UniDataProvider(systemData)); + } + else if ([systemFlavor caseInsensitiveCompare: NSHTMLPboardType] == NSOrderedSame) + { + dp = DataProviderPtr_t(new HTMLFormatDataProvider(systemData)); + } + else if ([systemFlavor caseInsensitiveCompare: NSPICTPboardType] == NSOrderedSame) + { + dp = DataProviderPtr_t(new BMPDataProvider(systemData)); + } + else if ([systemFlavor caseInsensitiveCompare: NSFilenamesPboardType] == NSOrderedSame) + { + //dp = DataProviderPtr_t(new FileListDataProvider(systemData)); + } + else + { + dp = DataProviderPtr_t(new ByteSequenceDataProvider(systemData)); + } + + return dp; +} + +bool DataFlavorMapper::isValidMimeContentType(const rtl::OUString& contentType) const +{ + bool result = true; + + try + { + Reference<XMimeContentType> xCntType(mrXMimeCntFactory->createMimeContentType(contentType)); + } + catch( IllegalArgumentException& ) + { + result = false; + } + + return result; +} + +NSArray* DataFlavorMapper::flavorSequenceToTypesArray(const com::sun::star::uno::Sequence<com::sun::star::datatransfer::DataFlavor>& flavors) const +{ + sal_uInt32 nFlavors = flavors.getLength(); + NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity: 1]; + + for (sal_uInt32 i = 0; i < nFlavors; i++) + { + NSString* str = openOfficeToSystemFlavor(flavors[i]); + + if (str != NULL) + { + [array addObject: str]; + } + } + + // #i89462# #i90747# + // in case no system flavor was found to report + // report at least one so D&D between OOo targets works + if( [array count] == 0 ) + { + [array addObject: PBTYPE_DUMMY_INTERNAL]; + } + + return [array autorelease]; +} + +com::sun::star::uno::Sequence<com::sun::star::datatransfer::DataFlavor> DataFlavorMapper::typesArrayToFlavorSequence(NSArray* types) const +{ + int nFormats = [types count]; + Sequence<DataFlavor> flavors; + + for (int i = 0; i < nFormats; i++) + { + NSString* sysFormat = [types objectAtIndex: i]; + DataFlavor oOOFlavor = systemToOpenOfficeFlavor(sysFormat); + + if (isValidFlavor(oOOFlavor)) + { + flavors.realloc(flavors.getLength() + 1); + flavors[flavors.getLength() - 1] = oOOFlavor; + } + } + + return flavors; +} + + +NSArray* DataFlavorMapper::getAllSupportedPboardTypes() const +{ + NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity: SIZE_FLAVOR_MAP]; + + for (sal_uInt32 i = 0; i < SIZE_FLAVOR_MAP; i++) + { + [array addObject: flavorMap[i].SystemFlavor]; + } + + return [array autorelease]; +} diff --git a/vcl/aqua/source/dtrans/DataFlavorMapping.hxx b/vcl/aqua/source/dtrans/DataFlavorMapping.hxx new file mode 100644 index 000000000000..03cb77e319f7 --- /dev/null +++ b/vcl/aqua/source/dtrans/DataFlavorMapping.hxx @@ -0,0 +1,141 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: DataFlavorMapping.hxx,v $ + * $Revision: 1.4 $ + * + * 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 INCLUDED_DATAFLAVORMAPPING_HXX_ +#define INCLUDED_DATAFLAVORMAPPING_HXX_ + +#include <com/sun/star/datatransfer/DataFlavor.hpp> +#include <com/sun/star/datatransfer/XMimeContentTypeFactory.hpp> +#include <com/sun/star/datatransfer/XTransferable.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> + +#include <premac.h> +#import <Cocoa/Cocoa.h> +#include <postmac.h> + +#include <memory> +#include <boost/shared_ptr.hpp> + + +/* An interface to get the clipboard data in either + system or OOo format. + */ +class DataProvider +{ +public: + virtual ~DataProvider() {}; + + /* Get the clipboard data in the system format. + The caller has to retain/release the returned + CFDataRef on demand. + */ + virtual NSData* getSystemData() = 0; + + /* Get the clipboard data in OOo format. + */ + virtual com::sun::star::uno::Any getOOoData() = 0; +}; + +typedef std::auto_ptr<DataProvider> DataProviderPtr_t; + + +//################################ + + +class DataFlavorMapper +{ +public: + /* Initialialize a DataFavorMapper instance. Throws a RuntimeException in case the XMimeContentTypeFactory service + cannot be created. + */ + DataFlavorMapper(); + + + /* Map a system data flavor to an OpenOffice data flavor. + Return an empty string if there is not suiteable + mapping from a system data flavor to a OpenOffice data + flavor. + */ + com::sun::star::datatransfer::DataFlavor systemToOpenOfficeFlavor(NSString* systemDataFlavor) const; + + + /* Map an OpenOffice data flavor to a system data flavor. + If there is no suiteable mapping available NULL will + be returned. + */ + NSString* openOfficeToSystemFlavor(const com::sun::star::datatransfer::DataFlavor& oooDataFlavor) const; + + + /* Get a data provider which is able to provide the data 'rTransferable' offers in a format that can + be put on to the system clipboard. + */ + DataProviderPtr_t getDataProvider(NSString* systemFlavor, + const com::sun::star::uno::Reference< com::sun::star::datatransfer::XTransferable > rTransferable) const; + + + + /* Get a data provider which is able to provide 'systemData' in the OOo expected format. + */ + DataProviderPtr_t getDataProvider(const NSString* systemFlavor, NSArray* systemData) const; + + + /* Get a data provider which is able to provide 'systemData' in the OOo expected format. + */ + DataProviderPtr_t getDataProvider(const NSString* systemFlavor, NSData* systemData) const; + + + /* Translate a sequence of DataFlavors into a NSArray of system types. + Only those DataFlavors for which a suitable mapping to a system + type exist will be contained in the returned types array. + */ + NSArray* flavorSequenceToTypesArray(const com::sun::star::uno::Sequence<com::sun::star::datatransfer::DataFlavor>& flavors) const; + + /* Translate a NSArray of system types into a sequence of DataFlavors. + Only those types for which a suitable mapping to a DataFlavor + exist will be contained in the new DataFlavor Sequence. + */ + com::sun::star::uno::Sequence<com::sun::star::datatransfer::DataFlavor> typesArrayToFlavorSequence(NSArray* types) const; + + /* Returns an NSArray containing all pasteboard types supported by OOo + */ + NSArray* DataFlavorMapper::getAllSupportedPboardTypes() const; + +private: + /* Determines if the provided Mime content type is valid. + */ + bool isValidMimeContentType(const rtl::OUString& contentType) const; + +private: + ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XMimeContentTypeFactory> mrXMimeCntFactory; +}; + +typedef boost::shared_ptr<DataFlavorMapper> DataFlavorMapperPtr_t; + +#endif diff --git a/vcl/aqua/source/dtrans/DragActionConversion.cxx b/vcl/aqua/source/dtrans/DragActionConversion.cxx new file mode 100644 index 000000000000..793dcca503a0 --- /dev/null +++ b/vcl/aqua/source/dtrans/DragActionConversion.cxx @@ -0,0 +1,95 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: DragActionConversion.cxx,v $ + * $Revision: 1.3 $ + * + * 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 "DragActionConversion.hxx" +#include <com/sun/star/datatransfer/dnd/DNDConstants.hpp> + + +using namespace com::sun::star::datatransfer::dnd; + + +/* Convert office drag actions as defined in + <type>com::sun::star::datatransfer::dnd::DNDConstants</type> + into system conform drag actions. + */ +unsigned int OfficeToSystemDragActions(sal_Int8 dragActions) +{ + unsigned int actions = NSDragOperationNone; + + if (dragActions & DNDConstants::ACTION_COPY) + { + actions |= NSDragOperationCopy; + } + + if (dragActions & DNDConstants::ACTION_MOVE) + { + actions |= NSDragOperationMove; + } + + if (dragActions & DNDConstants::ACTION_LINK) + { + actions |= NSDragOperationLink; + } + + return actions; +} + +/* Convert system conform drag actions into office conform + drag actions as defined in + <type>com::sun::star::datatransfer::dnd::DNDConstants</type>. + */ +sal_Int8 SystemToOfficeDragActions(unsigned int dragActions) +{ + sal_Int8 actions = DNDConstants::ACTION_NONE; + + if (dragActions & NSDragOperationCopy) + { + actions |= DNDConstants::ACTION_COPY; + } + + if (dragActions & NSDragOperationMove) + { + actions |= DNDConstants::ACTION_MOVE; + } + + if (dragActions & NSDragOperationLink) + { + actions |= DNDConstants::ACTION_LINK; + } + + // We map NSDragOperationGeneric to ACTION_DEFAULT to + // signal that we have to decide for a drag action + if (dragActions & NSDragOperationGeneric) + { + actions |= DNDConstants::ACTION_DEFAULT; + } + + return actions; +} diff --git a/vcl/aqua/source/dtrans/DragActionConversion.hxx b/vcl/aqua/source/dtrans/DragActionConversion.hxx new file mode 100644 index 000000000000..137e2af30be1 --- /dev/null +++ b/vcl/aqua/source/dtrans/DragActionConversion.hxx @@ -0,0 +1,49 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: DragActionConversion.hxx,v $ + * $Revision: 1.3 $ + * + * 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 <sal/types.h> + +#include <premac.h> +#import <Cocoa/Cocoa.h> +#include <postmac.h> + + +/* Convert office drag actions as defined in + <type>com::sun::star::datatransfer::dnd::DNDConstants</type> + into system conform drag actions. + */ +unsigned int OfficeToSystemDragActions(sal_Int8 dragActions); + +/* Convert system conform drag actions into office conform + drag actions as defined in + <type>com::sun::star::datatransfer::dnd::DNDConstants</type>. + */ +sal_Int8 SystemToOfficeDragActions(unsigned int dragActions); diff --git a/vcl/aqua/source/dtrans/DragSource.cxx b/vcl/aqua/source/dtrans/DragSource.cxx new file mode 100644 index 000000000000..074ce5c6c318 --- /dev/null +++ b/vcl/aqua/source/dtrans/DragSource.cxx @@ -0,0 +1,366 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: DragSource.cxx,v $ + * $Revision: 1.4 $ + * + * 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 <com/sun/star/datatransfer/dnd/DNDConstants.hpp> +#include <com/sun/star/datatransfer/XTransferable.hpp> +#include <com/sun/star/awt/MouseButton.hpp> +#include <rtl/unload.h> + +#include "comphelper/makesequence.hxx" + +#include "DragSource.hxx" +#include "DragSourceContext.hxx" +#include "aqua_clipboard.hxx" +#include "DragActionConversion.hxx" + +#include <rtl/ustring.h> +#include <memory> + + +using namespace rtl; +using namespace cppu; +using namespace osl; +using namespace com::sun::star::datatransfer; +using namespace com::sun::star::datatransfer::clipboard; +using namespace com::sun::star::datatransfer::dnd; +using namespace com::sun::star::datatransfer::dnd::DNDConstants; +using namespace com::sun::star::uno; +using namespace com::sun::star::awt::MouseButton; +using namespace com::sun::star::awt; +using namespace com::sun::star::lang; +using namespace comphelper; +using namespace std; + + +// For OOo internal D&D we provide the Transferable without NSDragPboard +// interference as a shortcut +Reference<XTransferable> DragSource::g_XTransferable = Reference<XTransferable>(); +NSView* DragSource::g_DragSourceView = nil; +bool DragSource::g_DropSuccessSet = false; +bool DragSource::g_DropSuccess = false; + + +OUString dragSource_getImplementationName() +{ + return OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.datatransfer.dnd.OleDragSource_V1")); +} + +Sequence<OUString> dragSource_getSupportedServiceNames() +{ + return makeSequence(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.dnd.OleDragSource"))); +} + + +@implementation DragSourceHelper; + +-(DragSourceHelper*)initWithDragSource: (DragSource*) pds +{ + self = [super init]; + + if (self) + { + mDragSource = pds; + } + + return self; +} + + +-(void)mouseDown: (NSEvent*)theEvent +{ + mDragSource->saveMouseEvent(theEvent); +} + + +-(void)mouseDragged: (NSEvent*)theEvent +{ + mDragSource->saveMouseEvent(theEvent); +} + + +-(unsigned int)draggingSourceOperationMaskForLocal: (MacOSBOOL)isLocal +{ + return mDragSource->getSupportedDragOperations(isLocal); +} + + +-(void)draggedImage:(NSImage*)anImage beganAt:(NSPoint)aPoint +{ + DragSourceDragEvent dsde(static_cast<OWeakObject*>(mDragSource), + new DragSourceContext(mDragSource), + mDragSource, + DNDConstants::ACTION_COPY, + DNDConstants::ACTION_COPY); + + mDragSource->mXDragSrcListener->dragEnter(dsde); +} + + +-(void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation +{ + // an internal drop can accept the drop but fail with dropComplete( false ) + // this is different than the Cocoa API + bool bDropSuccess = operation != NSDragOperationNone; + if( DragSource::g_DropSuccessSet ) + bDropSuccess = DragSource::g_DropSuccess; + + DragSourceDropEvent dsde(static_cast<OWeakObject*>(mDragSource), + new DragSourceContext(mDragSource), + static_cast< XDragSource* >(mDragSource), + SystemToOfficeDragActions(operation), + bDropSuccess ); + + mDragSource->mXDragSrcListener->dragDropEnd(dsde); + mDragSource->mXDragSrcListener = Reference<XDragSourceListener>(); +} + + +-(void)draggedImage:(NSImage *)draggedImage movedTo:(NSPoint)screenPoint +{ + DragSourceDragEvent dsde(static_cast<OWeakObject*>(mDragSource), + new DragSourceContext(mDragSource), + mDragSource, + DNDConstants::ACTION_COPY, + DNDConstants::ACTION_COPY); + + mDragSource->mXDragSrcListener->dragOver(dsde); +} + +@end + + +DragSource::DragSource(): + WeakComponentImplHelper3<XDragSource, XInitialization, XServiceInfo>(m_aMutex), + mView(NULL), + mLastMouseEventBeforeStartDrag(nil), + m_MouseButton(0) +{ +} + + +DragSource::~DragSource() +{ + [(id <MouseEventListener>)mView unregisterMouseEventListener: mDragSourceHelper]; + [mDragSourceHelper release]; +} + + +void SAL_CALL DragSource::initialize(const Sequence< Any >& aArguments) + throw(Exception) +{ + if (aArguments.getLength() < 2) + { + throw Exception(OUString(RTL_CONSTASCII_USTRINGPARAM("DragSource::initialize: Not enough parameter.")), + static_cast<OWeakObject*>(this)); + } + + Any pNSView = aArguments[1]; + sal_uInt64 tmp = 0; + pNSView >>= tmp; + mView = (NSView*)tmp; + + /* All SalFrameView the base class for all VCL system views inherits from + NSView in order to get mouse and other events. This is the only way to + get these events. In order to start a drag operation we need to provide + the mouse event which was the trigger. SalFrameView therefor implements + a hook mechanism so that we can get mouse events for our purpose. + */ + if (![mView respondsToSelector: @selector(registerMouseEventListener:)] || + ![mView respondsToSelector: @selector(unregisterMouseEventListener:)]) + { + throw Exception(OUString(RTL_CONSTASCII_USTRINGPARAM("DragSource::initialize: Provided view doesn't support mouse listener")), + static_cast<OWeakObject*>(this)); + } + + mDragSourceHelper = [[DragSourceHelper alloc] initWithDragSource: this]; + + if (mDragSourceHelper == nil) + { + throw Exception(OUString(RTL_CONSTASCII_USTRINGPARAM("DragSource::initialize: Cannot initialize DragSource")), + static_cast<OWeakObject*>(this)); + } + + [(id <MouseEventListener>)mView registerMouseEventListener: mDragSourceHelper]; +} + + +//---------------------------------------------------- +// XDragSource +//---------------------------------------------------- + +sal_Bool SAL_CALL DragSource::isDragImageSupported( ) + throw(RuntimeException) +{ + return true; +} + + +sal_Int32 SAL_CALL DragSource::getDefaultCursor( sal_Int8 /*dragAction*/ ) + throw( IllegalArgumentException, RuntimeException) +{ + return 0; +} + + +void SAL_CALL DragSource::startDrag(const DragGestureEvent& trigger, + sal_Int8 sourceActions, + sal_Int32 cursor, + sal_Int32 image, + const Reference<XTransferable >& transferable, + const Reference<XDragSourceListener >& listener ) + throw( RuntimeException) +{ + MutexGuard guard(m_aMutex); + + OSL_ASSERT(listener.is() && "DragSource::startDrag: No XDragSourceListener provided\n"); + OSL_ASSERT(transferable.is() && "DragSource::startDrag: No transferable provided\n"); + + trigger.Event >>= mMouseEvent; + m_MouseButton= mMouseEvent.Buttons; + mXDragSrcListener = listener; + mXCurrentContext = static_cast<XDragSourceContext*>(new DragSourceContext(this)); + auto_ptr<AquaClipboard> clipb(new AquaClipboard(NULL, false)); + g_XTransferable = transferable; + clipb->setContents(g_XTransferable, Reference<XClipboardOwner>()); + mDragSourceActions = sourceActions; + g_DragSourceView = mView; + + NSSize sz; + sz.width = 5; + sz.height = 5; + + NSImage* dragImage; + dragImage = [[NSImage alloc] initWithSize: sz]; + + NSRect bounds; + bounds.origin = NSMakePoint(0,0); + bounds.size = sz; + + [dragImage lockFocus]; + [[NSColor blackColor] set]; + [NSBezierPath fillRect: bounds]; + [dragImage unlockFocus]; + + NSPoint pInWnd = [mLastMouseEventBeforeStartDrag locationInWindow]; + NSPoint p; + p = [mView convertPoint: pInWnd fromView: nil]; + p.x = p.x - sz.width/2; + p.y = p.y - sz.height/2; + + // reset drop success flags + g_DropSuccessSet = false; + g_DropSuccess = false; + + [mView dragImage: dragImage + at: p + offset: NSMakeSize(0,0) + event: mLastMouseEventBeforeStartDrag + pasteboard: clipb->getPasteboard() + source: mDragSourceHelper + slideBack: 1]; + + [dragImage release]; + + g_XTransferable = Reference<XTransferable>(); + g_DragSourceView = nil; + + // reset drop success flags + g_DropSuccessSet = false; + g_DropSuccess = false; +} + + +// In order to initiate a D&D operation we need to +// provide the triggering mouse event which we get +// from the SalFrameView that is associated with +// this DragSource +void DragSource::saveMouseEvent(NSEvent* theEvent) +{ + if (mLastMouseEventBeforeStartDrag != nil) + { + [mLastMouseEventBeforeStartDrag release]; + } + + mLastMouseEventBeforeStartDrag = theEvent; +} + + +/* isLocal indicates whether or not the DnD operation is OOo + internal. + */ +unsigned int DragSource::getSupportedDragOperations(bool isLocal) const +{ + unsigned int srcActions = OfficeToSystemDragActions(mDragSourceActions); + + if (isLocal) + { + // Support NSDragOperation generic which means we can + // decide which D&D operation to choose. We map + // NSDragOperationGenric to DNDConstants::ACTION_DEFAULT + // in SystemToOfficeDragActions to signal this and + // use it in DropTarget::determineDropAction + srcActions |= NSDragOperationGeneric; + } + else + { + // Mask out link and move operations on external DnD + srcActions &= ~(NSDragOperationMove | NSDragOperationLink); + } + + return srcActions; +} + + +//################################ +// XServiceInfo +//################################ + +OUString SAL_CALL DragSource::getImplementationName( ) throw (RuntimeException) +{ + return dragSource_getImplementationName(); +} + + +sal_Bool SAL_CALL DragSource::supportsService( const OUString& ServiceName ) throw (RuntimeException) +{ + return ServiceName.equals(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.dnd.OleDragSource"))); +} + + +Sequence< OUString > SAL_CALL DragSource::getSupportedServiceNames() throw (RuntimeException) +{ + return dragSource_getSupportedServiceNames(); +} + + + + diff --git a/vcl/aqua/source/dtrans/DragSource.hxx b/vcl/aqua/source/dtrans/DragSource.hxx new file mode 100644 index 000000000000..1268a466adf3 --- /dev/null +++ b/vcl/aqua/source/dtrans/DragSource.hxx @@ -0,0 +1,143 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: DragSource.hxx,v $ + * $Revision: 1.4 $ + * + * 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 _DRAGSOURCE_HXX_ +#define _DRAGSOURCE_HXX_ + +#include <com/sun/star/datatransfer/dnd/XDragSource.hpp> +#include <com/sun/star/datatransfer/dnd/XDragSourceContext.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <cppuhelper/compbase3.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/basemutex.hxx> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <osl/thread.h> +#include <com/sun/star/awt/MouseEvent.hpp> + +#include <boost/utility.hpp> + +#include <premac.h> +#import <Cocoa/Cocoa.h> +#include <postmac.h> + + +class DragSource; + +/* The functions declared in this protocol are actually + declared in vcl/aqua/inc/salframe.h. Because we want + to avoid importing VCL headers in UNO services and + on the other hand want to avoid warnings caused by + gcc complaining about unknowness of these functions + we declare them in a protocol here and cast at the + appropriate places. +*/ +@protocol MouseEventListener +-(void)registerMouseEventListener:(id)theHandler; +-(void)unregisterMouseEventListener:(id)theHandler; +@end + + +@interface DragSourceHelper : NSObject +{ + DragSource* mDragSource; +} + +-(DragSourceHelper*)initWithDragSource: (DragSource*) pds; + +-(void)mouseDown: (NSEvent*)theEvent; +-(void)mouseDragged: (NSEvent*)theEvent; + +-(unsigned int)draggingSourceOperationMaskForLocal:(MacOSBOOL)isLocal; +-(void)draggedImage:(NSImage*)anImage beganAt:(NSPoint)aPoint; +-(void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation; +-(void)draggedImage:(NSImage *)draggedImage movedTo:(NSPoint)screenPoint; + +@end + + +class DragSource : public ::cppu::BaseMutex, + public ::cppu::WeakComponentImplHelper3< com::sun::star::datatransfer::dnd::XDragSource, + com::sun::star::lang::XInitialization, + com::sun::star::lang::XServiceInfo >, + private ::boost::noncopyable +{ +public: + DragSource(); + virtual ~DragSource(); + + // XInitialization + virtual void SAL_CALL initialize( const com::sun::star::uno::Sequence< com::sun::star::uno::Any >& aArguments ) + throw(com::sun::star::uno::Exception/*, com::sun::star::uno::RuntimeException*/); + + // XDragSource + virtual sal_Bool SAL_CALL isDragImageSupported( ) throw(com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getDefaultCursor(sal_Int8 dragAction) + throw(com::sun::star::lang::IllegalArgumentException, com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL startDrag( const com::sun::star::datatransfer::dnd::DragGestureEvent& trigger, + sal_Int8 sourceActions, + sal_Int32 cursor, + sal_Int32 image, + const com::sun::star::uno::Reference< com::sun::star::datatransfer::XTransferable >& transferable, + const com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDragSourceListener >& listener ) + 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); + + virtual void saveMouseEvent(NSEvent* theEvent); + virtual unsigned int getSupportedDragOperations(bool isLocal) const; + +public: + // The context notifies the XDragSourceListeners + com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDragSourceContext > mXCurrentContext; + + id mView; + NSEvent* mLastMouseEventBeforeStartDrag; + DragSourceHelper* mDragSourceHelper; + com::sun::star::awt::MouseEvent mMouseEvent; + com::sun::star::uno::Reference< com::sun::star::datatransfer::XTransferable > mXTransferable; + com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDragSourceListener > mXDragSrcListener; + // The mouse button that set off the drag and drop operation + short m_MouseButton; + sal_Int8 mDragSourceActions; + + static com::sun::star::uno::Reference< com::sun::star::datatransfer::XTransferable > g_XTransferable; + static NSView* g_DragSourceView; + static bool g_DropSuccessSet; + static bool g_DropSuccess; + +}; + + +#endif diff --git a/vcl/aqua/source/dtrans/DragSourceContext.cxx b/vcl/aqua/source/dtrans/DragSourceContext.cxx new file mode 100644 index 000000000000..cd657a6147e9 --- /dev/null +++ b/vcl/aqua/source/dtrans/DragSourceContext.cxx @@ -0,0 +1,77 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: DragSourceContext.cxx,v $ + * $Revision: 1.3 $ + * + * 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 <com/sun/star/datatransfer/dnd/DNDConstants.hpp> + +#include "DragSourceContext.hxx" +#include <rtl/unload.h> + + +using namespace com::sun::star::datatransfer::dnd; +using namespace com::sun::star::datatransfer::dnd::DNDConstants; +using namespace com::sun::star::uno; +using namespace cppu; + +DragSourceContext::DragSourceContext( DragSource* pSource) : + WeakComponentImplHelper1<XDragSourceContext>(m_aMutex), + m_pDragSource( pSource) +{ +} + +DragSourceContext::~DragSourceContext() +{ +} + +sal_Int32 SAL_CALL DragSourceContext::getCurrentCursor( ) + throw( RuntimeException) +{ + return 0; +} + +void SAL_CALL DragSourceContext::setCursor( sal_Int32 /*cursorId*/ ) + throw( RuntimeException) +{ +} + +void SAL_CALL DragSourceContext::setImage( sal_Int32 /*imageId*/ ) + throw( RuntimeException) +{ +} + +void SAL_CALL DragSourceContext::transferablesFlavorsChanged( ) + throw( RuntimeException) +{ +} + + diff --git a/vcl/aqua/source/dtrans/DragSourceContext.hxx b/vcl/aqua/source/dtrans/DragSourceContext.hxx new file mode 100644 index 000000000000..3526ec846fd6 --- /dev/null +++ b/vcl/aqua/source/dtrans/DragSourceContext.hxx @@ -0,0 +1,75 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: DragSourceContext.hxx,v $ + * $Revision: 1.3 $ + * + * 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 _DRAGSOURCECONTEXT_HXX_ +#define _DRAGSOURCECONTEXT_HXX_ + +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/datatransfer/dnd/XDragSourceContext.hpp> +#include <cppuhelper/compbase1.hxx> +#include <cppuhelper/basemutex.hxx> + +#include <boost/utility.hpp> + +#include "DragSource.hxx" + +// This class fires events to XDragSourceListener implementations. +// Of that interface only dragDropEnd and dropActionChanged are called. +// The functions dragEnter, dragExit and dragOver are not supported +// currently. +// An instance of SourceContext only lives as long as the drag and drop +// operation lasts. +class DragSourceContext: public cppu::BaseMutex, + public cppu::WeakComponentImplHelper1<com::sun::star::datatransfer::dnd::XDragSourceContext>, + private ::boost::noncopyable +{ +public: + DragSourceContext(DragSource* pSource); + ~DragSourceContext(); + + virtual sal_Int32 SAL_CALL getCurrentCursor( ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL setCursor( sal_Int32 cursorId ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL setImage( sal_Int32 imageId ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL transferablesFlavorsChanged( ) + throw( com::sun::star::uno::RuntimeException); + +private: + DragSource* m_pDragSource; +}; + + + +#endif diff --git a/vcl/aqua/source/dtrans/DropTarget.cxx b/vcl/aqua/source/dtrans/DropTarget.cxx new file mode 100644 index 000000000000..88ffc1e51d02 --- /dev/null +++ b/vcl/aqua/source/dtrans/DropTarget.cxx @@ -0,0 +1,602 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: DropTarget.cxx,v $ + * $Revision: 1.5 $ + * + * 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 <com/sun/star/datatransfer/dnd/DNDConstants.hpp> +#include <com/sun/star/datatransfer/XTransferable.hpp> +#include <com/sun/star/datatransfer/dnd/DropTargetDragEnterEvent.hpp> +#include <rtl/unload.h> + +#ifndef COMPHELPER_MAKESEQUENCE_HXX_INCLUDED +#include "comphelper/makesequence.hxx" +#endif +#include <cppuhelper/interfacecontainer.hxx> + +#include "aqua_clipboard.hxx" +#include "DropTarget.hxx" +#include "DragActionConversion.hxx" + +#include "DragSource.hxx" + +#include <rtl/ustring.h> +#include <stdio.h> + +#include <premac.h> +#include <Carbon/Carbon.h> +#include <postmac.h> + + +using namespace rtl; +using namespace cppu; +using namespace osl; +using namespace com::sun::star::datatransfer; +using namespace com::sun::star::datatransfer::dnd; +using namespace com::sun::star::datatransfer::dnd::DNDConstants; +using namespace com::sun::star::datatransfer::clipboard; +using namespace com::sun::star::lang; +using namespace com::sun::star::uno; +using namespace comphelper; + +OUString dropTarget_getImplementationName() +{ + return OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.datatransfer.dnd.OleDropTarget_V1")); +} + + +Sequence<OUString> dropTarget_getSupportedServiceNames() +{ + return makeSequence(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.dnd.OleDropTarget"))); +} + + +namespace /* private */ +{ + // Cocoa's coordinate system has its origin lower-left, VCL's + // coordinate system upper-left hence we need to transform + // coordinates + + inline void CocoaToVCL(NSPoint& rPoint, const NSRect& bounds) + { + rPoint.y = bounds.size.height - rPoint.y; + } + + inline void CocoaToVCL(NSRect& rRect, const NSRect& bounds) + { + rRect.origin.y = bounds.size.height - (rRect.origin.y + rRect.size.height); + } +} + + +@implementation DropTargetHelper + + +-(DropTargetHelper*)initWithDropTarget:(DropTarget*)pdt +{ + self = [super init]; + + if (self) + { + mDropTarget = pdt; + } + + return self; +} + + +-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender +{ + return mDropTarget->draggingEntered(sender); +} + + +-(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender +{ + return mDropTarget->draggingUpdated(sender); +} + + +-(void)draggingExited:(id <NSDraggingInfo>)sender +{ + mDropTarget->draggingExited(sender); +} + + +-(MacOSBOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender +{ + return mDropTarget->prepareForDragOperation(sender); +} + + +-(MacOSBOOL)performDragOperation:(id <NSDraggingInfo>)sender +{ + return mDropTarget->performDragOperation(sender); +} + + +-(void)concludeDragOperation:(id <NSDraggingInfo>)sender +{ + mDropTarget->concludeDragOperation(sender); +} + + +@end + + +DropTarget::DropTarget() : + WeakComponentImplHelper5<XInitialization, XDropTarget, XDropTargetDragContext, XDropTargetDropContext, XServiceInfo>(m_aMutex), + mDropTargetHelper(nil), + mbActive(false), + mDragSourceSupportedActions(DNDConstants::ACTION_NONE), + mSelectedDropAction(DNDConstants::ACTION_NONE), + mDefaultActions(DNDConstants::ACTION_COPY_OR_MOVE | DNDConstants::ACTION_LINK | DNDConstants::ACTION_DEFAULT) +{ + mDataFlavorMapper = DataFlavorMapperPtr_t(new DataFlavorMapper()); +} + + +DropTarget::~DropTarget() +{ + [(id <DraggingDestinationHandler>)mView unregisterDraggingDestinationHandler:mDropTargetHelper]; + [mDropTargetHelper release]; +} + + +sal_Int8 DropTarget::determineDropAction(sal_Int8 dropActions, id sender) const +{ + sal_Int8 dropAct = dropActions; + bool srcAndDestEqual = false; + + if ([sender draggingSource] != nil) + { + // Internal DnD + NSView* destView = [[sender draggingDestinationWindow] contentView]; + srcAndDestEqual = (DragSource::g_DragSourceView == destView); + } + + // If ACTION_DEFAULT is set this means NSDragOperationGeneric + // has been set and we map this to ACTION_MOVE or ACTION_COPY + // depending on whether or not source and dest are equal, + // this hopefully satisfies all parties + if( (dropActions == DNDConstants::ACTION_DEFAULT) + || ((dropActions == mDragSourceSupportedActions) + && !(~mDragSourceSupportedActions & DNDConstants::ACTION_COPY_OR_MOVE ) ) ) + { + dropAct = srcAndDestEqual ? DNDConstants::ACTION_MOVE : + DNDConstants::ACTION_COPY; + } + // if more than one drop actions have been specified + // set ACTION_DEFAULT in order to let the drop target + // decide which one to use + else if (dropActions != DNDConstants::ACTION_NONE && + dropActions != DNDConstants::ACTION_MOVE && + dropActions != DNDConstants::ACTION_COPY && + dropActions != DNDConstants::ACTION_LINK) + { + if (srcAndDestEqual) + { + dropAct = dropActions; + } + else // source and destination are different + { + if (dropActions & DNDConstants::ACTION_COPY) + dropAct = DNDConstants::ACTION_COPY; + else if (dropActions & DNDConstants::ACTION_MOVE) + dropAct = DNDConstants::ACTION_MOVE; + else if (dropActions & DNDConstants::ACTION_LINK) + dropAct = DNDConstants::ACTION_LINK; + } + + dropAct |= DNDConstants::ACTION_DEFAULT; + } + + return dropAct; +} + + +NSDragOperation DropTarget::draggingEntered(id sender) +{ + // Initially when DnD will be started no modifier key can be pressed yet + // thus we are getting all actions that the drag source supports, we save + // this value because later the system masks the drag source actions if + // a modifier key will be pressed + mDragSourceSupportedActions = SystemToOfficeDragActions([sender draggingSourceOperationMask]); + + // Only if the drop target is really interessted in the drag actions + // supported by the source + if (mDragSourceSupportedActions & mDefaultActions) + { + sal_Int8 currentAction = determineDropAction(mDragSourceSupportedActions, sender); + + NSRect bounds = [mView bounds]; + NSPoint dragLocation = [sender draggedImageLocation]; + + CocoaToVCL(dragLocation, bounds); + + sal_Int32 posX = static_cast<sal_Int32>(dragLocation.x); + sal_Int32 posY = static_cast<sal_Int32>(dragLocation.y); + + NSPasteboard* dragPboard = [sender draggingPasteboard]; + mXCurrentDragClipboard = new AquaClipboard(dragPboard, false); + + Reference<XTransferable> xTransferable = DragSource::g_XTransferable.is() ? + DragSource::g_XTransferable : mXCurrentDragClipboard->getContents(); + + DropTargetDragEnterEvent dtdee(static_cast<OWeakObject*>(this), + 0, + this, + currentAction, + posX, + posY, + mDragSourceSupportedActions, + xTransferable->getTransferDataFlavors()); + + fire_dragEnter(dtdee); + } + + return OfficeToSystemDragActions(mSelectedDropAction); +} + + +NSDragOperation DropTarget::draggingUpdated(id sender) +{ + sal_Int8 currentDragSourceActions = + SystemToOfficeDragActions([sender draggingSourceOperationMask]); + NSDragOperation dragOp = NSDragOperationNone; + + if (currentDragSourceActions & mDefaultActions) + { + sal_Int8 currentAction = determineDropAction(currentDragSourceActions, sender); + NSRect bounds = [mView bounds]; + NSPoint dragLocation = [sender draggedImageLocation]; + + CocoaToVCL(dragLocation, bounds); + + sal_Int32 posX = static_cast<sal_Int32>(dragLocation.x); + sal_Int32 posY = static_cast<sal_Int32>(dragLocation.y); + + DropTargetDragEvent dtde(static_cast<OWeakObject*>(this), + 0, + this, + currentAction, + posX, + posY, + mDragSourceSupportedActions); + + fire_dragOver(dtde); + + // drag over callbacks likely have rendered something + [mView setNeedsDisplay: TRUE]; + + dragOp = OfficeToSystemDragActions(mSelectedDropAction); + + //NSLog(@"Drag update: Source actions: %x proposed action %x selected action %x", mDragSourceSupportedActions, currentAction, mSelectedDropAction); + } + + // Weird but it appears as if there is no method in Cocoa + // to create a kThemeCopyArrowCursor hence we have to use + // Carbon to do it + if (dragOp == NSDragOperationNone) + SetThemeCursor(kThemeNotAllowedCursor); + else if (dragOp == NSDragOperationCopy) + SetThemeCursor(kThemeCopyArrowCursor); + else + SetThemeCursor(kThemeArrowCursor); + + return dragOp; +} + + + void DropTarget::draggingExited(id sender) + { + DropTargetEvent dte(static_cast<OWeakObject*>(this), 0); + fire_dragExit(dte); + mDragSourceSupportedActions = DNDConstants::ACTION_NONE; + mSelectedDropAction = DNDConstants::ACTION_NONE; + SetThemeCursor(kThemeArrowCursor); + } + + + MacOSBOOL DropTarget::prepareForDragOperation(id sender) + { + return 1; + } + + +MacOSBOOL DropTarget::performDragOperation(id sender) +{ + bool bSuccess = false; + + if (mSelectedDropAction != DNDConstants::ACTION_NONE) + { + Reference<XTransferable> xTransferable = DragSource::g_XTransferable; + + if (!DragSource::g_XTransferable.is()) + { + xTransferable = mXCurrentDragClipboard->getContents(); + } + + NSRect bounds = [mView bounds]; + NSPoint dragLocation = [sender draggedImageLocation]; + + CocoaToVCL(dragLocation, bounds); + + sal_Int32 posX = static_cast<sal_Int32>(dragLocation.x); + sal_Int32 posY = static_cast<sal_Int32>(dragLocation.y); + + DropTargetDropEvent dtde(static_cast<OWeakObject*>(this), + 0, + this, + mSelectedDropAction, + posX, + posY, + mDragSourceSupportedActions, + xTransferable); + + fire_drop(dtde); + + bSuccess = true; + } + + return bSuccess; +} + + + void DropTarget::concludeDragOperation(id sender) + { + mDragSourceSupportedActions = DNDConstants::ACTION_NONE; + mSelectedDropAction = DNDConstants::ACTION_NONE; + mXCurrentDragClipboard = Reference<XClipboard>(); + SetThemeCursor(kThemeArrowCursor); + } + + + // called from WeakComponentImplHelperX::dispose + // WeakComponentImplHelper calls disposing before it destroys + // itself. + void SAL_CALL DropTarget::disposing() + { + } + + + void SAL_CALL DropTarget::initialize(const Sequence< Any >& aArguments) + throw(Exception) + { + if (aArguments.getLength() < 2) + { + throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM("DropTarget::initialize: Cannot install window event handler")), + static_cast<OWeakObject*>(this)); + } + + Any pNSView = aArguments[0]; + sal_uInt64 tmp = 0; + pNSView >>= tmp; + mView = (id)tmp; + + mDropTargetHelper = [[DropTargetHelper alloc] initWithDropTarget: this]; + + [(id <DraggingDestinationHandler>)mView registerDraggingDestinationHandler:mDropTargetHelper]; + [mView registerForDraggedTypes: mDataFlavorMapper->getAllSupportedPboardTypes()]; + + id wnd = [mView window]; + NSWindow* parentWnd = [wnd parentWindow]; + unsigned int topWndStyle = (NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask); + unsigned int wndStyles = [wnd styleMask] & topWndStyle; + + if (parentWnd == nil && (wndStyles == topWndStyle)) + { + [wnd registerDraggingDestinationHandler:mDropTargetHelper]; + [wnd registerForDraggedTypes: [NSArray arrayWithObjects: NSFilenamesPboardType, nil]]; + } + } + + + void SAL_CALL DropTarget::addDropTargetListener(const Reference<XDropTargetListener>& dtl) + throw(RuntimeException) + { + rBHelper.addListener(::getCppuType(&dtl), dtl); + } + + + void SAL_CALL DropTarget::removeDropTargetListener(const Reference<XDropTargetListener>& dtl) + throw(RuntimeException) + { + rBHelper.removeListener(::getCppuType(&dtl), dtl); + } + + + sal_Bool SAL_CALL DropTarget::isActive( ) throw(RuntimeException) + { + return mbActive; + } + + + void SAL_CALL DropTarget::setActive(sal_Bool active) throw(RuntimeException) + { + mbActive = active; + } + + + sal_Int8 SAL_CALL DropTarget::getDefaultActions() throw(RuntimeException) + { + return mDefaultActions; + } + + + void SAL_CALL DropTarget::setDefaultActions(sal_Int8 actions) throw(RuntimeException) + { + OSL_ENSURE( actions < 8, "No valid default actions"); + mDefaultActions= actions; + } + + + // XDropTargetDragContext + + void SAL_CALL DropTarget::acceptDrag(sal_Int8 dragOperation) throw (RuntimeException) + { + mSelectedDropAction = dragOperation; + } + + + void SAL_CALL DropTarget::rejectDrag() throw (RuntimeException) + { + mSelectedDropAction = DNDConstants::ACTION_NONE; + } + + + //XDropTargetDropContext + + void SAL_CALL DropTarget::acceptDrop(sal_Int8 dropOperation) throw( RuntimeException) + { + mSelectedDropAction = dropOperation; + } + + + void SAL_CALL DropTarget::rejectDrop() throw (RuntimeException) + { + mSelectedDropAction = DNDConstants::ACTION_NONE; + } + + + void SAL_CALL DropTarget::dropComplete(sal_Bool success) throw (RuntimeException) + { + // Reset the internal transferable used as shortcut in case this is + // an internal D&D operation + DragSource::g_XTransferable = Reference<XTransferable>(); + DragSource::g_DropSuccessSet = true; + DragSource::g_DropSuccess = success; + } + + + void DropTarget::fire_drop( const DropTargetDropEvent& dte) + { + OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) ); + if( pContainer) + { + OInterfaceIteratorHelper iter( *pContainer); + while( iter.hasMoreElements()) + { + Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next())); + + try { listener->drop( dte); } + catch(RuntimeException&) {} + } + } + } + + + void DropTarget::fire_dragEnter(const DropTargetDragEnterEvent& e) + { + OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) ); + if( pContainer) + { + OInterfaceIteratorHelper iter( *pContainer); + while( iter.hasMoreElements()) + { + Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next())); + + try { listener->dragEnter( e); } + catch (RuntimeException&) {} + } + } + } + + + void DropTarget::fire_dragExit(const DropTargetEvent& dte) + { + OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) ); + + if( pContainer) + { + OInterfaceIteratorHelper iter( *pContainer); + while( iter.hasMoreElements()) + { + Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next())); + + try { listener->dragExit( dte); } + catch (RuntimeException&) {} + } + } + } + + + void DropTarget::fire_dragOver(const DropTargetDragEvent& dtde) + { + OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) ); + if( pContainer) + { + OInterfaceIteratorHelper iter( *pContainer ); + while( iter.hasMoreElements()) + { + Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next())); + + try { listener->dragOver( dtde); } + catch (RuntimeException&) {} + } + } + } + + + void DropTarget::fire_dropActionChanged(const DropTargetDragEvent& dtde) + { + OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) ); + if( pContainer) + { + OInterfaceIteratorHelper iter( *pContainer); + while( iter.hasMoreElements()) + { + Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next())); + + try { listener->dropActionChanged( dtde); } + catch (RuntimeException&) {} + } + } + } + + + // XServiceInfo + + OUString SAL_CALL DropTarget::getImplementationName() throw (RuntimeException) + { + return dropTarget_getImplementationName(); + } + + + sal_Bool SAL_CALL DropTarget::supportsService( const OUString& ServiceName ) throw (RuntimeException) + { + return ServiceName.equals(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.dnd.OleDropTarget"))); + } + + + Sequence< OUString > SAL_CALL DropTarget::getSupportedServiceNames( ) throw (RuntimeException) + { + return dropTarget_getSupportedServiceNames(); + } + diff --git a/vcl/aqua/source/dtrans/DropTarget.hxx b/vcl/aqua/source/dtrans/DropTarget.hxx new file mode 100644 index 000000000000..91b50c041916 --- /dev/null +++ b/vcl/aqua/source/dtrans/DropTarget.hxx @@ -0,0 +1,172 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: DropTarget.hxx,v $ + * $Revision: 1.3 $ + * + * 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 _DROPTARGET_HXX_ +#define _DROPTARGET_HXX_ + +#include "DataFlavorMapping.hxx" +#include <cppuhelper/compbase5.hxx> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp> + +#ifndef _COM_SUN_STAR_DATATRANSFER_DND_XDROPTARGETLISTENR_HPP_ +#include <com/sun/star/datatransfer/dnd/XDropTargetListener.hpp> +#endif +#include <com/sun/star/datatransfer/dnd/DropTargetDragEnterEvent.hpp> +#include <com/sun/star/datatransfer/dnd/XDropTargetDragContext.hpp> +#include <com/sun/star/datatransfer/dnd/XDropTargetDropContext.hpp> +#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/basemutex.hxx> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> + +#include <boost/utility.hpp> + +#include <premac.h> +#import <Cocoa/Cocoa.h> +#include <postmac.h> + +class DropTarget; + +/* The functions declared in this protocol are actually + declared in vcl/aqua/inc/salframe.h. Because we want + to avoid importing VCL headers in UNO services and + on the other hand want to avoid warnings caused by + gcc complaining about unknowness of these functions + we declare them in a protocol here and cast at the + appropriate places. +*/ +@protocol DraggingDestinationHandler +-(void)registerDraggingDestinationHandler:(id)theHandler; +-(void)unregisterDraggingDestinationHandler:(id)theHandler; +@end + + +@interface DropTargetHelper : NSObject +{ + DropTarget* mDropTarget; +} + +-(DropTargetHelper*)initWithDropTarget:(DropTarget*)pdt; + +-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender; +-(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender; +-(void)draggingExited:(id <NSDraggingInfo>)sender; +-(MacOSBOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender; +-(MacOSBOOL)performDragOperation:(id <NSDraggingInfo>)sender; +-(void)concludeDragOperation:(id <NSDraggingInfo>)sender; + +@end + + +class DropTarget: public cppu::BaseMutex, + public cppu::WeakComponentImplHelper5< com::sun::star::lang::XInitialization, + com::sun::star::datatransfer::dnd::XDropTarget, + com::sun::star::datatransfer::dnd::XDropTargetDragContext, + com::sun::star::datatransfer::dnd::XDropTargetDropContext, + com::sun::star::lang::XServiceInfo >, + private boost::noncopyable +{ +public: + DropTarget(); + virtual ~DropTarget(); + + // Overrides WeakComponentImplHelper::disposing which is called by + // WeakComponentImplHelper::dispose + // Must be called. + virtual void SAL_CALL disposing(); + + // XInitialization + virtual void SAL_CALL initialize( const com::sun::star::uno::Sequence< com::sun::star::uno::Any >& aArguments ) + throw(com::sun::star::uno::Exception); + + // XDropTarget + virtual void SAL_CALL addDropTargetListener( const com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDropTargetListener >& dtl ) + throw(com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL removeDropTargetListener( const com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDropTargetListener >& dtl ) + throw(com::sun::star::uno::RuntimeException); + + // Default is not active + virtual sal_Bool SAL_CALL isActive() throw(com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setActive(sal_Bool isActive) throw(com::sun::star::uno::RuntimeException); + virtual sal_Int8 SAL_CALL getDefaultActions() throw(com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDefaultActions(sal_Int8 actions) throw(com::sun::star::uno::RuntimeException); + + // XDropTargetDragContext + virtual void SAL_CALL acceptDrag(sal_Int8 dragOperation) throw(com::sun::star::uno::RuntimeException); + virtual void SAL_CALL rejectDrag() throw(com::sun::star::uno::RuntimeException); + + // XDropTargetDragContext + virtual void SAL_CALL acceptDrop(sal_Int8 dropOperation) throw (com::sun::star::uno::RuntimeException); + virtual void SAL_CALL rejectDrop() throw (com::sun::star::uno::RuntimeException); + virtual void SAL_CALL dropComplete(sal_Bool success) 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); + + // NSDraggingDestination protocol functions + virtual NSDragOperation draggingEntered(id sender); + virtual NSDragOperation draggingUpdated(id sender); + virtual void draggingExited(id sender); + virtual MacOSBOOL prepareForDragOperation(id sender); + virtual MacOSBOOL performDragOperation(id sender); + virtual void concludeDragOperation(id sender); + + /* If multiple actions are supported by the drag source and + the user did not choose a specific action by pressing a + modifier key choose a default action to be proposed to + the application. + */ + sal_Int8 determineDropAction(sal_Int8 dropActions, id sender) const; + +private: + void fire_drop(const com::sun::star::datatransfer::dnd::DropTargetDropEvent& dte); + void fire_dragEnter(const com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent& dtdee); + void fire_dragExit(const com::sun::star::datatransfer::dnd::DropTargetEvent& dte); + void fire_dragOver(const com::sun::star::datatransfer::dnd::DropTargetDragEvent& dtde); + void fire_dropActionChanged(const com::sun::star::datatransfer::dnd::DropTargetDragEvent& dtde); + +private: + com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDropTargetDragContext > mXCurrentDragContext; + com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDropTargetDropContext > mXCurrentDropContext; + com::sun::star::uno::Reference< com::sun::star::datatransfer::clipboard::XClipboard > mXCurrentDragClipboard; + DataFlavorMapperPtr_t mDataFlavorMapper; + id mView; + DropTargetHelper* mDropTargetHelper; + bool mbActive; + sal_Int8 mDragSourceSupportedActions; + sal_Int8 mSelectedDropAction; + sal_Int8 mDefaultActions; +}; + +#endif diff --git a/vcl/aqua/source/dtrans/HtmlFmtFlt.cxx b/vcl/aqua/source/dtrans/HtmlFmtFlt.cxx new file mode 100644 index 000000000000..3f558b0a5b4f --- /dev/null +++ b/vcl/aqua/source/dtrans/HtmlFmtFlt.cxx @@ -0,0 +1,147 @@ +#include "HtmlFmtFlt.hxx" + +#include <rtl/string.h> + +#include <string> +#include <sstream> +#include <vector> +#include <iomanip> + +#include <boost/assert.hpp> + +using namespace com::sun::star::uno; + +//------------------------------------------------------------------------------ +// converts the openoffice text/html clipboard format to the HTML Format +// well known under MS Windows +// the MS HTML Format has a header before the real html data +// +// Version:1.0 Version number of the clipboard. Staring is 0.9 +// StartHTML: Byte count from the beginning of the clipboard to the start +// of the context, or -1 if no context +// EndHTML: Byte count from the beginning of the clipboard to the end +// of the context, or -1 if no context +// StartFragment: Byte count from the beginning of the clipboard to the +// start of the fragment +// EndFragment: Byte count from the beginning of the clipboard to the +// end of the fragment +// StartSelection: Byte count from the beginning of the clipboard to the +// start of the selection +// EndSelection: Byte count from the beginning of the clipboard to the +// end of the selection +// +// StartSelection and EndSelection are optional +// The fragment should be preceded and followed by the HTML comments +// <!--StartFragment--> and <!--EndFragment--> (no space between !-- and the +// text +//------------------------------------------------------------------------------ + +namespace // private +{ +std::string GetHtmlFormatHeader(size_t startHtml, size_t endHtml, size_t startFragment, size_t endFragment) +{ + std::ostringstream htmlHeader; + htmlHeader << "Version:1.0" << '\r' << '\n'; + htmlHeader << "StartHTML:" << std::setw(10) << std::setfill('0') << std::dec << startHtml << '\r' << '\n'; + htmlHeader << "EndHTML:" << std::setw(10) << std::setfill('0') << std::dec << endHtml << '\r' << '\n'; + htmlHeader << "StartFragment:" << std::setw(10) << std::setfill('0') << std::dec << startFragment << '\r' << '\n'; + htmlHeader << "EndFragment:" << std::setw(10) << std::setfill('0') << std::dec << endFragment << '\r' << '\n'; + return htmlHeader.str(); +} + +} // namespace private + + +// the office allways writes the start and end html tag in upper cases and +// without spaces both tags don't allow parameters +const std::string TAG_HTML = std::string("<HTML>"); +const std::string TAG_END_HTML = std::string("</HTML>"); + +// The body tag may have parameters so we need to search for the +// closing '>' manually e.g. <BODY param> #92840# +const std::string TAG_BODY = std::string("<BODY"); +const std::string TAG_END_BODY = std::string("</BODY"); + +Sequence<sal_Int8> SAL_CALL TextHtmlToHTMLFormat(Sequence<sal_Int8>& aTextHtml) +{ + OSL_ASSERT(aTextHtml.getLength() > 0); + + if (!(aTextHtml.getLength() > 0)) + return Sequence<sal_Int8>(); + + // fill the buffer with dummy values to calc the exact length + std::string dummyHtmlHeader = GetHtmlFormatHeader(0, 0, 0, 0); + size_t lHtmlFormatHeader = dummyHtmlHeader.length(); + + std::string textHtml( + reinterpret_cast<const sal_Char*>(aTextHtml.getConstArray()), + reinterpret_cast<const sal_Char*>(aTextHtml.getConstArray()) + aTextHtml.getLength()); + + std::string::size_type nStartHtml = textHtml.find(TAG_HTML) + lHtmlFormatHeader - 1; // we start one before '<HTML>' Word 2000 does also so + std::string::size_type nEndHtml = textHtml.find(TAG_END_HTML) + lHtmlFormatHeader + TAG_END_HTML.length() + 1; // our SOffice 5.2 wants 2 behind </HTML>? + + // The body tag may have parameters so we need to search for the + // closing '>' manually e.g. <BODY param> #92840# + std::string::size_type nStartFragment = textHtml.find(">", textHtml.find(TAG_BODY)) + lHtmlFormatHeader + 1; + std::string::size_type nEndFragment = textHtml.find(TAG_END_BODY) + lHtmlFormatHeader; + + std::string htmlFormat = GetHtmlFormatHeader(nStartHtml, nEndHtml, nStartFragment, nEndFragment); + htmlFormat += textHtml; + + Sequence<sal_Int8> byteSequence(htmlFormat.length() + 1); // space the trailing '\0' + rtl_zeroMemory(byteSequence.getArray(), byteSequence.getLength()); + + rtl_copyMemory( + static_cast<void*>(byteSequence.getArray()), + static_cast<const void*>(htmlFormat.c_str()), + htmlFormat.length()); + + return byteSequence; +} + +const char* HtmlStartTag = "<html"; + +Sequence<sal_Int8> HTMLFormatToTextHtml(const Sequence<sal_Int8>& aHTMLFormat) +{ + BOOST_ASSERT(isHTMLFormat(aHTMLFormat) && "No HTML Format provided"); + + Sequence<sal_Int8>& nonconstHTMLFormatRef = const_cast< Sequence<sal_Int8>& >(aHTMLFormat); + sal_Char* dataStart = reinterpret_cast<sal_Char*>(nonconstHTMLFormatRef.getArray()); + sal_Char* dataEnd = dataStart + nonconstHTMLFormatRef.getLength() - 1; + const sal_Char* htmlStartTag = strcasestr(dataStart, HtmlStartTag); + + BOOST_ASSERT(htmlStartTag && "Seems to be no HTML at all"); + + // It doesn't seem to be HTML? Well then simply return what has been + // provided in non-debug builds + if (htmlStartTag == NULL) + { + return aHTMLFormat; + } + + sal_Int32 len = dataEnd - htmlStartTag; + Sequence<sal_Int8> plainHtmlData(len); + + rtl_copyMemory(static_cast<void*>(plainHtmlData.getArray()), htmlStartTag, len); + + return plainHtmlData; +} + +/* A simple format detection. We are just comparing the first few bytes + of the provided byte sequence to see whether or not it is the MS + Office Html format. If it shows that this is not reliable enough we + can improve this +*/ +const char HtmlFormatStart[] = "Version:"; +int HtmlFormatStartLen = (sizeof(HtmlFormatStart) - 1); + +bool isHTMLFormat(const Sequence<sal_Int8>& aHtmlSequence) +{ + if (aHtmlSequence.getLength() < HtmlFormatStartLen) + return false; + + return rtl_str_compareIgnoreAsciiCase_WithLength(HtmlFormatStart, + HtmlFormatStartLen, + reinterpret_cast<const sal_Char*>(aHtmlSequence.getConstArray()), + HtmlFormatStartLen) == 0; +} diff --git a/vcl/aqua/source/dtrans/HtmlFmtFlt.hxx b/vcl/aqua/source/dtrans/HtmlFmtFlt.hxx new file mode 100644 index 000000000000..49f0cc70590c --- /dev/null +++ b/vcl/aqua/source/dtrans/HtmlFmtFlt.hxx @@ -0,0 +1,20 @@ +#ifndef INCLUDED_HTMLFMTFLT_HXX +#define INCLUDED_HTMLFMTFLT_HXX + +#include <com/sun/star/uno/Sequence.hxx> + +/* Transform plain HTML into the format expected by MS Office. + */ +com::sun::star::uno::Sequence<sal_Int8> TextHtmlToHTMLFormat(com::sun::star::uno::Sequence<sal_Int8>& aTextHtml); + +/* Transform the MS Office HTML format into plain HTML. + */ +com::sun::star::uno::Sequence<sal_Int8> HTMLFormatToTextHtml(const com::sun::star::uno::Sequence<sal_Int8>& aHTMLFormat); + +/* Detects whether the given byte sequence contains the MS Office Html format. + + @returns True if the MS Office Html format will be detected False otherwise. + */ +bool isHTMLFormat (const com::sun::star::uno::Sequence<sal_Int8>& aHtmlSequence); + +#endif diff --git a/vcl/aqua/source/dtrans/OSXTransferable.cxx b/vcl/aqua/source/dtrans/OSXTransferable.cxx new file mode 100644 index 000000000000..a893f09d89cc --- /dev/null +++ b/vcl/aqua/source/dtrans/OSXTransferable.cxx @@ -0,0 +1,215 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: OSXTransferable.cxx,v $ + * $Revision: 1.4 $ + * + * 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> + +#ifndef _TRANSFERABLE_HXX_ +#include "OSXTransferable.hxx" +#endif + +#include "DataFlavorMapping.hxx" + +using namespace rtl; +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; + +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 + + +OSXTransferable::OSXTransferable(const Reference<XMimeContentTypeFactory> rXMimeCntFactory, + DataFlavorMapperPtr_t pDataFlavorMapper, + NSPasteboard* pasteboard) : + mrXMimeCntFactory(rXMimeCntFactory), + mDataFlavorMapper(pDataFlavorMapper), + mPasteboard(pasteboard) +{ + [mPasteboard retain]; + + initClipboardItemList(); +} + + +OSXTransferable::~OSXTransferable() +{ + [mPasteboard release]; +} + + +Any SAL_CALL OSXTransferable::getTransferData( const DataFlavor& aFlavor ) + throw( UnsupportedFlavorException, IOException, RuntimeException ) +{ + if (!isValidFlavor(aFlavor) || !isDataFlavorSupported(aFlavor)) + { + throw UnsupportedFlavorException(OUString(RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Unsupported data flavor")), + static_cast<XTransferable*>(this)); + } + + NSString* sysFormat = (NSString*)mDataFlavorMapper->openOfficeToSystemFlavor(aFlavor); + DataProviderPtr_t dp; + + if ([sysFormat caseInsensitiveCompare: NSFilenamesPboardType] == NSOrderedSame) + { + NSArray* sysData = [mPasteboard propertyListForType: sysFormat]; + dp = mDataFlavorMapper->getDataProvider(sysFormat, sysData); + } + else + { + NSData* sysData = [mPasteboard dataForType: sysFormat]; + dp = mDataFlavorMapper->getDataProvider(sysFormat, sysData); + } + + if (dp.get() == NULL) + { + throw UnsupportedFlavorException(OUString(RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Unsupported data flavor")), + static_cast<XTransferable*>(this)); + } + + return dp->getOOoData(); +} + + +bool OSXTransferable::isUnicodeText(const DataFlavor& flavor) +{ + return (flavor.DataType == CPPUTYPE_OUSTRING); +} + + +Sequence< DataFlavor > SAL_CALL OSXTransferable::getTransferDataFlavors( ) + throw( RuntimeException ) +{ + return mFlavorList; +} + + +sal_Bool SAL_CALL OSXTransferable::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 OSXTransferable::initClipboardItemList() +{ + NSArray* pboardFormats = [mPasteboard types]; + + if (pboardFormats == NULL) + { + throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Cannot get clipboard data")), + static_cast<XTransferable*>(this)); + } + + mFlavorList = mDataFlavorMapper->typesArrayToFlavorSequence(pboardFormats); +} + + +/* 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 OSXTransferable::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_ENSURE( sal_False, "Invalid content type detected" ); + return false; + } + + return true; +} + + +bool OSXTransferable::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; +} diff --git a/vcl/aqua/source/dtrans/OSXTransferable.hxx b/vcl/aqua/source/dtrans/OSXTransferable.hxx new file mode 100644 index 000000000000..9b371523c440 --- /dev/null +++ b/vcl/aqua/source/dtrans/OSXTransferable.hxx @@ -0,0 +1,103 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: OSXTransferable.hxx,v $ + * $Revision: 1.4 $ + * + * 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_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#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 "DataFlavorMapping.hxx" + +#include <premac.h> +#import <Cocoa/Cocoa.h> +#include <postmac.h> + +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> +#include <vector> + + +class OSXTransferable : public ::cppu::WeakImplHelper1<com::sun::star::datatransfer::XTransferable>, + private ::boost::noncopyable +{ +public: + typedef com::sun::star::uno::Sequence< sal_Int8 > ByteSequence_t; + + explicit OSXTransferable(com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XMimeContentTypeFactory> rXMimeCntFactory, + DataFlavorMapperPtr_t pDataFlavorMapper, + NSPasteboard* pasteboard); + + virtual ~OSXTransferable(); + + //------------------------------------------------------------------------ + // 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; + DataFlavorMapperPtr_t mDataFlavorMapper; + NSPasteboard* mPasteboard; +}; + +#endif diff --git a/vcl/aqua/source/dtrans/PictToBmpFlt.cxx b/vcl/aqua/source/dtrans/PictToBmpFlt.cxx new file mode 100644 index 000000000000..0643efae33ca --- /dev/null +++ b/vcl/aqua/source/dtrans/PictToBmpFlt.cxx @@ -0,0 +1,114 @@ +#include "PictToBmpFlt.hxx" + +/* This is a work-around to prevent 'deprecated' warning for 'KillPicture' API + Hopefully we can get rid of this whole code again when the OOo PICT filter + are good enough to be used see #i78953 thus this hack would vanish to again. + */ +#include <AvailabilityMacros.h> +#undef DEPRECATED_ATTRIBUTE +#define DEPRECATED_ATTRIBUTE + +#include <premac.h> +#include <Carbon/Carbon.h> +#include <QuickTime/QuickTime.h> +#include <postmac.h> + + +bool PICTtoBMP(com::sun::star::uno::Sequence<sal_Int8>& aPict, + com::sun::star::uno::Sequence<sal_Int8>& aBmp) +{ + bool result = false; + + ComponentInstance bmpExporter; + if (OpenADefaultComponent(GraphicsExporterComponentType, + kQTFileTypeBMP, + &bmpExporter) != noErr) + { + return result; + } + + Handle hPict; + if (PtrToHand(aPict.getArray(), &hPict, aPict.getLength()) != noErr) + { + return result; + } + + Handle hBmp; + if ((GraphicsExportSetInputPicture(bmpExporter, (PicHandle)hPict) != noErr) || + ((hBmp = NewHandleClear(0)) == NULL)) + { + CloseComponent(bmpExporter); + DisposeHandle(hPict); + return result; + } + + if ((GraphicsExportSetOutputHandle(bmpExporter, hBmp) == noErr) && + (GraphicsExportDoExport(bmpExporter, NULL) == noErr)) + { + size_t sz = GetHandleSize(hBmp); + aBmp.realloc(sz); + + HLock(hBmp); + rtl_copyMemory(aBmp.getArray(), ((sal_Int8*)*hBmp), sz); + HUnlock(hBmp); + + result = true; + } + + DisposeHandle(hPict); + DisposeHandle(hBmp); + CloseComponent(bmpExporter); + + return result; +} + +bool BMPtoPICT(com::sun::star::uno::Sequence<sal_Int8>& aBmp, + com::sun::star::uno::Sequence<sal_Int8>& aPict) +{ + bool result = false; + + Handle hBmp; + ComponentInstance pictExporter; + if ((PtrToHand(aBmp.getArray(), &hBmp, aBmp.getLength()) != noErr)) + { + return result; + } + + if (OpenADefaultComponent(GraphicsImporterComponentType, + kQTFileTypeBMP, + &pictExporter) != noErr) + { + DisposeHandle(hBmp); + return result; + } + + if (GraphicsImportSetDataHandle(pictExporter, hBmp) != noErr) + { + DisposeHandle(hBmp); + CloseComponent(pictExporter); + return result; + } + + PicHandle hPict; + if (GraphicsImportGetAsPicture(pictExporter, &hPict) == noErr) + { + size_t sz = GetHandleSize((Handle)hPict); + aPict.realloc(sz); + + HLock((Handle)hPict); + rtl_copyMemory(aPict.getArray(), ((sal_Int8*)*hPict), sz); + HUnlock((Handle)hPict); + + // Release the data associated with the picture + // Note: This function is deprecated in Mac OS X + // 10.4. + KillPicture(hPict); + + result = true; + } + + DisposeHandle(hBmp); + CloseComponent(pictExporter); + + return result; +} diff --git a/vcl/aqua/source/dtrans/PictToBmpFlt.hxx b/vcl/aqua/source/dtrans/PictToBmpFlt.hxx new file mode 100644 index 000000000000..29e9c535546f --- /dev/null +++ b/vcl/aqua/source/dtrans/PictToBmpFlt.hxx @@ -0,0 +1,22 @@ +#ifndef INCLUDED_PICTTOBMPFLT_HXX +#define INCLUDED_PICTTOBMPFLT_HXX + +#include <com/sun/star/uno/Sequence.hxx> + +/* Transform PICT into the a Window BMP. + + Returns true if the conversion was successful false + otherwise. + */ +bool PICTtoBMP(com::sun::star::uno::Sequence<sal_Int8>& aPict, + com::sun::star::uno::Sequence<sal_Int8>& aBmp); + +/* Transform a Windows BMP to a PICT. + + Returns true if the conversion was successful false + otherwise. + */ +bool BMPtoPICT(com::sun::star::uno::Sequence<sal_Int8>& aBmp, + com::sun::star::uno::Sequence<sal_Int8>& aPict); + +#endif diff --git a/vcl/aqua/source/dtrans/aqua_clipboard.cxx b/vcl/aqua/source/dtrans/aqua_clipboard.cxx new file mode 100644 index 000000000000..27bf308dce9b --- /dev/null +++ b/vcl/aqua/source/dtrans/aqua_clipboard.cxx @@ -0,0 +1,385 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: aqua_clipboard.cxx,v $ + * $Revision: 1.8 $ + * + * 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 "aqua_clipboard.hxx" + +#include "DataFlavorMapping.hxx" +#include "OSXTransferable.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 rtl; +using namespace std; +using namespace comphelper; + + +@implementation EventListener; + +-(EventListener*)initWithAquaClipboard: (AquaClipboard*) pcb +{ + self = [super init]; + + if (self) + pAquaClipboard = pcb; + + return self; +} + +-(void)pasteboard:(NSPasteboard*)sender provideDataForType:(NSString*)type +{ + if( pAquaClipboard ) + pAquaClipboard->provideDataForType(sender, type); +} + +-(void)applicationDidBecomeActive:(NSNotification*)aNotification +{ + if( pAquaClipboard ) + pAquaClipboard->applicationDidBecomeActive(aNotification); +} + +-(void)disposing +{ + pAquaClipboard = NULL; +} + +@end + + +OUString clipboard_getImplementationName() +{ + return OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.clipboard.AquaClipboard")); +} + +Sequence<OUString> clipboard_getSupportedServiceNames() +{ + return makeSequence(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.clipboard.SystemClipboard"))); +} + + +AquaClipboard::AquaClipboard(NSPasteboard* 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("AquaClipboard: Cannot create com.sun.star.datatransfer.MimeContentTypeFactory")), + static_cast<XClipboardEx*>(this)); + } + + mpDataFlavorMapper = DataFlavorMapperPtr_t(new DataFlavorMapper()); + + if (pasteboard != NULL) + { + mPasteboard = pasteboard; + mIsSystemPasteboard = false; + } + else + { + mPasteboard = bUseSystemPasteboard ? [NSPasteboard generalPasteboard] : + [NSPasteboard pasteboardWithName: NSDragPboard]; + + if (mPasteboard == nil) + { + throw RuntimeException(OUString( + RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Cannot create Cocoa pasteboard")), + static_cast<XClipboardEx*>(this)); + } + } + + [mPasteboard retain]; + + mEventListener = [[EventListener alloc] initWithAquaClipboard: this]; + + if (mEventListener == nil) + { + [mPasteboard release]; + + throw RuntimeException( + OUString(RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Cannot create pasteboard change listener")), + static_cast<XClipboardEx*>(this)); + } + + if (mIsSystemPasteboard) + { + NSNotificationCenter* notificationCenter = [NSNotificationCenter defaultCenter]; + + [notificationCenter addObserver: mEventListener + selector: @selector(applicationDidBecomeActive:) + name: @"NSApplicationDidBecomeActiveNotification" + object: [NSApplication sharedApplication]]; + } + + mPasteboardChangeCount = [mPasteboard changeCount]; +} + + +AquaClipboard::~AquaClipboard() +{ + if (mIsSystemPasteboard) + { + [[NSNotificationCenter defaultCenter] removeObserver: mEventListener]; + } + + [mEventListener disposing]; + [mEventListener release]; + [mPasteboard release]; +} + + +Reference<XTransferable> SAL_CALL AquaClipboard::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 OSXTransferable(mrXMimeCntFactory, + mpDataFlavorMapper, + mPasteboard)); +} + + +void SAL_CALL AquaClipboard::setContents(const Reference<XTransferable>& xTransferable, + const Reference<XClipboardOwner>& xClipboardOwner) + throw( RuntimeException ) +{ + ClearableMutexGuard aGuard(m_aMutex); + + Reference<XClipboardOwner> oldOwner(mXClipboardOwner); + mXClipboardOwner = xClipboardOwner; + + Reference<XTransferable> oldContent(mXClipboardContent); + mXClipboardContent = xTransferable; + + NSArray* types = mXClipboardContent.is() ? + mpDataFlavorMapper->flavorSequenceToTypesArray(mXClipboardContent->getTransferDataFlavors()) : + [NSArray array]; + mPasteboardChangeCount = [mPasteboard declareTypes: types owner: mEventListener]; + + // if we are already the owner of the clipboard + // then fire lost ownership event + if (oldOwner.is()) + { + fireLostClipboardOwnershipEvent(oldOwner, oldContent); + } + + fireClipboardChangedEvent(); +} + + +OUString SAL_CALL AquaClipboard::getName() throw( RuntimeException ) +{ + return OUString(); +} + + +sal_Int8 SAL_CALL AquaClipboard::getRenderingCapabilities() throw( RuntimeException ) +{ + return 0; +} + + +void SAL_CALL AquaClipboard::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 AquaClipboard::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 AquaClipboard::applicationDidBecomeActive(NSNotification* aNotification) +{ + MutexGuard 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>(); + + if (oldOwner.is()) + { + fireLostClipboardOwnershipEvent(oldOwner, oldContent); + } + + fireClipboardChangedEvent(); + } +} + + +void AquaClipboard::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 AquaClipboard::fireLostClipboardOwnershipEvent(Reference<XClipboardOwner> oldOwner, Reference<XTransferable> oldContent) +{ + BOOST_ASSERT(oldOwner.is()); + + try { oldOwner->lostOwnership(static_cast<XClipboardEx*>(this), oldContent); } + catch(RuntimeException&) { } +} + + +void AquaClipboard::provideDataForType(NSPasteboard* sender, NSString* type) +{ + DataProviderPtr_t dp = mpDataFlavorMapper->getDataProvider(type, mXClipboardContent); + NSData* pBoardData = NULL; + + if (dp.get() != NULL) + { + pBoardData = (NSData*)dp->getSystemData(); + [sender setData: pBoardData forType: type]; + } +} + + +//------------------------------------------------ +// XFlushableClipboard +//------------------------------------------------ + +void SAL_CALL AquaClipboard::flushClipboard() + throw(RuntimeException) +{ + 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); + } + } + } +} + + +NSPasteboard* AquaClipboard::getPasteboard() const +{ + return mPasteboard; +} + + +//------------------------------------------------- +// XServiceInfo +//------------------------------------------------- + +OUString SAL_CALL AquaClipboard::getImplementationName() throw( RuntimeException ) +{ + return clipboard_getImplementationName(); +} + + +sal_Bool SAL_CALL AquaClipboard::supportsService( const OUString& ServiceName ) throw( RuntimeException ) +{ + return sal_False; +} + + +Sequence< OUString > SAL_CALL AquaClipboard::getSupportedServiceNames() throw( RuntimeException ) +{ + return clipboard_getSupportedServiceNames(); +} + diff --git a/vcl/aqua/source/dtrans/aqua_clipboard.hxx b/vcl/aqua/source/dtrans/aqua_clipboard.hxx new file mode 100644 index 000000000000..90bb404fdb36 --- /dev/null +++ b/vcl/aqua/source/dtrans/aqua_clipboard.hxx @@ -0,0 +1,184 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: aqua_clipboard.hxx,v $ + * $Revision: 1.9 $ + * + * 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 _AQUA_CLIPBOARD_HXX_ +#define _AQUA_CLIPBOARD_HXX_ + +#include "DataFlavorMapping.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 <Cocoa/Cocoa.h> +#include <postmac.h> + +class AquaClipboard; + +@interface EventListener : NSObject +{ + AquaClipboard* pAquaClipboard; +} + +// Init the pasteboard change listener with a reference to the OfficeClipboard +// instance +- (EventListener*)initWithAquaClipboard: (AquaClipboard*) pcb; + +// Promiss resolver function +- (void)pasteboard:(NSPasteboard*)sender provideDataForType:(NSString *)type; + +-(void)applicationDidBecomeActive:(NSNotification*)aNotification; + +-(void)disposing; +@end + + +class AquaClipboard : 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 + */ + AquaClipboard(NSPasteboard* pasteboard = NULL, + bool bUseSystemClipboard = true); + + ~AquaClipboard(); + + //------------------------------------------------ + // 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 pastboard. + */ + NSPasteboard* 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(NSPasteboard* 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; + DataFlavorMapperPtr_t mpDataFlavorMapper; + bool mIsSystemPasteboard; + NSPasteboard* mPasteboard; + int mPasteboardChangeCount; + EventListener* mEventListener; +}; + +#endif diff --git a/vcl/aqua/source/dtrans/aqua_service.cxx b/vcl/aqua/source/dtrans/aqua_service.cxx new file mode 100644 index 000000000000..aeaf697670ef --- /dev/null +++ b/vcl/aqua/source/dtrans/aqua_service.cxx @@ -0,0 +1,111 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: aqua_service.cxx,v $ + * $Revision: 1.8 $ + * + * 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 "aqua_clipboard.hxx" +#include <cppuhelper/factory.hxx> +#include <com/sun/star/container/XSet.hpp> +#include <osl/diagnose.h> + +using namespace rtl; +using namespace com::sun::star::uno; +using namespace com::sun::star::registry; +using namespace cppu; +using namespace com::sun::star::lang; +using namespace com::sun::star::datatransfer::clipboard; +using namespace aqua; + +namespace aqua { + +Reference< XInterface > SAL_CALL createInstance( const Reference< XMultiServiceFactory >& rServiceManager ) +{ + return Reference< XInterface >( static_cast< XClipboard* >( new AquaClipboard(rServiceManager) ) ); +} + +} // namespace aqua + +extern "C" +{ + +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +sal_Bool SAL_CALL component_writeInfo( void* pServiceManager, void* pRegistryKey ) +{ + sal_Bool bRetVal = sal_False; + + if ( pRegistryKey ) + { + try + { + Reference< XRegistryKey > pXNewKey( static_cast< XRegistryKey* >( pRegistryKey ) ); + pXNewKey->createKey( OUString( RTL_CONSTASCII_USTRINGPARAM( AQUA_CLIPBOARD_REGKEY_NAME ) ) ); + bRetVal = sal_True; + } + catch( InvalidRegistryException& ) + { + OSL_ENSURE(sal_False, "InvalidRegistryException caught"); + bRetVal = sal_False; + } + } + + return bRetVal; +} + +void* SAL_CALL component_getFactory( const sal_Char* pImplName, uno_Interface* pSrvManager, uno_Interface* pRegistryKey ) +{ + void* pRet = 0; + + if ( pSrvManager && ( 0 == rtl_str_compare( pImplName, AQUA_CLIPBOARD_IMPL_NAME ) ) ) + { + Sequence< OUString > aSNS( 1 ); + aSNS.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( AQUA_CLIPBOARD_SERVICE_NAME ) ); + + //OUString( RTL_CONSTASCII_USTRINGPARAM( FPS_IMPL_NAME ) ) + Reference< XSingleServiceFactory > xFactory ( createOneInstanceFactory( + reinterpret_cast< XMultiServiceFactory* > ( pSrvManager ), + OUString::createFromAscii( pImplName ), + createInstance, + aSNS ) ); + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + + return pRet; +} + +} // extern "C" diff --git a/vcl/aqua/source/dtrans/makefile.mk b/vcl/aqua/source/dtrans/makefile.mk new file mode 100644 index 000000000000..e802c98abf64 --- /dev/null +++ b/vcl/aqua/source/dtrans/makefile.mk @@ -0,0 +1,72 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.14 $ +# +# 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. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=vcl +TARGET=dtransaqua +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +.IF "$(OS)"!="MACOSX" +dummy: + @echo "Nothing to build for this platform" +.ELSE # "$(OS)"!="MACOSX" +.IF "$(GUIBASE)"!="aqua" +dummy: + @echo "Nothing to build for GUIBASE $(GUIBASE)" +.ELSE + +CFLAGSCXX+=-fconstant-cfstrings -x objective-c++ -fobjc-exceptions + +SLOFILES= \ + $(SLO)$/aqua_clipboard.obj \ + $(SLO)$/DataFlavorMapping.obj \ + $(SLO)$/OSXTransferable.obj \ + $(SLO)$/HtmlFmtFlt.obj \ + $(SLO)$/PictToBmpFlt.obj \ + $(SLO)$/DropTarget.obj \ + $(SLO)$/DragSource.obj \ + $(SLO)$/service_entry.obj \ + $(SLO)$/DragSourceContext.obj \ + $(SLO)$/DragActionConversion.obj + +# --- Targets ------------------------------------------------------ +.INCLUDE : target.mk + +.ENDIF # "$(GUIBASE)"!="aqua" +.ENDIF # "$(OS)"!="MACOSX" + diff --git a/vcl/aqua/source/dtrans/service_entry.cxx b/vcl/aqua/source/dtrans/service_entry.cxx new file mode 100644 index 000000000000..38784ecb53dd --- /dev/null +++ b/vcl/aqua/source/dtrans/service_entry.cxx @@ -0,0 +1,67 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: service_entry.cxx,v $ + * $Revision: 1.3 $ + * + * 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 "saldata.hxx" +#include "salinst.h" +#include "DragSource.hxx" +#include "DropTarget.hxx" +#include "aqua_clipboard.hxx" +#include "osl/diagnose.h" + +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::cppu; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::datatransfer::clipboard; + + +Reference< XInterface > AquaSalInstance::CreateClipboard( const Sequence< Any >& i_rArguments ) +{ + SalData* pSalData = GetSalData(); + if( ! pSalData->mxClipboard.is() ) + pSalData->mxClipboard = Reference<XInterface>(static_cast< XClipboard* >(new AquaClipboard()), UNO_QUERY); + return pSalData->mxClipboard; +} + + +Reference<XInterface> AquaSalInstance::CreateDragSource() +{ + return Reference<XInterface>(static_cast< XInitialization* >(new DragSource()), UNO_QUERY); +} + +Reference<XInterface> AquaSalInstance::CreateDropTarget() +{ + return Reference<XInterface>(static_cast< XInitialization* >(new DropTarget()), UNO_QUERY); +} + diff --git a/vcl/aqua/source/dtrans/test_aquacb.cxx b/vcl/aqua/source/dtrans/test_aquacb.cxx new file mode 100644 index 000000000000..db60712ce852 --- /dev/null +++ b/vcl/aqua/source/dtrans/test_aquacb.cxx @@ -0,0 +1,211 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: test_aquacb.cxx,v $ + * $Revision: 1.6 $ + * + * 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 "aqua_clipboard.hxx" +#include <cppuhelper/servicefactory.hxx> +#include <com/sun/star/datatransfer/XTransferable.hpp> +#include <com/sun/star/datatransfer/clipboard/XClipboardOwner.hpp> +#include <com/sun/star/datatransfer/clipboard/XClipboardNotifier.hpp> +#include <com/sun/star/datatransfer/clipboard/XClipboardEx.hpp> +#include <com/sun/star/lang/XComponent.hpp> + +#ifndef _CPPUHELPER_IMPLBASE1_HXX_ +#include <cppuhelper/implbase2.hxx> +#endif +#include <rtl/ustring.hxx> +#include <sal/types.h> +#include <osl/diagnose.h> + +#include <stdio.h> + +using namespace ::rtl; +using namespace ::std; +using namespace ::cppu; +using namespace ::com::sun::star::datatransfer; +using namespace ::com::sun::star::datatransfer::clipboard; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; + +Reference< XTransferable > rXTransfRead; + +class TestTransferable : public WeakImplHelper2< XClipboardOwner, XTransferable > +{ +public: + TestTransferable(); + virtual Any SAL_CALL getTransferData( const DataFlavor& aFlavor ) throw(UnsupportedFlavorException, IOException, RuntimeException); + virtual Sequence< DataFlavor > SAL_CALL getTransferDataFlavors() throw(RuntimeException); + virtual sal_Bool SAL_CALL isDataFlavorSupported( const DataFlavor& aFlavor ) throw(RuntimeException); + virtual void SAL_CALL lostOwnership( const Reference< XClipboard >& xClipboard, const Reference< XTransferable >& xTrans ) throw(RuntimeException); + +private: + Sequence< DataFlavor > m_seqDFlv; + OUString m_Data; +}; + +TestTransferable::TestTransferable() : + m_seqDFlv( 1 ), + m_Data( RTL_CONSTASCII_USTRINGPARAM( "This is a test string" ) ) +{ + DataFlavor df; + + df.MimeType = OUString::createFromAscii( "text/html" ); + df.DataType = getCppuType( ( Sequence< sal_Int8 >* )0 ); + + m_seqDFlv[0] = df; +} + +Any SAL_CALL TestTransferable::getTransferData( const DataFlavor& aFlavor ) + throw(UnsupportedFlavorException, IOException, RuntimeException) +{ + Any anyData; + + if ( aFlavor.MimeType == m_seqDFlv[0].MimeType ) + { + OString aStr( m_Data.getStr(), m_Data.getLength(), 1252 ); + Sequence< sal_Int8 > sOfChars( aStr.getLength() ); + sal_Int32 lenStr = aStr.getLength(); + + for ( sal_Int32 i = 0; i < lenStr; ++i ) + sOfChars[i] = aStr[i]; + + anyData = makeAny( sOfChars ); + } + + return anyData; +} + +Sequence< DataFlavor > SAL_CALL TestTransferable::getTransferDataFlavors() + throw(RuntimeException) +{ + return m_seqDFlv; +} + +sal_Bool SAL_CALL TestTransferable::isDataFlavorSupported( const DataFlavor& aFlavor ) + throw(RuntimeException) +{ + sal_Int32 nLength = m_seqDFlv.getLength(); + sal_Bool bRet = sal_False; + + for ( sal_Int32 i = 0; i < nLength; ++i ) + { + if ( m_seqDFlv[i].MimeType == aFlavor.MimeType ) + { + bRet = sal_True; + break; + } + } + + return bRet; +} + +void SAL_CALL TestTransferable::lostOwnership( const Reference< XClipboard >& xClipboard, const Reference< XTransferable >& xTrans ) + throw(RuntimeException) +{ +} + +int SAL_CALL main( int argc, char** argv ) +{ + if(argc != 2) + { + fprintf( stderr, "usage: %s <my rdb file>\n", argv[0] ); + return 1; + } + + //------------------------------------------------- + // get the global service-manager + //------------------------------------------------- + OUString rdbName = OUString::createFromAscii( argv[1] ); + Reference< XMultiServiceFactory > g_xFactory( createRegistryServiceFactory( rdbName ) ); + + // Print a message if an error occured. + if ( !g_xFactory.is() ) + { + OSL_ENSURE(sal_False, "Can't create RegistryServiceFactory"); + return(-1); + } + + //------------------------------------------------- + // try to get an Interface to a XFilePicker Service + //------------------------------------------------- + + Reference< XTransferable > rXTransf( static_cast< XTransferable* >( new TestTransferable ) ); + + Reference< XClipboard > xClipboard( g_xFactory->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( AQUA_CLIPBOARD_SERVICE_NAME ) ) ), UNO_QUERY ); + if ( !xClipboard.is() ) + { + OSL_ENSURE( sal_False, "Error creating FolderPicker Service" ); + return(-1); + } + + Reference< XTypeProvider > rXTypProv( xClipboard, UNO_QUERY ); + + if ( rXTypProv.is() ) + { + Sequence< Type > seqType = rXTypProv->getTypes(); + sal_Int32 nLen = seqType.getLength(); + for ( sal_Int32 i = 0; i < nLen; i++ ) + { + Type nxtType = seqType[i]; + } + + Sequence< sal_Int8 > seqInt8 = rXTypProv->getImplementationId(); + } + + xClipboard->setContents( rXTransf, Reference< XClipboardOwner >( rXTransf, UNO_QUERY ) ); + + rXTransfRead = xClipboard->getContents(); + + // destroy the transferable explicitly + rXTransfRead = Reference< XTransferable>(); + + // destroy the clipboard + xClipboard = Reference< XClipboard >(); + + //-------------------------------------------------- + // shutdown the service manager + //-------------------------------------------------- + + // Cast factory to XComponent + Reference< XComponent > xComponent( g_xFactory, UNO_QUERY ); + + if ( !xComponent.is() ) + OSL_ENSURE(sal_False, "Error shuting down"); + + // Dispose and clear factory + xComponent->dispose(); + g_xFactory.clear(); + g_xFactory = Reference< XMultiServiceFactory >(); + + return 0; +} diff --git a/vcl/aqua/source/gdi/salbmp.cxx b/vcl/aqua/source/gdi/salbmp.cxx index 42f29d677b52..8b7b23a681a0 100644 --- a/vcl/aqua/source/gdi/salbmp.cxx +++ b/vcl/aqua/source/gdi/salbmp.cxx @@ -214,16 +214,26 @@ bool AquaSalBitmap::CreateContext() { // convert user data to 32 bit nContextBytesPerRow = mnWidth << 2; - maContextBuffer.reset( new sal_uInt8[ mnHeight * nContextBytesPerRow ] ); + try + { + maContextBuffer.reset( new sal_uInt8[ mnHeight * nContextBytesPerRow ] ); - if( !bSkipConversion ) - ConvertBitmapData( mnWidth, mnHeight, - 32, nContextBytesPerRow, maPalette, maContextBuffer.get(), - mnBits, mnBytesPerRow, maPalette, maUserBuffer.get() ); + if( !bSkipConversion ) + ConvertBitmapData( mnWidth, mnHeight, + 32, nContextBytesPerRow, maPalette, maContextBuffer.get(), + mnBits, mnBytesPerRow, maPalette, maUserBuffer.get() ); + } + catch( std::bad_alloc ) + { + mxGraphicContext = 0; + } } - mxGraphicContext = ::CGBitmapContextCreate( maContextBuffer.get(), mnWidth, mnHeight, - bitsPerComponent, nContextBytesPerRow, aCGColorSpace, aCGBmpInfo ); + if( maContextBuffer.get() ) + { + mxGraphicContext = ::CGBitmapContextCreate( maContextBuffer.get(), mnWidth, mnHeight, + bitsPerComponent, nContextBytesPerRow, aCGColorSpace, aCGBmpInfo ); + } if( !mxGraphicContext ) maContextBuffer.reset(); diff --git a/vcl/aqua/source/window/salframe.cxx b/vcl/aqua/source/window/salframe.cxx index 9c713ea26a52..b942c97cead1 100644 --- a/vcl/aqua/source/window/salframe.cxx +++ b/vcl/aqua/source/window/salframe.cxx @@ -43,6 +43,7 @@ #include "aqua11yfactory.h" #include "vcl/salwtype.hxx" #include "vcl/window.hxx" +#include "vcl/timer.hxx" #include "premac.h" // needed for theming @@ -749,16 +750,37 @@ void AquaSalFrame::ShowFullScreen( BOOL bFullScreen, sal_Int32 nDisplay ) // ----------------------------------------------------------------------- +class PreventSleepTimer : public AutoTimer +{ +public: + PreventSleepTimer() + { + SetTimeout( 30000 ); + Start(); + } + + virtual ~PreventSleepTimer() + { + } + + virtual void Timeout() + { + UpdateSystemActivity(OverallAct); + } +}; + void AquaSalFrame::StartPresentation( BOOL bStart ) { if( bStart ) { + mpActivityTimer.reset( new PreventSleepTimer() ); [mpWindow setLevel: NSScreenSaverWindowLevel]; if( mbShown ) [mpWindow makeMainWindow]; } else { + mpActivityTimer.reset(); [mpWindow setLevel: NSNormalWindowLevel]; } } @@ -1173,6 +1195,7 @@ void AquaSalFrame::UpdateSettings( AllSettings& rSettings ) Color aMenuTextColor( getColor( [NSColor textColor], aStyleSettings.GetMenuTextColor(), mpWindow ) ); aStyleSettings.SetMenuTextColor( aMenuTextColor ); + aStyleSettings.SetMenuBarTextColor( aMenuTextColor ); aStyleSettings.SetCursorBlinkTime( 500 ); diff --git a/vcl/aqua/source/window/salframeview.mm b/vcl/aqua/source/window/salframeview.mm index c7facd8c6c09..68ea2c2062f2 100755 --- a/vcl/aqua/source/window/salframeview.mm +++ b/vcl/aqua/source/window/salframeview.mm @@ -184,6 +184,8 @@ static AquaSalFrame* getMouseContainerFrame() return YES; if( mpFrame->mbFullScreen ) return YES; + if( (mpFrame->mnStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE) ) + return YES; return [super canBecomeKeyWindow]; } @@ -1420,7 +1422,7 @@ private: return 0; } -#ifdef MAC_OS_X_VERSION_10_5 +#if defined(MAC_OS_X_VERSION_10_5) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) /* build target 10.5 or greater */ - (NSInteger)conversationIdentifier #else |