summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
Diffstat (limited to 'vcl')
-rw-r--r--vcl/aqua/inc/saldata.hxx5
-rw-r--r--vcl/aqua/inc/salframe.h86
-rw-r--r--vcl/aqua/inc/salinst.h6
-rwxr-xr-xvcl/aqua/inc/vclnsapp.h4
-rw-r--r--vcl/aqua/source/a11y/aqua11yfactory.mm13
-rw-r--r--vcl/aqua/source/a11y/aqua11ywrapper.mm13
-rw-r--r--vcl/aqua/source/app/makefile.mk2
-rw-r--r--vcl/aqua/source/app/salinst.cxx14
-rwxr-xr-xvcl/aqua/source/app/vclnsapp.mm96
-rw-r--r--vcl/aqua/source/dtrans/DataFlavorMapping.cxx711
-rw-r--r--vcl/aqua/source/dtrans/DataFlavorMapping.hxx141
-rw-r--r--vcl/aqua/source/dtrans/DragActionConversion.cxx95
-rw-r--r--vcl/aqua/source/dtrans/DragActionConversion.hxx49
-rw-r--r--vcl/aqua/source/dtrans/DragSource.cxx366
-rw-r--r--vcl/aqua/source/dtrans/DragSource.hxx143
-rw-r--r--vcl/aqua/source/dtrans/DragSourceContext.cxx77
-rw-r--r--vcl/aqua/source/dtrans/DragSourceContext.hxx75
-rw-r--r--vcl/aqua/source/dtrans/DropTarget.cxx602
-rw-r--r--vcl/aqua/source/dtrans/DropTarget.hxx172
-rw-r--r--vcl/aqua/source/dtrans/HtmlFmtFlt.cxx147
-rw-r--r--vcl/aqua/source/dtrans/HtmlFmtFlt.hxx20
-rw-r--r--vcl/aqua/source/dtrans/OSXTransferable.cxx215
-rw-r--r--vcl/aqua/source/dtrans/OSXTransferable.hxx103
-rw-r--r--vcl/aqua/source/dtrans/PictToBmpFlt.cxx114
-rw-r--r--vcl/aqua/source/dtrans/PictToBmpFlt.hxx22
-rw-r--r--vcl/aqua/source/dtrans/aqua_clipboard.cxx385
-rw-r--r--vcl/aqua/source/dtrans/aqua_clipboard.hxx184
-rw-r--r--vcl/aqua/source/dtrans/aqua_service.cxx111
-rw-r--r--vcl/aqua/source/dtrans/makefile.mk72
-rw-r--r--vcl/aqua/source/dtrans/service_entry.cxx67
-rw-r--r--vcl/aqua/source/dtrans/test_aquacb.cxx211
-rw-r--r--vcl/aqua/source/gdi/salbmp.cxx24
-rw-r--r--vcl/aqua/source/window/salframe.cxx23
-rwxr-xr-xvcl/aqua/source/window/salframeview.mm4
-rw-r--r--vcl/inc/vcl/floatwin.hxx2
-rw-r--r--vcl/inc/vcl/lazydelete.hxx4
-rw-r--r--vcl/inc/vcl/ppdparser.hxx2
-rw-r--r--vcl/inc/vcl/salframe.hxx2
-rw-r--r--vcl/inc/vcl/salinst.hxx8
-rw-r--r--vcl/inc/vcl/settings.hxx5
-rw-r--r--vcl/inc/vcl/vclevent.hxx1
-rw-r--r--vcl/inc/vcl/wintypes.hxx1
-rw-r--r--vcl/os2/source/window/salframe.cxx1
-rw-r--r--vcl/prj/build.lst7
-rw-r--r--vcl/prj/d.lst5
-rw-r--r--vcl/source/app/settings.cxx3
-rw-r--r--vcl/source/app/svapp.cxx4
-rw-r--r--vcl/source/components/dtranscomp.cxx556
-rw-r--r--vcl/source/components/factory.cxx52
-rw-r--r--vcl/source/components/makefile.mk1
-rw-r--r--vcl/source/control/button.cxx13
-rw-r--r--vcl/source/control/combobox.cxx15
-rw-r--r--vcl/source/control/field.cxx3
-rw-r--r--vcl/source/control/fixed.cxx14
-rw-r--r--vcl/source/control/ilstbox.cxx17
-rw-r--r--vcl/source/control/imgctrl.cxx8
-rw-r--r--vcl/source/control/lstbox.cxx3
-rw-r--r--vcl/source/fontsubset/cff.cxx474
-rw-r--r--vcl/source/fontsubset/fontsubset.cxx2
-rw-r--r--vcl/source/gdi/outdev3.cxx136
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx11
-rw-r--r--vcl/source/gdi/wall.cxx2
-rw-r--r--vcl/source/glyphs/graphite_adaptors.cxx2
-rw-r--r--vcl/source/glyphs/graphite_cache.cxx2
-rw-r--r--vcl/source/glyphs/graphite_features.cxx2
-rw-r--r--vcl/source/glyphs/graphite_layout.cxx6
-rw-r--r--vcl/source/glyphs/graphite_serverfont.cxx2
-rw-r--r--vcl/source/helper/lazydelete.cxx3
-rw-r--r--vcl/source/window/brdwin.cxx2
-rw-r--r--vcl/source/window/dockmgr.cxx4
-rw-r--r--vcl/source/window/floatwin.cxx14
-rw-r--r--vcl/source/window/menu.cxx28
-rw-r--r--vcl/source/window/msgbox.cxx6
-rw-r--r--vcl/source/window/toolbox.cxx75
-rw-r--r--vcl/source/window/toolbox2.cxx4
-rw-r--r--vcl/source/window/window.cxx16
-rw-r--r--vcl/unx/gtk/a11y/atktext.cxx65
-rw-r--r--vcl/unx/gtk/a11y/atktextattributes.cxx13
-rw-r--r--vcl/unx/gtk/a11y/atktextattributes.hxx1
-rw-r--r--vcl/unx/gtk/a11y/atkwrapper.cxx2
-rw-r--r--vcl/unx/gtk/a11y/atkwrapper.hxx2
-rw-r--r--vcl/unx/gtk/app/gtkinst.cxx10
-rw-r--r--vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx39
-rw-r--r--vcl/unx/gtk/window/gtkframe.cxx5
-rw-r--r--vcl/unx/inc/salinst.h5
-rw-r--r--vcl/unx/kde/kdedata.cxx10
-rw-r--r--vcl/unx/kde/salnativewidgets-kde.cxx8
-rw-r--r--vcl/unx/kde4/KDEData.cxx2
-rw-r--r--vcl/unx/kde4/KDESalFrame.cxx1
-rw-r--r--vcl/unx/kde4/KDESalGraphics.cxx129
-rw-r--r--vcl/unx/kde4/main.cxx10
-rw-r--r--vcl/unx/source/app/salinst.cxx10
-rw-r--r--vcl/unx/source/app/sm.cxx40
-rw-r--r--vcl/unx/source/desktopdetect/desktopdetector.cxx346
-rw-r--r--vcl/unx/source/desktopdetect/makefile.mk61
-rw-r--r--vcl/unx/source/dtrans/X11_clipboard.cxx296
-rw-r--r--vcl/unx/source/dtrans/X11_clipboard.hxx154
-rw-r--r--vcl/unx/source/dtrans/X11_dndcontext.cxx141
-rw-r--r--vcl/unx/source/dtrans/X11_dndcontext.hxx105
-rw-r--r--vcl/unx/source/dtrans/X11_droptarget.cxx231
-rw-r--r--vcl/unx/source/dtrans/X11_selection.cxx4024
-rw-r--r--vcl/unx/source/dtrans/X11_selection.hxx518
-rw-r--r--vcl/unx/source/dtrans/X11_service.cxx138
-rw-r--r--vcl/unx/source/dtrans/X11_transferable.cxx137
-rw-r--r--vcl/unx/source/dtrans/X11_transferable.hxx75
-rw-r--r--vcl/unx/source/dtrans/bmp.cxx742
-rw-r--r--vcl/unx/source/dtrans/bmp.hxx106
-rw-r--r--vcl/unx/source/dtrans/config.cxx151
-rw-r--r--vcl/unx/source/dtrans/copydata_curs.h45
-rw-r--r--vcl/unx/source/dtrans/copydata_mask.h45
-rw-r--r--vcl/unx/source/dtrans/linkdata_curs.h45
-rw-r--r--vcl/unx/source/dtrans/linkdata_mask.h45
-rw-r--r--vcl/unx/source/dtrans/makefile.mk72
-rw-r--r--vcl/unx/source/dtrans/movedata_curs.h45
-rw-r--r--vcl/unx/source/dtrans/movedata_mask.h45
-rw-r--r--vcl/unx/source/dtrans/nodrop_curs.h45
-rw-r--r--vcl/unx/source/dtrans/nodrop_mask.h45
-rw-r--r--vcl/unx/source/gdi/cdeint.cxx1
-rw-r--r--vcl/unx/source/gdi/salgdi.cxx83
-rw-r--r--vcl/unx/source/plugadapt/salplug.cxx328
-rw-r--r--vcl/unx/source/printer/ppdparser.cxx8
-rw-r--r--vcl/unx/source/window/salframe.cxx7
-rw-r--r--vcl/util/makefile.mk29
-rw-r--r--vcl/util/makefile2.pmk1
-rwxr-xr-xvcl/win/source/gdi/winlayout.cxx2
-rw-r--r--vcl/win/source/window/salframe.cxx5
-rw-r--r--vcl/workben/makefile.mk3
127 files changed, 13517 insertions, 849 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..82ac5b6f4ffd 100644
--- a/vcl/aqua/inc/salinst.h
+++ b/vcl/aqua/inc/salinst.h
@@ -146,6 +146,12 @@ public:
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..56bf1a612b40 100644
--- a/vcl/aqua/source/app/salinst.cxx
+++ b/vcl/aqua/source/app/salinst.cxx
@@ -815,6 +815,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 +840,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;
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
diff --git a/vcl/inc/vcl/floatwin.hxx b/vcl/inc/vcl/floatwin.hxx
index 8dcba41e2a8e..02ac18ac28f8 100644
--- a/vcl/inc/vcl/floatwin.hxx
+++ b/vcl/inc/vcl/floatwin.hxx
@@ -157,6 +157,8 @@ public:
const Link& GetPopupModeEndHdl() const { return maPopupModeEndHdl; }
BOOL GrabsFocus() const { return mbGrabFocus; }
+
+ static Point CalcFloatingPosition( Window* pWindow, const Rectangle& rRect, ULONG nFlags, USHORT& rArrangeIndex );
};
#endif // _SV_FLOATWIN_HXX
diff --git a/vcl/inc/vcl/lazydelete.hxx b/vcl/inc/vcl/lazydelete.hxx
index a0acba21fefa..4821492af1f8 100644
--- a/vcl/inc/vcl/lazydelete.hxx
+++ b/vcl/inc/vcl/lazydelete.hxx
@@ -225,7 +225,7 @@ namespace vcl
SomeWindow::Paint()
{
- static vcl::DeleteOnDeinitBase< BitmapEx > aBmp( new BitmapEx( ResId( 1000, myResMgr ) ) );
+ static vcl::DeleteOnDeinit< BitmapEx > aBmp( new BitmapEx( ResId( 1000, myResMgr ) ) );
if( aBmp.get() ) // check whether DeInitVCL has been called already
DrawBitmapEx( Point( 10, 10 ), *aBmp.get() );
@@ -244,7 +244,7 @@ namespace vcl
};
template < typename T >
- class VCL_DLLPUBLIC DeleteOnDeinit : public DeleteOnDeinitBase
+ class DeleteOnDeinit : public DeleteOnDeinitBase
{
T* m_pT;
virtual void doCleanup() { delete m_pT; m_pT = NULL; }
diff --git a/vcl/inc/vcl/ppdparser.hxx b/vcl/inc/vcl/ppdparser.hxx
index 5fa47d412f26..ed9f91b97d99 100644
--- a/vcl/inc/vcl/ppdparser.hxx
+++ b/vcl/inc/vcl/ppdparser.hxx
@@ -202,7 +202,7 @@ public:
static const PPDParser* getParser( const String& rFile );
static String getPPDPrinterName( const String& rFile );
static void freeAll();
- static void getKnownPPDDrivers( std::list< rtl::OUString >& o_rDrivers );
+ static void getKnownPPDDrivers( std::list< rtl::OUString >& o_rDrivers, bool bRefresh = false );
const String& getFilename() const { return m_aFile; }
diff --git a/vcl/inc/vcl/salframe.hxx b/vcl/inc/vcl/salframe.hxx
index 7a99442ebd5b..0e3f4e94a0b3 100644
--- a/vcl/inc/vcl/salframe.hxx
+++ b/vcl/inc/vcl/salframe.hxx
@@ -102,6 +102,8 @@ struct SystemEnvData;
#define SAL_FRAME_STYLE_SYSTEMCHILD ((ULONG)0x08000000)
// floating window
#define SAL_FRAME_STYLE_FLOAT ((ULONG)0x20000000)
+// floating window that needs to be focusable
+#define SAL_FRAME_STYLE_FLOAT_FOCUSABLE ((ULONG)0x04000000)
// toolwindows should be painted with a smaller decoration
#define SAL_FRAME_STYLE_TOOLWINDOW ((ULONG)0x40000000)
// the window containing the intro bitmap, aka splashscreen
diff --git a/vcl/inc/vcl/salinst.hxx b/vcl/inc/vcl/salinst.hxx
index 221c9e370ea6..650e57cdccc4 100644
--- a/vcl/inc/vcl/salinst.hxx
+++ b/vcl/inc/vcl/salinst.hxx
@@ -31,6 +31,8 @@
#ifndef _SV_SALINST_HXX
#define _SV_SALINST_HXX
+#include "com/sun/star/uno/Reference.hxx"
+
#include "vcl/sv.h"
#include "vcl/dllapi.h"
@@ -176,6 +178,12 @@ public:
// this is only necessary because PrintFontManager is an exported vcl API and therefore
// needs to be in libvcl while libvclplug_* do not contain exported C++ API
virtual void FillFontPathList( std::list< rtl::OString >& o_rFontPaths );
+
+ // 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();
};
// called from SVMain
diff --git a/vcl/inc/vcl/settings.hxx b/vcl/inc/vcl/settings.hxx
index a7cd61477519..decb7d01b2d4 100644
--- a/vcl/inc/vcl/settings.hxx
+++ b/vcl/inc/vcl/settings.hxx
@@ -379,6 +379,7 @@ private:
Color maMenuHighlightColor;
Color maMenuHighlightTextColor;
Color maMenuTextColor;
+ Color maMenuBarTextColor;
Color maMonoColor;
Color maRadioCheckTextColor;
Color maShadowColor;
@@ -689,6 +690,10 @@ public:
{ CopyData(); mpData->maMenuTextColor = rColor; }
const Color& GetMenuTextColor() const
{ return mpData->maMenuTextColor; }
+ void SetMenuBarTextColor( const Color& rColor )
+ { CopyData(); mpData->maMenuBarTextColor = rColor; }
+ const Color& GetMenuBarTextColor() const
+ { return mpData->maMenuBarTextColor; }
void SetMenuHighlightColor( const Color& rColor )
{ CopyData(); mpData->maMenuHighlightColor = rColor; }
const Color& GetMenuHighlightColor() const
diff --git a/vcl/inc/vcl/vclevent.hxx b/vcl/inc/vcl/vclevent.hxx
index a28127dd6f82..ff0639d70e82 100644
--- a/vcl/inc/vcl/vclevent.hxx
+++ b/vcl/inc/vcl/vclevent.hxx
@@ -150,6 +150,7 @@ class Menu;
#define VCLEVENT_LISTBOX_ENTRY_EXPANDED 1174
#define VCLEVENT_LISTBOX_ENTRY_COLLAPSED 1175
// <--
+#define VCLEVENT_DROPDOWN_PRE_OPEN 1176
// VclMenuEvent
#define VCLEVENT_MENU_ACTIVATE 1200
diff --git a/vcl/inc/vcl/wintypes.hxx b/vcl/inc/vcl/wintypes.hxx
index f5869eca55e4..968f0e1d255f 100644
--- a/vcl/inc/vcl/wintypes.hxx
+++ b/vcl/inc/vcl/wintypes.hxx
@@ -194,6 +194,7 @@ typedef sal_Int64 WinBits;
#define WB_TOOLTIPWIN ((WinBits)SAL_CONST_INT64(0x800000000))
#define WB_OWNERDRAWDECORATION ((WinBits)SAL_CONST_INT64(0x2000000000))
#define WB_DEFAULTWIN ((WinBits)SAL_CONST_INT64(0x4000000000))
+#define WB_NEEDSFOCUS ((WinBits)SAL_CONST_INT64(0x1000000000))
#define WB_HIDE ((WinBits)SAL_CONST_INT64(0x80000000))
#define WB_HSCROLL WB_HORZ
diff --git a/vcl/os2/source/window/salframe.cxx b/vcl/os2/source/window/salframe.cxx
index 8860d68d683e..345573b268c3 100644
--- a/vcl/os2/source/window/salframe.cxx
+++ b/vcl/os2/source/window/salframe.cxx
@@ -2172,6 +2172,7 @@ void Os2SalFrame::UpdateSettings( AllSettings& rSettings )
aStyleSettings.SetDeactiveBorderColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_INACTIVEBORDER, 0 ) ) );
aStyleSettings.SetMenuColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_MENU, 0 ) ) );
aStyleSettings.SetMenuTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_MENUTEXT, 0 ) ) );
+ aStyleSettings.SetMenuBarTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_MENUTEXT, 0 ) ) );
}
aStyleSettings.SetDialogTextColor( aStyleSettings.GetButtonTextColor() );
aStyleSettings.SetRadioCheckTextColor( aStyleSettings.GetButtonTextColor() );
diff --git a/vcl/prj/build.lst b/vcl/prj/build.lst
index 52b444164029..908dd1eafd72 100644
--- a/vcl/prj/build.lst
+++ b/vcl/prj/build.lst
@@ -14,13 +14,15 @@ vc vcl\os2\source\app nmake - p vc__appp vc_inc NULL
vc vcl\os2\source\gdi nmake - p vc__gdip vc_inc NULL
vc vcl\os2\source\window nmake - p vc__winp vc_inc NULL
vc vcl\os2\source\src nmake - p vc__srcp vc_inc NULL
-vc vcl\source\components nmake - all vc_components NULL
+vc vcl\source\components nmake - all vc_components vc_inc NULL
vc vcl\win\source\app nmake - w vc__appw vc_inc NULL
vc vcl\win\source\gdi nmake - w vc__gdiw vc_inc NULL
vc vcl\win\source\window nmake - w vc__winw vc_inc NULL
vc vcl\win\source\src nmake - w vc__srcw vc_inc NULL
vc vcl\unx\source\plugadapt nmake - u vc__plug vc_inc NULL
+vc vcl\unx\source\desktopdetect nmake - u vc__desk vc_inc NULL
vc vcl\unx\source\app nmake - u vc__appu vc_inc NULL
+vc vcl\unx\source\dtrans nmake - u vc__dtru vc_inc NULL
vc vcl\unx\source\fontmanager nmake - u vc__ftmu vc_inc NULL
vc vcl\unx\source\gdi nmake - u vc__gdiu vc_inc NULL
vc vcl\unx\source\printer nmake - u vc__prnu vc_inc NULL
@@ -35,6 +37,7 @@ vc vcl\unx\kde nmake - u vc__kde vc_inc NULL
vc vcl\unx\kde4 nmake - u vc__kde4 vc_inc NULL
vc vcl\aqua\source\a11y nmake - u vc__aquy vc_inc NULL
vc vcl\aqua\source\app nmake - u vc__appa vc_inc NULL
+vc vcl\aqua\source\dtrans nmake - u vc__dtra vc_inc NULL
vc vcl\aqua\source\gdi nmake - u vc__gdia vc_inc NULL
vc vcl\aqua\source\res nmake - u vc__resa NULL
vc vcl\aqua\source\window nmake - u vc__wina vc_inc NULL
@@ -42,6 +45,6 @@ vc vcl\mac\source\app nmake - m vc__appm vc_inc NULL
vc vcl\mac\source\gdi nmake - m vc__gdim vc_inc NULL
vc vcl\mac\source\window nmake - m vc__winm vc_inc NULL
vc vcl\mac\source\src nmake - m vc__srcm vc_inc NULL
-vc vcl\util nmake - all vc_util vc__plug.u vc__aquy.u vc__appa.u vc__appm.m vc__appu.u vc__appw.w vc__appp.p vc__gdia.u vc__gdim.m vc__gdiu.u vc__gdiw.w vc__gdip.p vc__srcm.m vc__srcw.w vc__srcp.p vc__wina.u vc__winm.m vc__winu.u vc__winw.w vc__winp.p vc__gtka.u vc__gtky.u vc__gtkw.u vc__gtkg.u vc__kde.u vc__kde4.u vc__hl.u vc__ftmu.u vc__prgu.u vc__prnu.u vc_app vc_ctrl vc_gdi vc_hlp vc_src vc_win vc_glyphs vc_fts vc_components NULL
+vc vcl\util nmake - all vc_util vc__plug.u vc__desk.u vc__aquy.u vc__appa.u vc__dtra.u vc__appm.m vc__appu.u vc__dtru.u vc__appw.w vc__appp.p vc__gdia.u vc__gdim.m vc__gdiu.u vc__gdiw.w vc__gdip.p vc__srcm.m vc__srcw.w vc__srcp.p vc__wina.u vc__winm.m vc__winu.u vc__winw.w vc__winp.p vc__gtka.u vc__gtky.u vc__gtkw.u vc__gtkg.u vc__kde.u vc__kde4.u vc__hl.u vc__ftmu.u vc__prgu.u vc__prnu.u vc_app vc_ctrl vc_gdi vc_hlp vc_src vc_win vc_glyphs vc_fts vc_components NULL
vc vcl\util\linksvp nmake - u vc_lsvp vc_util NULL
vc vcl\workben nmake - all vc_wrkb vc_util vc_salmain NULL
diff --git a/vcl/prj/d.lst b/vcl/prj/d.lst
index d9c14f46b8d1..983628184177 100644
--- a/vcl/prj/d.lst
+++ b/vcl/prj/d.lst
@@ -1,14 +1,12 @@
mkdir: %COMMON_DEST%\bin%_EXT%\hid
mkdir: %_DEST%\inc%_EXT%\vcl
-mkdir: %_DEST%\inc%_EXT%\vcl\plug
-mkdir: %_DEST%\inc%_EXT%\vcl\plug\vcl
..\%COMMON_OUTDIR%\bin\*.zip %COMMON_DEST%\bin%_EXT%\*.zip
..\%COMMON_OUTDIR%\misc\*.hid %COMMON_DEST%\bin%_EXT%\hid\*.hid
..\%__SRC%\bin\vcl*.res %_DEST%\bin%_EXT%\vcl*.res
..\%__SRC%\bin\vcl?????.dll %_DEST%\bin%_EXT%\vcl?????.dll
..\%__SRC%\bin\vcl?????.sym %_DEST%\bin%_EXT%\vcl?????.sym
-..\%__SRC%\lib\libvcl*.so %_DEST%\lib%_EXT%\libvcl*.so
+..\%__SRC%\lib\lib*.so %_DEST%\lib%_EXT%\lib*.so
..\%__SRC%\lib\*.dylib %_DEST%\lib%_EXT%\*.dylib
..\%__SRC%\lib\ivcl.lib %_DEST%\lib%_EXT%\ivcl.lib
..\%__SRC%\misc\vcl?????.map %_DEST%\bin%_EXT%\vcl?????.map
@@ -153,3 +151,4 @@ mkdir: %_DEST%\inc%_EXT%\vcl\plug\vcl
..\inc\vcl\ppdparser.hxx %_DEST%\inc%_EXT%\vcl\ppdparser.hxx
..\inc\vcl\helper.hxx %_DEST%\inc%_EXT%\vcl\helper.hxx
..\inc\vcl\strhelper.hxx %_DEST%\inc%_EXT%\vcl\strhelper.hxx
+..\inc\vcl\lazydelete.hxx %_DEST%\inc%_EXT%\vcl\lazydelete.hxx \ No newline at end of file
diff --git a/vcl/source/app/settings.cxx b/vcl/source/app/settings.cxx
index 444f1f58c8fb..6aa453563596 100644
--- a/vcl/source/app/settings.cxx
+++ b/vcl/source/app/settings.cxx
@@ -478,6 +478,7 @@ ImplStyleData::ImplStyleData( const ImplStyleData& rData ) :
maMenuHighlightColor( rData.maMenuHighlightColor ),
maMenuHighlightTextColor( rData.maMenuHighlightTextColor ),
maMenuTextColor( rData.maMenuTextColor ),
+ maMenuBarTextColor( rData.maMenuBarTextColor ),
maMonoColor( rData.maMonoColor ),
maRadioCheckTextColor( rData.maRadioCheckTextColor ),
maShadowColor( rData.maShadowColor ),
@@ -597,6 +598,7 @@ void ImplStyleData::SetStandardStyles()
maMenuBarColor = Color( COL_LIGHTGRAY );
maMenuBorderColor = Color( COL_LIGHTGRAY );
maMenuTextColor = Color( COL_BLACK );
+ maMenuBarTextColor = Color( COL_BLACK );
maMenuHighlightColor = Color( COL_BLUE );
maMenuHighlightTextColor = Color( COL_WHITE );
maHighlightColor = Color( COL_BLUE );
@@ -1028,6 +1030,7 @@ BOOL StyleSettings::operator ==( const StyleSettings& rSet ) const
(mpData->maMenuBarColor == rSet.mpData->maMenuBarColor) &&
(mpData->maMenuBorderColor == rSet.mpData->maMenuBorderColor) &&
(mpData->maMenuTextColor == rSet.mpData->maMenuTextColor) &&
+ (mpData->maMenuBarTextColor == rSet.mpData->maMenuBarTextColor) &&
(mpData->maMenuHighlightColor == rSet.mpData->maMenuHighlightColor) &&
(mpData->maMenuHighlightTextColor == rSet.mpData->maMenuHighlightTextColor) &&
(mpData->maHighlightColor == rSet.mpData->maHighlightColor) &&
diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
index 262910d18c82..b53ceceeb757 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -674,11 +674,11 @@ void Application::MergeSystemSettings( AllSettings& rSettings )
ImplSVData* pSVData = ImplGetSVData();
if ( !pSVData->maAppData.mbSettingsInit )
{
- pWindow->ImplGetFrame()->UpdateSettings( *pSVData->maAppData.mpSettings );
+ // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
pWindow->ImplUpdateGlobalSettings( *pSVData->maAppData.mpSettings );
pSVData->maAppData.mbSettingsInit = TRUE;
}
- pWindow->ImplGetFrame()->UpdateSettings( rSettings );
+ // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
pWindow->ImplUpdateGlobalSettings( rSettings, FALSE );
}
}
diff --git a/vcl/source/components/dtranscomp.cxx b/vcl/source/components/dtranscomp.cxx
new file mode 100644
index 000000000000..58792cd4fbdb
--- /dev/null
+++ b/vcl/source/components/dtranscomp.cxx
@@ -0,0 +1,556 @@
+/*************************************************************************
+ *
+ * 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: fontident.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/lang/XServiceInfo.hpp"
+#include "com/sun/star/lang/XSingleServiceFactory.hpp"
+#include "com/sun/star/lang/XInitialization.hpp"
+#include "com/sun/star/lang/DisposedException.hpp"
+#include "com/sun/star/datatransfer/XTransferable.hpp"
+#include "com/sun/star/datatransfer/clipboard/XClipboard.hpp"
+#include "com/sun/star/datatransfer/clipboard/XClipboardEx.hpp"
+#include "com/sun/star/datatransfer/clipboard/XClipboardNotifier.hpp"
+#include "com/sun/star/datatransfer/clipboard/XClipboardListener.hpp"
+#include "com/sun/star/datatransfer/dnd/XDragSource.hpp"
+#include "com/sun/star/datatransfer/dnd/XDropTarget.hpp"
+#include "com/sun/star/datatransfer/dnd/DNDConstants.hpp"
+
+#include "vcl/svapp.hxx"
+#include "vcl/svdata.hxx"
+#include "vcl/salinst.hxx"
+#include "vos/mutex.hxx"
+#include "osl/mutex.hxx"
+
+#include "cppuhelper/compbase1.hxx"
+#include "cppuhelper/compbase2.hxx"
+#include "cppuhelper/compbase3.hxx"
+#include "cppuhelper/implbase1.hxx"
+
+using rtl::OUString;
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+
+// -----------------------------------------------------------------------
+
+namespace vcl
+{
+// generic implementation to satisfy SalInstance
+class GenericClipboard :
+ public cppu::WeakComponentImplHelper3 <
+ datatransfer::clipboard::XClipboardEx,
+ datatransfer::clipboard::XClipboardNotifier,
+ XServiceInfo
+ >
+{
+ osl::Mutex m_aMutex;
+ Reference< ::com::sun::star::datatransfer::XTransferable > m_aContents;
+ Reference< ::com::sun::star::datatransfer::clipboard::XClipboardOwner > m_aOwner;
+ std::list< Reference< ::com::sun::star::datatransfer::clipboard::XClipboardListener > > m_aListeners;
+
+ void fireChangedContentsEvent();
+ void clearContents();
+
+public:
+
+ GenericClipboard() : cppu::WeakComponentImplHelper3<
+ datatransfer::clipboard::XClipboardEx,
+ datatransfer::clipboard::XClipboardNotifier,
+ XServiceInfo
+ >( m_aMutex )
+ {}
+ virtual ~GenericClipboard();
+
+ /*
+ * XServiceInfo
+ */
+
+ virtual rtl::OUString SAL_CALL getImplementationName() throw( RuntimeException );
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw( RuntimeException );
+ virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw( RuntimeException );
+
+ static rtl::OUString getImplementationName_static();
+ static Sequence< rtl::OUString > getSupportedServiceNames_static();
+
+ /*
+ * XClipboard
+ */
+
+ virtual Reference< ::com::sun::star::datatransfer::XTransferable > SAL_CALL getContents()
+ throw(RuntimeException);
+
+ virtual void SAL_CALL setContents(
+ const Reference< ::com::sun::star::datatransfer::XTransferable >& xTrans,
+ const Reference< ::com::sun::star::datatransfer::clipboard::XClipboardOwner >& xClipboardOwner )
+ throw(RuntimeException);
+
+ virtual ::rtl::OUString SAL_CALL getName()
+ throw(RuntimeException);
+
+ /*
+ * XClipboardEx
+ */
+
+ virtual sal_Int8 SAL_CALL getRenderingCapabilities()
+ throw(RuntimeException);
+
+ /*
+ * XClipboardNotifier
+ */
+ virtual void SAL_CALL addClipboardListener(
+ const Reference< ::com::sun::star::datatransfer::clipboard::XClipboardListener >& listener )
+ throw(RuntimeException);
+
+ virtual void SAL_CALL removeClipboardListener(
+ const Reference< ::com::sun::star::datatransfer::clipboard::XClipboardListener >& listener )
+ throw(RuntimeException);
+};
+
+GenericClipboard::~GenericClipboard()
+{
+}
+
+rtl::OUString GenericClipboard::getImplementationName_static()
+{
+ return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.datatransfer.VCLGenericClipboard" ) );
+}
+
+Sequence< rtl::OUString > GenericClipboard::getSupportedServiceNames_static()
+{
+ Sequence< OUString > aRet(1);
+ aRet[0] = OUString::createFromAscii("com.sun.star.datatransfer.clipboard.SystemClipboard");
+ return aRet;
+}
+
+rtl::OUString GenericClipboard::getImplementationName() throw( RuntimeException )
+{
+ return getImplementationName_static();
+}
+
+Sequence< rtl::OUString > GenericClipboard::getSupportedServiceNames() throw( RuntimeException )
+{
+ return getSupportedServiceNames_static();
+}
+
+sal_Bool GenericClipboard::supportsService( const ::rtl::OUString& ServiceName ) throw( RuntimeException )
+{
+ Sequence< OUString > aServices( getSupportedServiceNames() );
+ sal_Int32 nServices = aServices.getLength();
+ for( sal_Int32 i = 0; i < nServices; i++ )
+ {
+ if( aServices[i] == ServiceName )
+ return sal_True;
+ }
+ return sal_False;
+}
+
+Reference< ::com::sun::star::datatransfer::XTransferable > GenericClipboard::getContents() throw( RuntimeException )
+{
+ return m_aContents;
+}
+
+void GenericClipboard::setContents(
+ const Reference< ::com::sun::star::datatransfer::XTransferable >& xTrans,
+ const Reference< ::com::sun::star::datatransfer::clipboard::XClipboardOwner >& xClipboardOwner )
+ throw( RuntimeException )
+{
+ osl::ClearableMutexGuard aGuard( m_aMutex );
+ Reference< datatransfer::clipboard::XClipboardOwner > xOldOwner( m_aOwner );
+ Reference< datatransfer::XTransferable > xOldContents( m_aContents );
+ m_aContents = xTrans;
+ m_aOwner = xClipboardOwner;
+
+ std::list< Reference< datatransfer::clipboard::XClipboardListener > > xListeners( m_aListeners );
+ datatransfer::clipboard::ClipboardEvent aEv;
+ aEv.Contents = m_aContents;
+
+ aGuard.clear();
+
+ if( xOldOwner.is() && xOldOwner != xClipboardOwner )
+ xOldOwner->lostOwnership( this, xOldContents );
+ for( std::list< Reference< datatransfer::clipboard::XClipboardListener > >::iterator it =
+ xListeners.begin(); it != xListeners.end() ; ++it )
+ {
+ (*it)->changedContents( aEv );
+ }
+}
+
+rtl::OUString GenericClipboard::getName() throw( RuntimeException )
+{
+ return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CLIPBOARD" ) );
+}
+
+sal_Int8 GenericClipboard::getRenderingCapabilities() throw( RuntimeException )
+{
+ return 0;
+}
+
+void GenericClipboard::addClipboardListener( const Reference< datatransfer::clipboard::XClipboardListener >& listener )
+ throw( RuntimeException )
+{
+ osl::ClearableMutexGuard aGuard( m_aMutex );
+
+ m_aListeners.push_back( listener );
+}
+
+void GenericClipboard::removeClipboardListener( const Reference< datatransfer::clipboard::XClipboardListener >& listener )
+ throw( RuntimeException )
+{
+ osl::ClearableMutexGuard aGuard( m_aMutex );
+
+ m_aListeners.remove( listener );
+}
+
+// ------------------------------------------------------------------------
+
+class ClipboardFactory : public ::cppu::WeakComponentImplHelper1<
+ com::sun::star::lang::XSingleServiceFactory
+>
+{
+ osl::Mutex m_aMutex;
+public:
+ ClipboardFactory();
+ virtual ~ClipboardFactory();
+
+ /*
+ * XSingleServiceFactory
+ */
+ virtual Reference< XInterface > SAL_CALL createInstance() throw();
+ virtual Reference< XInterface > SAL_CALL createInstanceWithArguments( const Sequence< Any >& rArgs ) throw();
+};
+
+// ------------------------------------------------------------------------
+
+ClipboardFactory::ClipboardFactory() :
+ cppu::WeakComponentImplHelper1<
+ com::sun::star::lang::XSingleServiceFactory
+>( m_aMutex )
+{
+}
+
+// ------------------------------------------------------------------------
+
+ClipboardFactory::~ClipboardFactory()
+{
+}
+
+// ------------------------------------------------------------------------
+
+Reference< XInterface > ClipboardFactory::createInstance() throw()
+{
+ return createInstanceWithArguments( Sequence< Any >() );
+}
+
+// ------------------------------------------------------------------------
+
+Reference< XInterface > ClipboardFactory::createInstanceWithArguments( const Sequence< Any >& arguments ) throw()
+{
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+ Reference< XInterface > xResult = ImplGetSVData()->mpDefInst->CreateClipboard( arguments );
+ return xResult;
+}
+
+// ------------------------------------------------------------------------
+
+Sequence< OUString > SAL_CALL Clipboard_getSupportedServiceNames()
+{
+ Sequence< OUString > aRet(1);
+ aRet[0] = OUString::createFromAscii("com.sun.star.datatransfer.clipboard.SystemClipboard");
+ return aRet;
+}
+
+OUString SAL_CALL Clipboard_getImplementationName()
+{
+ #if defined UNX
+ return OUString( RTL_CONSTASCII_USTRINGPARAM(
+ #if ! defined QUARTZ
+ "com.sun.star.datatransfer.X11ClipboardSupport"
+ #else
+ "com.sun.star.datatransfer.clipboard.AquaClipboard"
+ #endif
+ ) );
+ #else
+ return GenericClipboard::getImplementationName_static();
+ #endif
+}
+
+Reference< XSingleServiceFactory > SAL_CALL Clipboard_createFactory( const Reference< XMultiServiceFactory > & )
+{
+ return Reference< XSingleServiceFactory >( new ClipboardFactory() );
+}
+
+/*
+* generic DragSource dummy
+*/
+class GenericDragSource : public cppu::WeakComponentImplHelper2<
+ datatransfer::dnd::XDragSource,
+ XInitialization
+ >
+{
+ osl::Mutex m_aMutex;
+public:
+ GenericDragSource() : cppu::WeakComponentImplHelper2< datatransfer::dnd::XDragSource, XInitialization >( m_aMutex ) {}
+ virtual ~GenericDragSource();
+
+ // XDragSource
+ virtual sal_Bool SAL_CALL isDragImageSupported() throw();
+ virtual sal_Int32 SAL_CALL getDefaultCursor( sal_Int8 dragAction ) throw();
+ virtual void SAL_CALL startDrag(
+ const datatransfer::dnd::DragGestureEvent& trigger,
+ sal_Int8 sourceActions, sal_Int32 cursor, sal_Int32 image,
+ const Reference< datatransfer::XTransferable >& transferable,
+ const Reference< datatransfer::dnd::XDragSourceListener >& listener
+ ) throw();
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const Sequence< Any >& arguments ) throw( ::com::sun::star::uno::Exception );
+
+ static Sequence< OUString > getSupportedServiceNames_static()
+ {
+ Sequence< OUString > aRet( 1 );
+ aRet[0] = OUString::createFromAscii( "com.sun.star.datatransfer.dnd.GenericDragSource" );
+ return aRet;
+ }
+
+ static OUString getImplementationName_static()
+ {
+ return OUString::createFromAscii( "com.sun.star.datatransfer.dnd.VclGenericDragSource" );
+ }
+};
+
+GenericDragSource::~GenericDragSource()
+{
+}
+
+sal_Bool GenericDragSource::isDragImageSupported() throw()
+{
+ return sal_False;
+}
+
+sal_Int32 GenericDragSource::getDefaultCursor( sal_Int8 ) throw()
+{
+ return 0;
+}
+
+void GenericDragSource::startDrag( const datatransfer::dnd::DragGestureEvent&,
+ sal_Int8 /*sourceActions*/, sal_Int32 /*cursor*/, sal_Int32 /*image*/,
+ const Reference< datatransfer::XTransferable >&,
+ const Reference< datatransfer::dnd::XDragSourceListener >& listener
+ ) throw()
+{
+ datatransfer::dnd::DragSourceDropEvent aEv;
+ aEv.DropAction = datatransfer::dnd::DNDConstants::ACTION_COPY;
+ aEv.DropSuccess = sal_False;
+ listener->dragDropEnd( aEv );
+}
+
+void GenericDragSource::initialize( const Sequence< Any >& ) throw( Exception )
+{
+}
+
+
+Sequence< OUString > SAL_CALL DragSource_getSupportedServiceNames()
+{
+ #if defined UNX
+ static OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM(
+ #if ! defined QUARTZ
+ "com.sun.star.datatransfer.dnd.X11DragSource"
+ #else
+ "com.sun.star.datatransfer.dnd.OleDragSource"
+ #endif
+ ) );
+ static Sequence< OUString > aServiceNames( &aServiceName, 1 );
+ return aServiceNames;
+ #else
+ return GenericDragSource::getSupportedServiceNames_static();
+ #endif
+}
+
+OUString SAL_CALL DragSource_getImplementationName()
+{
+ #if defined UNX
+ return OUString( RTL_CONSTASCII_USTRINGPARAM(
+ #if ! defined QUARTZ
+ "com.sun.star.datatransfer.dnd.XdndSupport"
+ #else
+ "com.sun.star.comp.datatransfer.dnd.OleDragSource_V1"
+ #endif
+ ) );
+ #else
+ return GenericDragSource::getImplementationName_static();
+ #endif
+}
+
+Reference< XInterface > SAL_CALL DragSource_createInstance( const Reference< XMultiServiceFactory >& )
+{
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+ Reference< XInterface > xResult = ImplGetSVData()->mpDefInst->CreateDragSource();
+ return xResult;
+}
+
+/*
+* generic DragSource dummy
+*/
+
+class GenericDropTarget : public cppu::WeakComponentImplHelper2<
+ datatransfer::dnd::XDropTarget,
+ XInitialization
+ >
+{
+ osl::Mutex m_aMutex;
+public:
+ GenericDropTarget() : cppu::WeakComponentImplHelper2<
+ datatransfer::dnd::XDropTarget,
+ XInitialization
+ > ( m_aMutex )
+ {}
+ virtual ~GenericDropTarget();
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const Sequence< Any >& args ) throw ( Exception );
+
+ // XDropTarget
+ virtual void SAL_CALL addDropTargetListener( const Reference< ::com::sun::star::datatransfer::dnd::XDropTargetListener >& ) throw();
+ virtual void SAL_CALL removeDropTargetListener( const Reference< ::com::sun::star::datatransfer::dnd::XDropTargetListener >& ) throw();
+ virtual sal_Bool SAL_CALL isActive() throw();
+ virtual void SAL_CALL setActive( sal_Bool active ) throw();
+ virtual sal_Int8 SAL_CALL getDefaultActions() throw();
+ virtual void SAL_CALL setDefaultActions( sal_Int8 actions ) throw();
+
+ static Sequence< OUString > getSupportedServiceNames_static()
+ {
+ Sequence< OUString > aRet( 1 );
+ aRet[0] = OUString::createFromAscii( "com.sun.star.datatransfer.dnd.GenericDropTarget" );
+ return aRet;
+ }
+
+ static OUString getImplementationName_static()
+ {
+ return OUString::createFromAscii( "com.sun.star.datatransfer.dnd.VclGenericDropTarget" );
+ }
+};
+
+GenericDropTarget::~GenericDropTarget()
+{
+}
+
+void GenericDropTarget::initialize( const Sequence< Any >& ) throw( Exception )
+{
+}
+
+void GenericDropTarget::addDropTargetListener( const Reference< ::com::sun::star::datatransfer::dnd::XDropTargetListener >& ) throw()
+{
+}
+
+void GenericDropTarget::removeDropTargetListener( const Reference< ::com::sun::star::datatransfer::dnd::XDropTargetListener >& ) throw()
+{
+}
+
+sal_Bool GenericDropTarget::isActive() throw()
+{
+ return sal_False;
+}
+
+void GenericDropTarget::setActive( sal_Bool ) throw()
+{
+}
+
+sal_Int8 GenericDropTarget::getDefaultActions() throw()
+{
+ return 0;
+}
+
+void GenericDropTarget::setDefaultActions( sal_Int8) throw()
+{
+}
+
+Sequence< OUString > SAL_CALL DropTarget_getSupportedServiceNames()
+{
+ #if defined UNX
+ static OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM(
+ #if ! defined QUARTZ
+ "com.sun.star.datatransfer.dnd.X11DropTarget"
+ #else
+ "com.sun.star.datatransfer.dnd.OleDropTarget"
+ #endif
+ ) );
+ static Sequence< OUString > aServiceNames( &aServiceName, 1 );
+ return aServiceNames;
+ #else
+ return GenericDropTarget::getSupportedServiceNames_static();
+ #endif
+}
+
+OUString SAL_CALL DropTarget_getImplementationName()
+{
+ #if defined UNX
+ return OUString( RTL_CONSTASCII_USTRINGPARAM(
+ #if ! defined QUARTZ
+ "com.sun.star.datatransfer.dnd.XdndDropTarget"
+ #else
+ "com.sun.star.comp.datatransfer.dnd.OleDropTarget_V1"
+ #endif
+ ) );
+ #else
+ return GenericDropTarget::getImplementationName_static();
+ #endif
+}
+
+Reference< XInterface > SAL_CALL DropTarget_createInstance( const Reference< XMultiServiceFactory >& )
+{
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+ Reference< XInterface > xResult = ImplGetSVData()->mpDefInst->CreateDropTarget();
+ return xResult;
+}
+
+
+} // namespace vcl
+
+/*
+* SalInstance generic
+*/
+Reference< XInterface > SalInstance::CreateClipboard( const Sequence< Any >& )
+{
+ return Reference< XInterface >( ( cppu::OWeakObject * )new vcl::GenericClipboard() );
+}
+
+Reference< XInterface > SalInstance::CreateDragSource()
+{
+ return Reference< XInterface >( ( cppu::OWeakObject * )new vcl::GenericDragSource() );
+}
+
+Reference< XInterface > SalInstance::CreateDropTarget()
+{
+ return Reference< XInterface >( ( cppu::OWeakObject * )new vcl::GenericDropTarget() );
+}
+
diff --git a/vcl/source/components/factory.cxx b/vcl/source/components/factory.cxx
index ef2e5c3b85fd..e816c31c613a 100644
--- a/vcl/source/components/factory.cxx
+++ b/vcl/source/components/factory.cxx
@@ -59,11 +59,23 @@ namespace vcl
{
extern Sequence< OUString > SAL_CALL DisplayAccess_getSupportedServiceNames();
extern OUString SAL_CALL DisplayAccess_getImplementationName();
-extern Reference< XInterface > SAL_CALL DisplayAccess_createInstance( const Reference< XMultiServiceFactory > & );
+extern Reference< XInterface > SAL_CALL DisplayAccess_createInstance( const Reference< XMultiServiceFactory > & );
extern Sequence< OUString > SAL_CALL FontIdentificator_getSupportedServiceNames();
extern OUString SAL_CALL FontIdentificator_getImplementationName();
-extern Reference< XInterface > SAL_CALL FontIdentificator_createInstance( const Reference< XMultiServiceFactory > & );
+extern Reference< XInterface > SAL_CALL FontIdentificator_createInstance( const Reference< XMultiServiceFactory > & );
+
+extern Sequence< OUString > SAL_CALL Clipboard_getSupportedServiceNames();
+extern OUString SAL_CALL Clipboard_getImplementationName();
+extern Reference< XSingleServiceFactory > SAL_CALL Clipboard_createFactory( const Reference< XMultiServiceFactory > & );
+
+extern Sequence< OUString > SAL_CALL DragSource_getSupportedServiceNames();
+extern OUString SAL_CALL DragSource_getImplementationName();
+extern Reference< XInterface > SAL_CALL DragSource_createInstance( const Reference< XMultiServiceFactory > & );
+
+extern Sequence< OUString > SAL_CALL DropTarget_getSupportedServiceNames();
+extern OUString SAL_CALL DropTarget_getImplementationName();
+extern Reference< XInterface > SAL_CALL DropTarget_createInstance( const Reference< XMultiServiceFactory > & );
}
extern "C" {
@@ -102,6 +114,26 @@ extern "C" {
aImplName.append( vcl::FontIdentificator_getSupportedServiceNames()[0] );
xKey->createKey( aImplName.makeStringAndClear() );
+ #if defined UNX
+ aImplName.appendAscii( "/" );
+ aImplName.append( vcl::Clipboard_getImplementationName() );
+ aImplName.appendAscii( "/UNO/SERVICES/" );
+ aImplName.append( vcl::Clipboard_getSupportedServiceNames()[0] );
+ xKey->createKey( aImplName.makeStringAndClear() );
+
+ aImplName.appendAscii( "/" );
+ aImplName.append( vcl::DragSource_getImplementationName() );
+ aImplName.appendAscii( "/UNO/SERVICES/" );
+ aImplName.append( vcl::DragSource_getSupportedServiceNames()[0] );
+ xKey->createKey( aImplName.makeStringAndClear() );
+
+ aImplName.appendAscii( "/" );
+ aImplName.append( vcl::DropTarget_getImplementationName() );
+ aImplName.appendAscii( "/UNO/SERVICES/" );
+ aImplName.append( vcl::DropTarget_getSupportedServiceNames()[0] );
+ xKey->createKey( aImplName.makeStringAndClear() );
+ #endif
+
return sal_True;
}
catch( ::com::sun::star::registry::InvalidRegistryException& )
@@ -143,6 +175,22 @@ extern "C" {
xMgr, vcl::FontIdentificator_getImplementationName(), vcl::FontIdentificator_createInstance,
vcl::FontIdentificator_getSupportedServiceNames() );
}
+ else if( vcl::Clipboard_getImplementationName().equalsAscii( pImplementationName ) )
+ {
+ xFactory = vcl::Clipboard_createFactory( xMgr );
+ }
+ else if( vcl::DragSource_getImplementationName().equalsAscii( pImplementationName ) )
+ {
+ xFactory = ::cppu::createSingleFactory(
+ xMgr, vcl::DragSource_getImplementationName(), vcl::DragSource_createInstance,
+ vcl::DragSource_getSupportedServiceNames() );
+ }
+ else if( vcl::DropTarget_getImplementationName().equalsAscii( pImplementationName ) )
+ {
+ xFactory = ::cppu::createSingleFactory(
+ xMgr, vcl::DropTarget_getImplementationName(), vcl::DropTarget_createInstance,
+ vcl::DropTarget_getSupportedServiceNames() );
+ }
if( xFactory.is() )
{
xFactory->acquire();
diff --git a/vcl/source/components/makefile.mk b/vcl/source/components/makefile.mk
index 9158d33bb888..8cc836fe5424 100644
--- a/vcl/source/components/makefile.mk
+++ b/vcl/source/components/makefile.mk
@@ -44,6 +44,7 @@ ENABLE_EXCEPTIONS=TRUE
# --- Files --------------------------------------------------------
SLOFILES= $(SLO)$/display.obj \
+ $(SLO)$/dtranscomp.obj \
$(SLO)$/fontident.obj \
$(SLO)$/factory.obj
diff --git a/vcl/source/control/button.cxx b/vcl/source/control/button.cxx
index 2e2342fc6fc8..e7a4aadb8694 100644
--- a/vcl/source/control/button.cxx
+++ b/vcl/source/control/button.cxx
@@ -420,10 +420,9 @@ void Button::ImplDrawAlignedImage( OutputDevice* pDev, Point& rPos,
Image *pImage = &(mpButtonData->maImage);
BitmapEx *pBitmapEx = mpButtonData->mpBitmapEx;
- Color aBackCol;
- if( !!(mpButtonData->maImageHC) && ImplGetCurrentBackgroundColor( aBackCol ) )
+ if( !!(mpButtonData->maImageHC) )
{
- if( aBackCol.IsDark() )
+ if( GetSettings().GetStyleSettings().GetHighContrastMode() )
{
pImage = &(mpButtonData->maImageHC);
pBitmapEx = mpButtonData->mpBitmapExHC;
@@ -2375,14 +2374,10 @@ if ( bNativeOK == FALSE )
// check for HC mode
Image *pImage = &maImage;
- Color aBackCol;
- if( !!maImageHC && ImplGetCurrentBackgroundColor( aBackCol ) )
+ if( !!maImageHC )
{
- if( aBackCol.IsDark() )
+ if( rStyleSettings.GetHighContrastMode() )
pImage = &maImageHC;
- // #99902 no col transform required
- //if( aBackCol.IsBright() )
- // nStyle |= IMAGE_DRAW_COLORTRANSFORM;
}
Point aImagePos( aImageRect.TopLeft() );
diff --git a/vcl/source/control/combobox.cxx b/vcl/source/control/combobox.cxx
index 49c7e5457da7..f83e46e38302 100644
--- a/vcl/source/control/combobox.cxx
+++ b/vcl/source/control/combobox.cxx
@@ -287,6 +287,7 @@ BOOL ComboBox::IsAutocompleteEnabled() const
IMPL_LINK( ComboBox, ImplClickBtnHdl, void*, EMPTYARG )
{
+ ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
mpSubEdit->GrabFocus();
if ( !mpImplLB->GetEntryList()->GetMRUCount() )
ImplUpdateFloatSelection();
@@ -523,6 +524,7 @@ void ComboBox::ToggleDropDown()
ImplUpdateFloatSelection();
else
mpImplLB->SelectEntry( 0 , TRUE );
+ ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
mpBtn->SetPressed( TRUE );
SetSelection( Selection( 0, SELECTION_MAX ) );
mpFloatWin->StartFloat( TRUE );
@@ -800,14 +802,8 @@ void ComboBox::DataChanged( const DataChangedEvent& rDCEvt )
long ComboBox::PreNotify( NotifyEvent& rNEvt )
{
- long nDone = 0;
-
- if( ( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN ) && ( rNEvt.GetWindow() == mpImplLB->GetMainWindow() ) )
- {
- mpSubEdit->GrabFocus();
- }
- return nDone ? nDone : Edit::PreNotify( rNEvt );
+ return Edit::PreNotify( rNEvt );
}
// -----------------------------------------------------------------------
@@ -830,6 +826,7 @@ long ComboBox::Notify( NotifyEvent& rNEvt )
ImplUpdateFloatSelection();
if( ( nKeyCode == KEY_DOWN ) && mpFloatWin && !mpFloatWin->IsInPopupMode() && aKeyEvt.GetKeyCode().IsMod2() )
{
+ ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
mpBtn->SetPressed( TRUE );
if ( mpImplLB->GetEntryList()->GetMRUCount() )
mpImplLB->SelectEntry( 0 , TRUE );
@@ -886,6 +883,10 @@ long ComboBox::Notify( NotifyEvent& rNEvt )
nDone = 0; // don't eat this event, let the default handling happen (i.e. scroll the context)
}
}
+ else if( ( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN ) && ( rNEvt.GetWindow() == mpImplLB->GetMainWindow() ) )
+ {
+ mpSubEdit->GrabFocus();
+ }
return nDone ? nDone : Edit::Notify( rNEvt );
}
diff --git a/vcl/source/control/field.cxx b/vcl/source/control/field.cxx
index 1bc6af51f369..3cb6e45f0400 100644
--- a/vcl/source/control/field.cxx
+++ b/vcl/source/control/field.cxx
@@ -503,6 +503,9 @@ void NumericFormatter::ImplLoadRes( const ResId& rResId )
mnFieldValue = mnMin;
mnLastValue = mnFieldValue;
}
+
+ if ( NUMERICFORMATTER_NOTHOUSANDSEP & nMask )
+ SetUseThousandSep( !(BOOL)pMgr->ReadShort() );
}
}
diff --git a/vcl/source/control/fixed.cxx b/vcl/source/control/fixed.cxx
index 530e928532e1..ecb066d107ce 100644
--- a/vcl/source/control/fixed.cxx
+++ b/vcl/source/control/fixed.cxx
@@ -804,13 +804,10 @@ void FixedBitmap::ImplDraw( OutputDevice* pDev, ULONG /* nDrawFlags */,
USHORT nStyle = 0;
Bitmap* pBitmap = &maBitmap;
Color aCol;
- if( !!maBitmapHC && ImplGetCurrentBackgroundColor( aCol ) )
+ if( !!maBitmapHC )
{
- if( aCol.IsDark() )
+ if( GetSettings().GetStyleSettings().GetHighContrastMode() )
pBitmap = &maBitmapHC;
- // #99902 no col transform required
- //if( aCol.IsBright() )
- // nStyle |= IMAGE_DRAW_COLORTRANSFORM;
}
if( nStyle & IMAGE_DRAW_COLORTRANSFORM )
@@ -1058,13 +1055,10 @@ void FixedImage::ImplDraw( OutputDevice* pDev, ULONG nDrawFlags,
Image *pImage = &maImage;
Color aCol;
- if( !!maImageHC && ImplGetCurrentBackgroundColor( aCol ) )
+ if( !!maImageHC )
{
- if( aCol.IsDark() )
+ if( GetSettings().GetStyleSettings().GetHighContrastMode() )
pImage = &maImageHC;
- // #99902 no col transform required
- //if( aCol.IsBright() )
- // nStyle |= IMAGE_DRAW_COLORTRANSFORM;
}
// Haben wir ueberhaupt ein Image
diff --git a/vcl/source/control/ilstbox.cxx b/vcl/source/control/ilstbox.cxx
index a25ddbb68e8b..c0a28c8b03fd 100644
--- a/vcl/source/control/ilstbox.cxx
+++ b/vcl/source/control/ilstbox.cxx
@@ -2899,23 +2899,8 @@ void ImplWin::DrawEntry( BOOL bDrawImage, BOOL bDrawText, BOOL bDrawTextAtImageP
if( !!maImageHC )
{
- // determine backgroundcolor as done in Paint()
- Color aBackCol;
- if( IsEnabled() )
- {
- if( HasFocus() )
- aBackCol = GetSettings().GetStyleSettings().GetHighlightColor();
- else
- aBackCol = GetBackground().GetColor();
- }
- else // Disabled
- aBackCol = GetBackground().GetColor();
-
- if( aBackCol.IsDark() )
+ if( GetSettings().GetStyleSettings().GetHighContrastMode() )
pImage = &maImageHC;
- // #99902 no col transform required
- //if( aBackCol.IsBright() )
- // nStyle |= IMAGE_DRAW_COLORTRANSFORM;
}
if ( !IsZoom() )
diff --git a/vcl/source/control/imgctrl.cxx b/vcl/source/control/imgctrl.cxx
index 6d4777013a73..73b5154d32ac 100644
--- a/vcl/source/control/imgctrl.cxx
+++ b/vcl/source/control/imgctrl.cxx
@@ -93,14 +93,10 @@ void ImageControl::UserDraw( const UserDrawEvent& rUDEvt )
{
USHORT nStyle = 0;
BitmapEx* pBitmap = &maBmp;
- Color aCol;
- if( !!maBmpHC && ImplGetCurrentBackgroundColor( aCol ) )
+ if( !!maBmpHC )
{
- if( aCol.IsDark() )
+ if( GetSettings().GetStyleSettings().GetHighContrastMode() )
pBitmap = &maBmpHC;
- // #99902 no col transform required
- //if( aCol.IsBright() )
- // nStyle |= IMAGE_DRAW_COLORTRANSFORM;
}
if ( !*pBitmap )
diff --git a/vcl/source/control/lstbox.cxx b/vcl/source/control/lstbox.cxx
index a5e9ff1cc7d0..a4d3cbc22544 100644
--- a/vcl/source/control/lstbox.cxx
+++ b/vcl/source/control/lstbox.cxx
@@ -303,6 +303,7 @@ IMPL_LINK( ListBox, ImplClickBtnHdl, void*, EMPTYARG )
{
if( !mpFloatWin->IsInPopupMode() )
{
+ ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
mpImplWin->GrabFocus();
mpBtn->SetPressed( TRUE );
mpFloatWin->StartFloat( TRUE );
@@ -363,6 +364,7 @@ void ListBox::ToggleDropDown()
mpFloatWin->EndPopupMode();
else
{
+ ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
mpImplWin->GrabFocus();
mpBtn->SetPressed( TRUE );
mpFloatWin->StartFloat( TRUE );
@@ -919,6 +921,7 @@ long ListBox::PreNotify( NotifyEvent& rNEvt )
if( mpFloatWin && !mpFloatWin->IsInPopupMode() &&
aKeyEvt.GetKeyCode().IsMod2() )
{
+ ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
mpBtn->SetPressed( TRUE );
mpFloatWin->StartFloat( FALSE );
ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN );
diff --git a/vcl/source/fontsubset/cff.cxx b/vcl/source/fontsubset/cff.cxx
index 7af7e7e9c9e0..e5d83dc0733a 100644
--- a/vcl/source/fontsubset/cff.cxx
+++ b/vcl/source/fontsubset/cff.cxx
@@ -42,8 +42,10 @@ typedef long long S64;
typedef sal_Int32 GlyphWidth;
+typedef float RealType;
+typedef RealType ValType;
#include <vector>
-typedef std::vector<int> IntVector;
+typedef std::vector<ValType> ValVector;
// ====================================================================
@@ -310,8 +312,8 @@ struct CffGlobal
int mnFontDictBase;
int mnFDAryCount;
- IntVector maFontBBox;
- //FloatVector maFontMatrix;
+ ValVector maFontBBox;
+ ValVector maFontMatrix;
int mnFontNameSID;
int mnFullNameSID;
@@ -336,16 +338,16 @@ struct CffLocal
// ATM hinting related values
int mnStemStdHW;
int mnStemStdVW;
- IntVector maStemSnapH;
- IntVector maStemSnapV;
- IntVector maBlueValues;
- IntVector maOtherBlues;
- IntVector maFamilyBlues;
- IntVector maFamilyOtherBlues;
- double mfBlueScale;
- double mfBlueShift;
- double mfBlueFuzz;
- double mfExpFactor;
+ ValVector maStemSnapH;
+ ValVector maStemSnapV;
+ ValVector maBlueValues;
+ ValVector maOtherBlues;
+ ValVector maFamilyBlues;
+ ValVector maFamilyOtherBlues;
+ RealType mfBlueScale;
+ RealType mfBlueShift;
+ RealType mfBlueFuzz;
+ RealType mfExpFactor;
int mnLangGroup;
bool mbForceBold;
};
@@ -422,7 +424,7 @@ private:
CffLocal* mpCffLocal;
void readDictOp( void);
- double readRealVal( void);
+ RealType readRealVal( void);
const char* getString( int nStringID);
int getFDSelect( int nGlyphIndex) const;
int getGlyphSID( int nGlyphIndex) const;
@@ -431,7 +433,7 @@ private:
void readTypeOp( void);
void read2push( void);
void pop2write( void);
- void writeType1Val( int/*TODO: double*/ nVal);
+ void writeType1Val( ValType);
void writeTypeOp( int nTypeOp);
void writeTypeEsc( int nTypeOp);
void writeCurveTo( int nStackPos, int nIX1, int nIY1, int nIX2, int nIY2, int nIX3, int nIY3);
@@ -441,10 +443,13 @@ private:
public: // TODO: is public really needed?
// accessing the value stack
// TODO: add more checks
- void push( int nVal) { mnValStack[ mnStackIdx++] = nVal;}
- int pop( void) { return ((mnStackIdx>0) ? mnValStack[ --mnStackIdx] : 0);}
- int peek( void) { return ((mnStackIdx>0) ? mnValStack[ mnStackIdx-1] : 0);}
- int get( int nIndex) { return mnValStack[ nIndex];}
+ void push( ValType nVal) { mnValStack[ mnStackIdx++] = nVal;}
+ ValType popVal( void) { return ((mnStackIdx>0) ? mnValStack[ --mnStackIdx] : 0);}
+ ValType peekVal( void) const { return ((mnStackIdx>0) ? mnValStack[ mnStackIdx-1] : 0);}
+ ValType getVal( int nIndex) const { return mnValStack[ nIndex];}
+ int popInt( void);
+ int peekInt( void) const;
+ int getInt( int nIndex) const;
int size( void) const { return mnStackIdx;}
bool empty( void) const { return !mnStackIdx;}
void clear( void) { mnStackIdx = 0;}
@@ -453,7 +458,7 @@ public: // TODO: is public really needed?
void addHints( bool bVerticalHints);
int getHorzHintCount( void) const { return (mnHorzHintSize/2);}
int getVertHintCount( void) const { return (mnHintSize-mnHorzHintSize)/2;}
- void getHintPair( int nIndex, int* nMin, int* nEnd) const;
+ void getHintPair( int nIndex, ValType* nMin, ValType* nEnd) const;
// accessing other charstring specifics
bool hasCharWidth( void) const { return (mnCharWidth != -1);}
@@ -465,12 +470,12 @@ public: // TODO: is public really needed?
private:
// typeop exceution context
int mnStackIdx;
- int mnValStack[ NMAXSTACK];
- int mnTransVals[ NMAXTRANS];
+ ValType mnValStack[ NMAXSTACK];
+ ValType mnTransVals[ NMAXTRANS];
int mnHintSize;
int mnHorzHintSize;
- int mnHintStack[ NMAXHINTS];
+ ValType mnHintStack[ NMAXHINTS];
int mnCharWidth;
};
@@ -499,6 +504,36 @@ CffSubsetterContext::~CffSubsetterContext( void)
// --------------------------------------------------------------------
+inline int CffSubsetterContext::popInt( void)
+{
+ const ValType aVal = popVal();
+ const int nInt = static_cast<int>(aVal);
+ assert( nInt == aVal);
+ return nInt;
+}
+
+// --------------------------------------------------------------------
+
+inline int CffSubsetterContext::peekInt( void) const
+{
+ const ValType aVal = peekVal();
+ const int nInt = static_cast<int>(aVal);
+ assert( nInt == aVal);
+ return nInt;
+}
+
+// --------------------------------------------------------------------
+
+inline int CffSubsetterContext::getInt( int nIndex) const
+{
+ const ValType aVal = getVal( nIndex);
+ const int nInt = static_cast<int>(aVal);
+ assert( nInt == aVal);
+ return nInt;
+}
+
+// --------------------------------------------------------------------
+
inline void CffSubsetterContext::updateWidth( bool bUseFirstVal)
{
#if 1 // TODO: is this still needed?
@@ -507,7 +542,7 @@ inline void CffSubsetterContext::updateWidth( bool bUseFirstVal)
return;
#endif
if( bUseFirstVal) {
- mnCharWidth = mpCffLocal->mnNominalWidth + mnValStack[0];
+ mnCharWidth = static_cast<int>(mpCffLocal->mnNominalWidth + mnValStack[0]);
// remove bottom stack entry
--mnStackIdx;
for( int i = 0; i < mnStackIdx; ++i)
@@ -535,16 +570,16 @@ void CffSubsetterContext::addHints( bool bVerticalHints)
assert( (mnHintSize + mnStackIdx) <= 2*NMAXHINTS);
#ifdef IGNORE_HINTS
- mnHorzHintSize += mnStackIdx;
+ mnHintSize += mnStackIdx;
#else
- int nHintOfs = 0;
+ ValType nHintOfs = 0;
for( int i = 0; i < mnStackIdx; ++i) {
- nHintOfs += mnValStack[ i];
+ nHintOfs += mnValStack[ i ];
mnHintStack[ mnHintSize++] = nHintOfs;
}
+#endif // IGNORE_HINTS
if( !bVerticalHints)
mnHorzHintSize = mnHintSize;
-#endif // IGNORE_HINTS
// clear all values from the stack
mnStackIdx = 0;
@@ -552,12 +587,12 @@ void CffSubsetterContext::addHints( bool bVerticalHints)
// --------------------------------------------------------------------
-void CffSubsetterContext::getHintPair( int nIndex, int* pMin, int* pEnd) const
+void CffSubsetterContext::getHintPair( int nIndex, ValType* pMin, ValType* pEnd) const
{
nIndex *= 2;
assert( nIndex < mnHintSize);
assert( nIndex >= 0);
- const int* pHint = &mnHintStack[ nIndex];
+ const ValType* pHint = &mnHintStack[ nIndex ];
*pMin = pHint[0];
*pEnd = pHint[1];
}
@@ -596,7 +631,8 @@ void CffSubsetterContext::readCharString( const U8* pTypeOps, int nTypeLen)
void CffSubsetterContext::readDictOp( void)
{
- int nVal = 0;
+ ValType nVal = 0;
+ int nInt = 0;
const U8 c = *mpReadPtr;
if( c <= 21 ) {
int nOpId = *(mpReadPtr++);
@@ -613,41 +649,45 @@ void CffSubsetterContext::readDictOp( void)
switch( *pCmdName) {
default: fprintf( stderr, "unsupported DictOp.type=\'%c\'\n", *pCmdName); break;
case 'b': // bool
- nVal = pop();
+ nInt = popInt();
switch( nOpId) {
- case 915: mpCffLocal->mbForceBold = nVal; break; // "ForceBold"
+ case 915: mpCffLocal->mbForceBold = nInt; break; // "ForceBold"
default: break; // TODO: handle more boolean dictops?
}
break;
case 'n': // dict-op number
- nVal = pop();
+ nVal = popVal();
+ nInt = static_cast<int>(nVal);
switch( nOpId) {
- case 10: mpCffLocal->mnStemStdHW = nVal; break; // "StdHW"
- case 11: mpCffLocal->mnStemStdVW = nVal; break; // "StdVW"
- case 15: mnCharsetBase = nVal; break; // "charset"
- case 16: mnEncodingBase = nVal; break; // "nEncoding"
- case 17: mnCharStrBase = nVal; break; // "nCharStrings"
- case 19: mpCffLocal->mnLocalSubrOffs = nVal; break;// "nSubrs"
- case 20: setDefaultWidth( nVal); break; // "defaultWidthX"
- case 21: setNominalWidth( nVal); break; // "nominalWidthX"
+ case 10: mpCffLocal->mnStemStdHW = nInt; break; // "StdHW"
+ case 11: mpCffLocal->mnStemStdVW = nInt; break; // "StdVW"
+ case 15: mnCharsetBase = nInt; break; // "charset"
+ case 16: mnEncodingBase = nInt; break; // "nEncoding"
+ case 17: mnCharStrBase = nInt; break; // "nCharStrings"
+ case 19: mpCffLocal->mnLocalSubrOffs = nInt; break;// "nSubrs"
+ case 20: setDefaultWidth( nInt ); break; // "defaultWidthX"
+ case 21: setNominalWidth( nInt ); break; // "nominalWidthX"
case 909: mpCffLocal->mfBlueScale = nVal; break; // "BlueScale"
case 910: mpCffLocal->mfBlueShift = nVal; break; // "BlueShift"
case 911: mpCffLocal->mfBlueFuzz = nVal; break; // "BlueFuzz"
case 912: mpCffLocal->mfExpFactor = nVal; break; // "ExpansionFactor"
- case 917: mpCffLocal->mnLangGroup = nVal; break; // "LanguageGroup"
- case 936: mnFontDictBase = nVal; break; // "nFDArray"
- case 937: mnFDSelectBase = nVal; break; // "nFDSelect"
+ case 917: mpCffLocal->mnLangGroup = nInt; break; // "LanguageGroup"
+ case 936: mnFontDictBase = nInt; break; // "nFDArray"
+ case 937: mnFDSelectBase = nInt; break; // "nFDSelect"
default: break; // TODO: handle more numeric dictops?
}
break;
case 'a': { // array
+ switch( nOpId) {
+ case 5: maFontBBox.clear(); break; // "FontBBox"
+ case 907: maFontMatrix.clear(); break; // "FontMatrix"
+ default: break; // TODO: reset other arrays?
+ }
for( int i = 0; i < size(); ++i ) {
- nVal = get(i);
+ nVal = getVal(i);
switch( nOpId) {
case 5: maFontBBox.push_back( nVal); break; // "FontBBox"
-#if 0 // TODO
case 907: maFontMatrix.push_back( nVal); break; // "FontMatrix"
-#endif
default: break; // TODO: handle more array dictops?
}
}
@@ -656,7 +696,7 @@ void CffSubsetterContext::readDictOp( void)
case 'd': { // delta array
nVal = 0;
for( int i = 0; i < size(); ++i ) {
- nVal += get(i);
+ nVal += getVal(i);
switch( nOpId) {
case 6: mpCffLocal->maBlueValues.push_back( nVal); break; // "BlueValues"
case 7: mpCffLocal->maOtherBlues.push_back( nVal); break; // "OtherBlues"
@@ -670,39 +710,39 @@ void CffSubsetterContext::readDictOp( void)
clear();
} break;
case 's': // stringid (SID)
- nVal = pop();
- switch( nOpId) {
- case 2: mnFullNameSID = nVal; break; // "FullName"
- case 3: mnFamilyNameSID = nVal; break; // "FamilyName"
- case 938: mnFontNameSID = nVal; break; // "FontName"
+ nInt = popInt();
+ switch( nOpId ) {
+ case 2: mnFullNameSID = nInt; break; // "FullName"
+ case 3: mnFamilyNameSID = nInt; break; // "FamilyName"
+ case 938: mnFontNameSID = nInt; break; // "FontName"
default: break; // TODO: handle more string dictops?
}
break;
case 'P': // private dict
- mpCffLocal->mnPrivDictBase = pop();
- mpCffLocal->mnPrivDictSize = pop();
+ mpCffLocal->mnPrivDictBase = popInt();
+ mpCffLocal->mnPrivDictSize = popInt();
break;
case 'r': { // ROS operands
- int nSid1 = pop();
- int nSid2 = pop();
+ int nSid1 = popInt();
+ int nSid2 = popInt();
(void)nSid1; // TODO: use
(void)nSid2; // TODO: use
- nVal = pop();
+ nVal = popVal();
mbCIDFont = true;
} break;
case 't': // CharstringType
- nVal = pop();
- setCharStringType( nVal);
+ nInt = popInt();
+ setCharStringType( nInt );
break;
}
return;
}
- if( (c >= 32) || (c == 28)) {
+ if( (c >= 32) || (c == 28) ) {
// --mpReadPtr;
read2push();
- } else if( c == 29) { // longint
+ } else if( c == 29 ) { // longint
++mpReadPtr; // skip 29
int nS32 = mpReadPtr[0] << 24;
nS32 += mpReadPtr[1] << 16;
@@ -711,13 +751,13 @@ void CffSubsetterContext::readDictOp( void)
if( (sizeof(nS32) != 4) && (nS32 & (1<<31)))
nS32 |= (~0U) << 31; // assuming 2s complement
mpReadPtr += 4;
- nVal = nS32;
- push( nVal);
+ nVal = static_cast<ValType>(nS32);
+ push( nVal );
} else if( c == 30) { // real number
++mpReadPtr; // skip 30
- const double fReal = readRealVal();
+ const RealType fReal = readRealVal();
// push value onto stack
- nVal = static_cast<int>(fReal+0.5); //TODO!!! allow float on operand stack!
+ nVal = fReal;
push( nVal);
}
}
@@ -759,12 +799,12 @@ void CffSubsetterContext::readTypeOp( void)
case 'C': nMinStack = 6; nMaxStack = 999; break;
case 'E': nMinStack = 1; nMaxStack = 999; break;
case 'G': nMinStack = 1; nMaxStack = 999; // global subr
- nVal = peek();
+ nVal = peekInt();
// TODO global subr
break;
case 'L': // local subr
nMinStack = 1; nMaxStack = 999;
- nVal = peek();
+ nVal = peekInt();
// TODO local subr
break;
case 'I': // operands for "index"
@@ -830,57 +870,70 @@ void CffSubsetterContext::readTypeOp( void)
// --------------------------------------------------------------------
-void CffSubsetterContext::read2push( void)
+void CffSubsetterContext::read2push()
{
- int nVal = 0;
+ ValType aVal = 0;
const U8*& p = mpReadPtr;
const U8 c = *p;
- if( c == 28) {
+ if( c == 28 ) {
short nS16 = (p[1] << 8) + p[2];
if( (sizeof(nS16) != 2) && (nS16 & (1<<15)))
nS16 |= (~0U) << 15; // assuming 2s complement
- nVal = nS16;
+ aVal = nS16;
p += 3;
- } else if( c <= 246) { // -107..+107
- nVal = p[0] - 139;
+ } else if( c <= 246 ) { // -107..+107
+ aVal = static_cast<ValType>(p[0] - 139);
p += 1;
- } else if( c <= 250) { // +108..+1131
- nVal = ((p[0] << 8) + p[1]) - 63124;
+ } else if( c <= 250 ) { // +108..+1131
+ aVal = static_cast<ValType>(((p[0] << 8) + p[1]) - 63124);
p += 2;
- } else if( c <= 254) { // -108..-1131
- nVal = 64148 - ((p[0] << 8) + p[1]);
+ } else if( c <= 254 ) { // -108..-1131
+ aVal = static_cast<ValType>(64148 - ((p[0] << 8) + p[1]));
p += 2;
} else /*if( c == 255)*/ { // Fixed16.16
- nVal = (p[1] << 8) + p[2];
- // TODO: read non-integer part
+ int nS32 = (p[1] << 24) + (p[2] << 16) + (p[3] << 8) + p[4];
+ if( (sizeof(nS32) != 2) && (nS32 & (1<<31)))
+ nS32 |= (~0U) << 31; // assuming 2s complement
+ aVal = static_cast<ValType>(nS32 * (1.0 / 0x10000));
p += 5;
}
- push( nVal);
+ push( aVal);
}
// --------------------------------------------------------------------
-void CffSubsetterContext::writeType1Val( int/*TODO: double*/ nVal)
+void CffSubsetterContext::writeType1Val( ValType aVal)
{
U8* pOut = mpWritePtr;
- if( (nVal >= -107) && (nVal <= +107)) {
- *(pOut++) = static_cast<U8>(nVal + 139); // -107..+107
- } else if( (nVal >= -1131) && (nVal <= +1131)) {
- if( nVal >= 0)
- nVal += 63124; // +108..+1131
+
+ int nInt = static_cast<int>(aVal);
+ static const int nOutCharstrType = 1;
+ if( (nInt != aVal) && (nOutCharstrType == 2)) {
+ // numtype==255 means int32 for Type1, but 16.16 for Type2 charstrings!!!
+ *(pOut++) = 255; // Fixed 16.16
+ *(pOut++) = static_cast<U8>(nInt >> 8);
+ *(pOut++) = static_cast<U8>(nInt);
+ nInt = static_cast<int>(aVal * 0x10000) & 0xFFFF;
+ *(pOut++) = static_cast<U8>(nInt >> 8);
+ *(pOut++) = static_cast<U8>(nInt);
+ } else if( (nInt >= -107) && (nInt <= +107)) {
+ *(pOut++) = static_cast<U8>(nInt + 139); // -107..+107
+ } else if( (nInt >= -1131) && (nInt <= +1131)) {
+ if( nInt >= 0)
+ nInt += 63124; // +108..+1131
else
- nVal = 64148 - nVal; // -108..-1131
- *(pOut++) = static_cast<U8>(nVal >> 8);
- *(pOut++) = static_cast<U8>(nVal);
- } else {
+ nInt = 64148 - nInt; // -108..-1131
+ *(pOut++) = static_cast<U8>(nInt >> 8);
+ *(pOut++) = static_cast<U8>(nInt);
+ } else if( nOutCharstrType == 1) {
// numtype==255 means int32 for Type1, but 16.16 for Type2 charstrings!!!
*(pOut++) = 255;
- *(pOut++) = static_cast<U8>(nVal >> 24);
- *(pOut++) = static_cast<U8>(nVal >> 16);
- *(pOut++) = static_cast<U8>(nVal >> 8);
- *(pOut++) = static_cast<U8>(nVal);
+ *(pOut++) = static_cast<U8>(nInt >> 24);
+ *(pOut++) = static_cast<U8>(nInt >> 16);
+ *(pOut++) = static_cast<U8>(nInt >> 8);
+ *(pOut++) = static_cast<U8>(nInt);
}
mpWritePtr = pOut;
@@ -890,8 +943,8 @@ void CffSubsetterContext::writeType1Val( int/*TODO: double*/ nVal)
inline void CffSubsetterContext::pop2write( void)
{
- int nVal = pop();
- writeType1Val( nVal);
+ const ValType aVal = popVal();
+ writeType1Val( aVal);
}
// --------------------------------------------------------------------
@@ -915,8 +968,8 @@ void CffSubsetterContext::pop2MultiWrite( int nArgsPerTypo, int nTypeOp, int nTy
{
for( int i = 0; i < mnStackIdx;) {
for( int j = 0; j < nArgsPerTypo; ++j) {
- int nVal = mnValStack[i+j];
- writeType1Val( nVal);
+ const ValType aVal = mnValStack[i+j];
+ writeType1Val( aVal);
}
i += nArgsPerTypo;
writeTypeOp( nTypeOp);
@@ -931,8 +984,8 @@ void CffSubsetterContext::popAll2Write( int nTypeOp)
{
// pop in reverse order, then write
for( int i = 0; i < mnStackIdx; ++i) {
- int nVal = mnValStack[i];
- writeType1Val( nVal);
+ const ValType aVal = mnValStack[i];
+ writeType1Val( aVal);
}
clear();
writeTypeOp( nTypeOp);
@@ -944,23 +997,23 @@ void CffSubsetterContext::writeCurveTo( int nStackPos,
int nIX1, int nIY1, int nIX2, int nIY2, int nIX3, int nIY3)
{
// get the values from the stack
- const int nDX1 = nIX1 ? mnValStack[ nStackPos+nIX1] : 0;
- const int nDY1 = nIY1 ? mnValStack[ nStackPos+nIY1] : 0;
- const int nDX2 = nIX2 ? mnValStack[ nStackPos+nIX2] : 0;
- const int nDY2 = nIY2 ? mnValStack[ nStackPos+nIY2] : 0;
- const int nDX3 = nIX3 ? mnValStack[ nStackPos+nIX3] : 0;
- const int nDY3 = nIY3 ? mnValStack[ nStackPos+nIY3] : 0;
+ const ValType nDX1 = nIX1 ? mnValStack[ nStackPos+nIX1 ] : 0;
+ const ValType nDY1 = nIY1 ? mnValStack[ nStackPos+nIY1 ] : 0;
+ const ValType nDX2 = nIX2 ? mnValStack[ nStackPos+nIX2 ] : 0;
+ const ValType nDY2 = nIY2 ? mnValStack[ nStackPos+nIY2 ] : 0;
+ const ValType nDX3 = nIX3 ? mnValStack[ nStackPos+nIX3 ] : 0;
+ const ValType nDY3 = nIY3 ? mnValStack[ nStackPos+nIY3 ] : 0;
// emit the curveto operator and operands
// TODO: determine the most efficient curveto operator
// TODO: depending on type1op or type2op target
- writeType1Val( nDX1);
- writeType1Val( nDY1);
- writeType1Val( nDX2);
- writeType1Val( nDY2);
- writeType1Val( nDX3);
- writeType1Val( nDY3);
- writeTypeOp( TYPE1OP::RCURVETO);
+ writeType1Val( nDX1 );
+ writeType1Val( nDY1 );
+ writeType1Val( nDX2 );
+ writeType1Val( nDY2 );
+ writeType1Val( nDX3 );
+ writeType1Val( nDY3 );
+ writeTypeOp( TYPE1OP::RCURVETO );
}
// --------------------------------------------------------------------
@@ -969,7 +1022,7 @@ void CffSubsetterContext::convertOneTypeOp( void)
{
const int nType2Op = *(mpReadPtr++);
- int i, nVal; // prevent WAE for declarations inside switch cases
+ int i, nInt; // prevent WAE for declarations inside switch cases
// convert each T2op
switch( nType2Op) {
case TYPE2OP::T2ESC:
@@ -977,12 +1030,12 @@ void CffSubsetterContext::convertOneTypeOp( void)
break;
case TYPE2OP::HSTEM:
case TYPE2OP::VSTEM:
- addHints( nType2Op == TYPE2OP::VSTEM);
+ addHints( nType2Op == TYPE2OP::VSTEM );
#ifndef IGNORE_HINTS
- for( i = 0; i < mnHintSize; i+=2) {
+ for( i = 0; i < mnHintSize; i+=2 ) {
writeType1Val( mnHintStack[i]);
writeType1Val( mnHintStack[i+1] - mnHintStack[i]);
- writeTypeOp( nType2Op);
+ writeTypeOp( nType2Op );
}
#endif // IGNORE_HINTS
break;
@@ -1063,9 +1116,9 @@ void CffSubsetterContext::convertOneTypeOp( void)
case TYPE2OP::CALLSUBR:
case TYPE2OP::CALLGSUBR:
{
- nVal = pop();
+ nInt = popInt();
const bool bGlobal = (nType2Op == TYPE2OP::CALLGSUBR);
- callType2Subr( bGlobal, nVal);
+ callType2Subr( bGlobal, nInt);
}
break;
case TYPE2OP::RETURN:
@@ -1131,19 +1184,19 @@ void CffSubsetterContext::convertOneTypeOp( void)
{
bool bVert = (nType2Op == TYPE2OP::VHCURVETO);
i = 0;
- nVal = 0;
- if( mnStackIdx & 1)
- nVal = mnValStack[ --mnStackIdx];
+ nInt = 0;
+ if( mnStackIdx & 1 )
+ nInt = static_cast<int>(mnValStack[ --mnStackIdx ]);
while( (i += 4) <= mnStackIdx) {
// TODO: use writeCurveTo()
- if( bVert) writeType1Val( 0);
- writeType1Val( mnValStack[i-4]);
- if( !bVert) writeType1Val( 0);
- writeType1Val( mnValStack[i-3]);
- writeType1Val( mnValStack[i-2]);
- if( !bVert) writeType1Val( (i==mnStackIdx) ? nVal : 0);
- writeType1Val( mnValStack[i-1]);
- if( bVert) writeType1Val( (i==mnStackIdx) ? nVal : 0 );
+ if( bVert ) writeType1Val( 0 );
+ writeType1Val( mnValStack[i-4] );
+ if( !bVert ) writeType1Val( 0);
+ writeType1Val( mnValStack[i-3] );
+ writeType1Val( mnValStack[i-2] );
+ if( !bVert ) writeType1Val( static_cast<ValType>((i==mnStackIdx) ? nInt : 0) );
+ writeType1Val( mnValStack[i-1] );
+ if( bVert ) writeType1Val( static_cast<ValType>((i==mnStackIdx) ? nInt : 0) );
bVert = !bVert;
writeTypeOp( TYPE2OP::RCURVETO);
}
@@ -1195,83 +1248,83 @@ void CffSubsetterContext::convertOneTypeOp( void)
void CffSubsetterContext::convertOneTypeEsc( void)
{
const int nType2Esc = *(mpReadPtr++);
- int* pTop = &mnValStack[ mnStackIdx-1];
+ ValType* pTop = &mnValStack[ mnStackIdx-1];
// convert each T2op
switch( nType2Esc) {
case TYPE2OP::AND:
- assert( mnStackIdx >= 2);
- pTop[0] &= pTop[-1];
+ assert( mnStackIdx >= 2 );
+ pTop[0] = static_cast<ValType>(static_cast<int>(pTop[0]) & static_cast<int>(pTop[-1]));
--mnStackIdx;
break;
case TYPE2OP::OR:
- assert( mnStackIdx >= 2);
- pTop[0] |= pTop[-1];
+ assert( mnStackIdx >= 2 );
+ pTop[0] = static_cast<ValType>(static_cast<int>(pTop[0]) | static_cast<int>(pTop[-1]));
--mnStackIdx;
break;
case TYPE2OP::NOT:
- assert( mnStackIdx >= 1);
- pTop[0] = !pTop[0];
+ assert( mnStackIdx >= 1 );
+ pTop[0] = (pTop[0] == 0);
break;
case TYPE2OP::ABS:
- assert( mnStackIdx >= 1);
+ assert( mnStackIdx >= 1 );
if( pTop[0] >= 0)
break;
// fall through
case TYPE2OP::NEG:
- assert( mnStackIdx >= 1);
+ assert( mnStackIdx >= 1 );
pTop[0] = -pTop[0];
break;
case TYPE2OP::ADD:
- assert( mnStackIdx >= 2);
+ assert( mnStackIdx >= 2 );
pTop[0] += pTop[-1];
--mnStackIdx;
break;
case TYPE2OP::SUB:
- assert( mnStackIdx >= 2);
+ assert( mnStackIdx >= 2 );
pTop[0] -= pTop[-1];
--mnStackIdx;
break;
case TYPE2OP::MUL:
- assert( mnStackIdx >= 2);
+ assert( mnStackIdx >= 2 );
if( pTop[-1])
pTop[0] *= pTop[-1];
--mnStackIdx;
break;
case TYPE2OP::DIV:
- assert( mnStackIdx >= 2);
+ assert( mnStackIdx >= 2 );
if( pTop[-1])
pTop[0] /= pTop[-1];
--mnStackIdx;
break;
case TYPE2OP::EQ:
- assert( mnStackIdx >= 2);
+ assert( mnStackIdx >= 2 );
pTop[0] = (pTop[0] == pTop[-1]);
--mnStackIdx;
break;
case TYPE2OP::DROP:
- assert( mnStackIdx >= 1);
+ assert( mnStackIdx >= 1 );
--mnStackIdx;
break;
case TYPE2OP::PUT: {
- assert( mnStackIdx >= 2);
- const int nIdx = pTop[0];
- assert( nIdx >= 0);
- assert( nIdx < NMAXTRANS);
+ assert( mnStackIdx >= 2 );
+ const int nIdx = static_cast<int>(pTop[0]);
+ assert( nIdx >= 0 );
+ assert( nIdx < NMAXTRANS );
mnTransVals[ nIdx] = pTop[-1];
mnStackIdx -= 2;
break;
}
case TYPE2OP::GET: {
- assert( mnStackIdx >= 1);
- const int nIdx = pTop[0];
- assert( nIdx >= 0);
- assert( nIdx < NMAXTRANS);
- pTop[0] = mnTransVals[ nIdx];
+ assert( mnStackIdx >= 1 );
+ const int nIdx = static_cast<int>(pTop[0]);
+ assert( nIdx >= 0 );
+ assert( nIdx < NMAXTRANS );
+ pTop[0] = mnTransVals[ nIdx ];
break;
}
case TYPE2OP::IFELSE: {
- assert( mnStackIdx >= 4);
- if( pTop[-1] > pTop[0])
+ assert( mnStackIdx >= 4 );
+ if( pTop[-1] > pTop[0] )
pTop[-3] = pTop[-2];
mnStackIdx -= 3;
break;
@@ -1284,69 +1337,69 @@ void CffSubsetterContext::convertOneTypeEsc( void)
// TODO: implement
break;
case TYPE2OP::DUP:
- assert( mnStackIdx >= 1);
+ assert( mnStackIdx >= 1 );
pTop[+1] = pTop[0];
++mnStackIdx;
break;
case TYPE2OP::EXCH: {
- assert( mnStackIdx >= 2);
- const int nVal = pTop[0];
+ assert( mnStackIdx >= 2 );
+ const ValType nVal = pTop[0];
pTop[0] = pTop[-1];
pTop[-1] = nVal;
break;
}
case TYPE2OP::INDEX: {
- assert( mnStackIdx >= 1);
- const int nVal = pTop[0];
- assert( nVal >= 0);
- assert( nVal < mnStackIdx-1);
+ assert( mnStackIdx >= 1 );
+ const int nVal = static_cast<int>(pTop[0]);
+ assert( nVal >= 0 );
+ assert( nVal < mnStackIdx-1 );
pTop[0] = pTop[-1-nVal];
break;
}
case TYPE2OP::ROLL: {
- assert( mnStackIdx >= 1);
- const int nNum = pTop[0];
+ assert( mnStackIdx >= 1 );
+ const int nNum = static_cast<int>(pTop[0]);
assert( nNum >= 0);
- assert( nNum < mnStackIdx-2);
+ assert( nNum < mnStackIdx-2 );
(void)nNum; // TODO: implement
- const int nOfs = pTop[-1];
+ const int nOfs = static_cast<int>(pTop[-1]);
mnStackIdx -= 2;
(void)nOfs;// TODO: implement
break;
}
case TYPE2OP::HFLEX1: {
- assert( mnStackIdx == 9);
- writeCurveTo( mnStackIdx, -9, -8, -7, -6, -5, -6);
- writeCurveTo( mnStackIdx, -4, -6, -3, -2, -1, -8);
+ assert( mnStackIdx == 9 );
+ writeCurveTo( mnStackIdx, -9, -8, -7, -6, -5, -6 );
+ writeCurveTo( mnStackIdx, -4, -6, -3, -2, -1, -8 );
mnStackIdx -= 9;
}
break;
case TYPE2OP::HFLEX: {
- assert( mnStackIdx == 7);
- writeCurveTo( mnStackIdx, -7, 0, -6, -5, -4, -5);
- writeCurveTo( mnStackIdx, -3, -5, -2, 0, -1, 0);
+ assert( mnStackIdx == 7 );
+ writeCurveTo( mnStackIdx, -7, 0, -6, -5, -4, -5 );
+ writeCurveTo( mnStackIdx, -3, -5, -2, 0, -1, 0 );
mnStackIdx -= 7;
}
break;
case TYPE2OP::FLEX: {
- assert( mnStackIdx == 13);
- writeCurveTo( mnStackIdx, -13, -12, -11, -10, -9, -8);
- writeCurveTo( mnStackIdx, -7, -6, -5, -4, -3, -2);
- const int nFlexDepth = mnValStack[ mnStackIdx-1];
+ assert( mnStackIdx == 13 );
+ writeCurveTo( mnStackIdx, -13, -12, -11, -10, -9, -8 );
+ writeCurveTo( mnStackIdx, -7, -6, -5, -4, -3, -2 );
+ const ValType nFlexDepth = mnValStack[ mnStackIdx-1 ];
(void)nFlexDepth; // ignoring nFlexDepth
mnStackIdx -= 13;
}
break;
case TYPE2OP::FLEX1: {
- assert( mnStackIdx == 11);
+ assert( mnStackIdx == 11 );
// write the first part of the flex1-hinted curve
- writeCurveTo( mnStackIdx, -11, -10, -9, -8, -7, -6);
+ writeCurveTo( mnStackIdx, -11, -10, -9, -8, -7, -6 );
// determine if nD6 is horizontal or vertical
const int i = mnStackIdx;
- int nDeltaX = mnValStack[i-11] + mnValStack[i-9] + mnValStack[i-7] + mnValStack[i-5] + mnValStack[i-3];
+ ValType nDeltaX = mnValStack[i-11] + mnValStack[i-9] + mnValStack[i-7] + mnValStack[i-5] + mnValStack[i-3];
if( nDeltaX < 0 ) nDeltaX = -nDeltaX;
- int nDeltaY = mnValStack[i-10] + mnValStack[i-8] + mnValStack[i-6] + mnValStack[i-4] + mnValStack[i-2];
+ ValType nDeltaY = mnValStack[i-10] + mnValStack[i-8] + mnValStack[i-6] + mnValStack[i-4] + mnValStack[i-2];
if( nDeltaY < 0 ) nDeltaY = -nDeltaY;
const bool bVertD6 = (nDeltaY > nDeltaX);
@@ -1473,14 +1526,14 @@ if( mbSawError) {
// --------------------------------------------------------------------
-double CffSubsetterContext::readRealVal()
+RealType CffSubsetterContext::readRealVal()
{
// TODO: more thorough number validity test
bool bComma = false;
int nExpVal = 0;
int nExpSign = 0;
S64 nNumber = 0;
- double fReal = +1.0;
+ RealType fReal = +1.0;
for(;;){
const U8 c = *(mpReadPtr++); // read nibbles
// parse high nibble
@@ -1548,6 +1601,7 @@ double CffSubsetterContext::readRealVal()
// prepare to access an element inside a CFF/CID index table
int CffSubsetterContext::seekIndexData( int nIndexBase, int nDataIndex)
{
+ assert( (nIndexBase > 0) && (mpBasePtr + nIndexBase + 3 <= mpBaseEnd));
if( nDataIndex < 0)
return -1;
mpReadPtr = mpBasePtr + nIndexBase;
@@ -1578,6 +1632,7 @@ int CffSubsetterContext::seekIndexData( int nIndexBase, int nDataIndex)
mpReadEnd = mpReadPtr + (nOfs2 - nOfs1);
assert( nOfs1 >= 0);
assert( nOfs2 >= nOfs1);
+ assert( mpReadPtr <= mpBaseEnd);
assert( mpReadEnd <= mpBaseEnd);
return (nOfs2 - nOfs1);
}
@@ -1587,10 +1642,12 @@ int CffSubsetterContext::seekIndexData( int nIndexBase, int nDataIndex)
// skip over a CFF/CID index table
void CffSubsetterContext::seekIndexEnd( int nIndexBase)
{
+ assert( (nIndexBase > 0) && (mpBasePtr + nIndexBase + 3 <= mpBaseEnd));
mpReadPtr = mpBasePtr + nIndexBase;
const int nDataCount = (mpReadPtr[0]<<8) + mpReadPtr[1];
const int nDataOfsSz = mpReadPtr[2];
mpReadPtr += 3 + nDataOfsSz * nDataCount;
+ assert( mpReadPtr <= mpBaseEnd);
int nEndOfs = 0;
switch( nDataOfsSz) {
default: fprintf( stderr, "\tINVALID nDataOfsSz=%d\n\n", nDataOfsSz); return;
@@ -1602,6 +1659,8 @@ void CffSubsetterContext::seekIndexEnd( int nIndexBase)
mpReadPtr += nDataOfsSz;
mpReadPtr += nEndOfs - 1;
mpReadEnd = mpBaseEnd;
+ assert( nEndOfs >= 0);
+ assert( mpReadEnd <= mpBaseEnd);
}
// ====================================================================
@@ -1944,7 +2003,7 @@ public:
void emitAllCrypted( void);
int tellPos( void) const;
void updateLen( int nTellPos, int nLength);
- void emitIntVector( const char* pLineHead, const char* pLineTail, const IntVector&);
+ void emitValVector( const char* pLineHead, const char* pLineTail, const ValVector&);
private:
FILE* mpFileOut;
bool mbCloseOutfile;
@@ -2095,8 +2154,8 @@ void Type1Emitter::emitAllCrypted( void)
// --------------------------------------------------------------------
-void Type1Emitter::emitIntVector( const char* pLineHead, const char* pLineTail,
- const IntVector& rVector)
+void Type1Emitter::emitValVector( const char* pLineHead, const char* pLineTail,
+ const ValVector& rVector)
{
// ignore empty vectors
if( rVector.empty())
@@ -2105,15 +2164,15 @@ void Type1Emitter::emitIntVector( const char* pLineHead, const char* pLineTail,
// emit the line head
mpPtr += sprintf( mpPtr, pLineHead);
// emit the vector values
- IntVector::value_type nVal = 0;
- for( IntVector::const_iterator it = rVector.begin();;) {
- nVal = *it;
+ ValVector::value_type aVal = 0;
+ for( ValVector::const_iterator it = rVector.begin();;) {
+ aVal = *it;
if( ++it == rVector.end() )
break;
- mpPtr += sprintf( mpPtr, "%d ", nVal);
+ mpPtr += sprintf( mpPtr, "%g ", aVal);
}
// emit the last value
- mpPtr += sprintf( mpPtr, "%d", nVal);
+ mpPtr += sprintf( mpPtr, "%g", aVal);
// emit the line tail
mpPtr += sprintf( mpPtr, pLineTail);
}
@@ -2178,12 +2237,16 @@ bool CffSubsetterContext::emitAsType1( Type1Emitter& rEmitter,
"/PaintType 0 def\n");
pOut += sprintf( pOut, "/FontName /%s def\n", rEmitter.maSubsetName);
pOut += sprintf( pOut, "/UniqueID %d def\n", nUniqueId);
- pOut += sprintf( pOut, "/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def\n");
+ // emit FontMatrix
+ if( maFontMatrix.size() == 6)
+ rEmitter.emitValVector( "/FontMatrix [", "]readonly def\n", maFontMatrix);
+ else // emit default FontMatrix if needed
+ pOut += sprintf( pOut, "/FontMatrix [0.001 0 0 0.001 0 0]readonly def\n");
+ // emit FontBBox
if( maFontBBox.size() == 4)
- pOut += sprintf( pOut, "/FontBBox [%d %d %d %d ]readonly def\n",
- maFontBBox[0], maFontBBox[1], maFontBBox[2], maFontBBox[3]);
- else
- pOut += sprintf( pOut, "/FontBBox [0 0 999 999]readonly def\n");
+ rEmitter.emitValVector( "/FontBBox {", "}readonly def\n", maFontBBox);
+ else // emit default FontBBox if needed
+ pOut += sprintf( pOut, "/FontBBox {0 0 999 999}readonly def\n");
// emit FONTINFO into TOPDICT
pOut += sprintf( pOut,
"/FontInfo 2 dict dup begin\n" // TODO: check fontinfo entry count
@@ -2259,12 +2322,12 @@ bool CffSubsetterContext::emitAsType1( Type1Emitter& rEmitter,
#else
// emit blue hint related privdict entries
if( !mpCffLocal->maBlueValues.empty())
- rEmitter.emitIntVector( "/BlueValues [", "]ND\n", mpCffLocal->maBlueValues);
+ rEmitter.emitValVector( "/BlueValues [", "]ND\n", mpCffLocal->maBlueValues);
else
pOut += sprintf( pOut, "/BlueValues []ND\n"); // default to empty BlueValues
- rEmitter.emitIntVector( "/OtherBlues [", "]ND\n", mpCffLocal->maOtherBlues);
- rEmitter.emitIntVector( "/FamilyBlues [", "]ND\n", mpCffLocal->maFamilyBlues);
- rEmitter.emitIntVector( "/FamilyOtherBlues [", "]ND\n", mpCffLocal->maFamilyOtherBlues);
+ rEmitter.emitValVector( "/OtherBlues [", "]ND\n", mpCffLocal->maOtherBlues);
+ rEmitter.emitValVector( "/FamilyBlues [", "]ND\n", mpCffLocal->maFamilyBlues);
+ rEmitter.emitValVector( "/FamilyOtherBlues [", "]ND\n", mpCffLocal->maFamilyOtherBlues);
if( mpCffLocal->mfBlueScale)
pOut += sprintf( pOut, "/BlueScale %.6f def\n", mpCffLocal->mfBlueScale);
@@ -2278,8 +2341,8 @@ bool CffSubsetterContext::emitAsType1( Type1Emitter& rEmitter,
pOut += sprintf( pOut, "/StdHW [%d] def\n", mpCffLocal->mnStemStdHW);
if( mpCffLocal->mnStemStdVW)
pOut += sprintf( pOut, "/StdVW [%d] def\n", mpCffLocal->mnStemStdVW);
- rEmitter.emitIntVector( "/StemSnapH [", "]ND\n", mpCffLocal->maStemSnapH);
- rEmitter.emitIntVector( "/StemSnapV [", "]ND\n", mpCffLocal->maStemSnapV);
+ rEmitter.emitValVector( "/StemSnapH [", "]ND\n", mpCffLocal->maStemSnapH);
+ rEmitter.emitValVector( "/StemSnapV [", "]ND\n", mpCffLocal->maStemSnapV);
// emit other hints
if( mpCffLocal->mbForceBold)
@@ -2383,7 +2446,8 @@ bool CffSubsetterContext::emitAsType1( Type1Emitter& rEmitter,
// provide details to the subset requesters, TODO: move into own method?
// note: Top and Bottom are flipped between Type1 and VCL
- rFSInfo.m_aFontBBox = Rectangle( Point( maFontBBox[0], maFontBBox[1] ), Point( maFontBBox[2], maFontBBox[3] ) );
+ rFSInfo.m_aFontBBox = Rectangle( Point( static_cast<long>(maFontBBox[0]), static_cast<long>(maFontBBox[1]) ),
+ Point( static_cast<long>(maFontBBox[2]), static_cast<long>(maFontBBox[3]) ) );
// PDF-Spec says the values below mean the ink bounds!
// TODO: use better approximations for these ink bounds
rFSInfo.m_nAscent = +rFSInfo.m_aFontBBox.Bottom(); // for capital letters
diff --git a/vcl/source/fontsubset/fontsubset.cxx b/vcl/source/fontsubset/fontsubset.cxx
index e203feed1645..84f548d0a32f 100644
--- a/vcl/source/fontsubset/fontsubset.cxx
+++ b/vcl/source/fontsubset/fontsubset.cxx
@@ -40,7 +40,7 @@ FontSubsetInfo::FontSubsetInfo()
, m_nCapHeight( 0)
, m_nFontType( FontSubsetInfo::NO_FONT)
, mpInFontBytes( NULL)
-, mnInByteLength( NULL)
+, mnInByteLength( 0)
, meInFontType( FontSubsetInfo::NO_FONT)
, mpSftTTFont( NULL)
{}
diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx
index 345dc162e67e..0a7a8b765b6b 100644
--- a/vcl/source/gdi/outdev3.cxx
+++ b/vcl/source/gdi/outdev3.cxx
@@ -6,8 +6,6 @@
*
* OpenOffice.org - a multi-platform office productivity suite
*
- * $RCSfile: outdev3.cxx,v $
- *
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
@@ -4498,71 +4496,78 @@ void OutputDevice::ImplDrawStrikeoutChar( long nBaseX, long nBaseY,
FontStrikeout eStrikeout,
Color aColor )
{
- BOOL bOldMap = IsMapModeEnabled();
- EnableMapMode( FALSE );
-
- Color aOldColor = GetTextColor();
- SetTextColor( aColor );
- ImplInitTextColor();
+ // PDF-export does its own strikeout drawing... why again?
+ if( mpPDFWriter && mpPDFWriter->isBuiltinFont(mpFontEntry->maFontSelData.mpFontData) )
+ return;
- xub_Unicode pChars[5];
+ // prepare string for strikeout measurement
+ static char cStrikeoutChar;
if ( eStrikeout == STRIKEOUT_SLASH )
- pChars[0] = '/';
+ cStrikeoutChar = '/';
else // ( eStrikeout == STRIKEOUT_X )
- pChars[0] = 'X';
- pChars[3]=pChars[2]=pChars[1]=pChars[0];
+ cStrikeoutChar = 'X';
+ static const int nTestStrLen = 4;
+ static const int nMaxStrikeStrLen = 2048;
+ xub_Unicode aChars[ nMaxStrikeStrLen +1]; // +1 for valgrind...
+ for( int i = 0; i < nTestStrLen; ++i)
+ aChars[i] = cStrikeoutChar;
+ const String aStrikeoutTest( aChars, nTestStrLen );
// calculate approximation of strikeout atom size
long nStrikeoutWidth = nWidth;
- String aStrikeoutTest( pChars, 4 );
- SalLayout* pLayout = ImplLayout( aStrikeoutTest, 0, 4 );
- if ( pLayout )
+ SalLayout* pLayout = ImplLayout( aStrikeoutTest, 0, nTestStrLen );
+ if( pLayout )
{
- nStrikeoutWidth = (pLayout->GetTextWidth() + 2) / 4;
+ nStrikeoutWidth = (pLayout->GetTextWidth() +nTestStrLen/2) / (nTestStrLen * pLayout->GetUnitsPerPixel());
pLayout->Release();
- if ( nStrikeoutWidth <= 0 ) // sanity check
- nStrikeoutWidth = 1;
}
+ if( nStrikeoutWidth <= 0 ) // sanity check
+ return;
// calculate acceptable strikeout length
// allow the strikeout to be one pixel larger than the text it strikes out
- long nMaxWidth = nStrikeoutWidth/2;
+ long nMaxWidth = nStrikeoutWidth / 2;
if ( nMaxWidth < 2 )
nMaxWidth = 2;
nMaxWidth += nWidth + 1;
- // build strikeout string
- long nFullStrikeoutWidth = 0;
- String aStrikeoutText( pChars, 0 );
- while ( (nFullStrikeoutWidth+=nStrikeoutWidth) < nMaxWidth+1 )
- aStrikeoutText += pChars[0];
-
+ int nStrikeStrLen = (nMaxWidth + nStrikeoutWidth - 1) / nStrikeoutWidth;
// if the text width is smaller than the strikeout text, then do not
// strike out at all. This case requires user interaction, e.g. adding
// a space to the text
- if ( (aStrikeoutText.Len() > 0)
- && !(mpPDFWriter && mpPDFWriter->isBuiltinFont(mpFontEntry->maFontSelData.mpFontData) ) )
- {
- if ( mpFontEntry->mnOrientation )
- ImplRotatePos( nBaseX, nBaseY, nX, nY, mpFontEntry->mnOrientation );
+ if( nStrikeStrLen <= 0 )
+ return;
+ if( nStrikeStrLen > nMaxStrikeStrLen )
+ nStrikeStrLen = nMaxStrikeStrLen;
- // strikeout text has to be left aligned
- ULONG nOrigTLM = mnTextLayoutMode;
- mnTextLayoutMode = TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_COMPLEX_DISABLED;
- SalLayout* pSalLayout = ImplLayout( aStrikeoutText, 0, STRING_LEN );
- mnTextLayoutMode = nOrigTLM;
+ // build the strikeout string
+ for( int i = nTestStrLen; i < nStrikeStrLen; ++i)
+ aChars[i] = cStrikeoutChar;
+ const String aStrikeoutText( aChars, xub_StrLen(nStrikeStrLen) );
- if ( pSalLayout )
- {
- pSalLayout->DrawBase() = Point( nX+mnTextOffX, nY+mnTextOffY );
- pSalLayout->DrawText( *mpGraphics );
- pSalLayout->Release();
- }
- }
+ if( mpFontEntry->mnOrientation )
+ ImplRotatePos( nBaseX, nBaseY, nX, nY, mpFontEntry->mnOrientation );
+
+ // strikeout text has to be left aligned
+ ULONG nOrigTLM = mnTextLayoutMode;
+ mnTextLayoutMode = TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_COMPLEX_DISABLED;
+ pLayout = ImplLayout( aStrikeoutText, 0, STRING_LEN );
+ mnTextLayoutMode = nOrigTLM;
+
+ if( !pLayout )
+ return;
+
+ // draw the strikeout text
+ const Color aOldColor = GetTextColor();
+ SetTextColor( aColor );
+ ImplInitTextColor();
+
+ pLayout->DrawBase() = Point( nX+mnTextOffX, nY+mnTextOffY );
+ pLayout->DrawText( *mpGraphics );
+ pLayout->Release();
SetTextColor( aOldColor );
ImplInitTextColor();
- EnableMapMode( bOldMap );
}
// -----------------------------------------------------------------------
@@ -6777,17 +6782,21 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
{
BOOL bHighContrastBlack = FALSE;
BOOL bHighContrastWhite = FALSE;
- Color aCol;
- if( IsBackground() )
- aCol = GetBackground().GetColor();
- else
- // best guess is the face color here
- // but it may be totally wrong. the background color
- // was typically already reset
- aCol = GetSettings().GetStyleSettings().GetFaceColor();
+ const StyleSettings& rStyleSettings( GetSettings().GetStyleSettings() );
+ if( rStyleSettings.GetHighContrastMode() )
+ {
+ Color aCol;
+ if( IsBackground() )
+ aCol = GetBackground().GetColor();
+ else
+ // best guess is the face color here
+ // but it may be totally wrong. the background color
+ // was typically already reset
+ aCol = rStyleSettings.GetFaceColor();
- bHighContrastBlack = aCol.IsDark();
- bHighContrastWhite = aCol.IsBright() && GetSettings().GetStyleSettings().GetHighContrastMode();
+ bHighContrastBlack = aCol.IsDark();
+ bHighContrastWhite = aCol.IsBright();
+ }
aOldTextColor = GetTextColor();
if ( IsTextFillColor() )
@@ -6795,8 +6804,6 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
bRestoreFillColor = TRUE;
aOldTextFillColor = GetTextFillColor();
}
- else
- bRestoreFillColor = FALSE;
if( bHighContrastBlack )
SetTextColor( COL_GREEN );
else if( bHighContrastWhite )
@@ -6811,7 +6818,7 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
aRect.Move( 1, 1 );
DrawText( aRect, rOrigStr, nStyle & ~TEXT_DRAW_DISABLE );
*/
- SetTextColor( GetSettings().GetStyleSettings().GetShadowColor() );
+ SetTextColor( GetSettings().GetStyleSettings().GetDisableColor() );
}
}
@@ -7445,13 +7452,18 @@ void OutputDevice::DrawCtrlText( const Point& rPos, const XubString& rStr,
BOOL bRestoreFillColor;
BOOL bHighContrastBlack = FALSE;
BOOL bHighContrastWhite = FALSE;
- if( IsBackground() )
+ const StyleSettings& rStyleSettings( GetSettings().GetStyleSettings() );
+ if( rStyleSettings.GetHighContrastMode() )
{
- Wallpaper aWall = GetBackground();
- Color aCol = aWall.GetColor();
- bHighContrastBlack = aCol.IsDark();
- bHighContrastWhite = aCol.IsBright() && GetSettings().GetStyleSettings().GetHighContrastMode();
+ if( IsBackground() )
+ {
+ Wallpaper aWall = GetBackground();
+ Color aCol = aWall.GetColor();
+ bHighContrastBlack = aCol.IsDark();
+ bHighContrastWhite = aCol.IsBright();
+ }
}
+
aOldTextColor = GetTextColor();
if ( IsTextFillColor() )
{
@@ -7466,7 +7478,7 @@ void OutputDevice::DrawCtrlText( const Point& rPos, const XubString& rStr,
else if( bHighContrastWhite )
SetTextColor( COL_LIGHTGREEN );
else
- SetTextColor( GetSettings().GetStyleSettings().GetShadowColor() );
+ SetTextColor( GetSettings().GetStyleSettings().GetDisableColor() );
DrawText( rPos, aStr, nIndex, nLen, pVector, pDisplayText );
if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_NOMNEMONICS) && !pVector )
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 2cbebf6f23e2..e7ee18ec7705 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -805,7 +805,7 @@ class Matrix3
{
double f[6];
- void set( double *pn ) { for( int i = 0 ; i < 5; i++ ) f[i] = pn[i]; }
+ void set( double *pn ) { for( int i = 0 ; i < 6; i++ ) f[i] = pn[i]; }
public:
Matrix3();
~Matrix3() {}
@@ -6787,14 +6787,15 @@ void PDFWriterImpl::drawHorizontalGlyphs(
for( sal_uInt32 nPos = nBeginRun+1; nPos < aRunEnds[nRun]; nPos++ )
{
appendHex( rGlyphs[nPos].m_nMappedGlyphId, aUnkernedLine );
- // check if glyph advance matches with the width of the previous glyph, else adjust
+ // check if default glyph positioning is sufficient
const Point aThisPos = aMat.transform( rGlyphs[nPos].m_aPos );
const Point aPrevPos = aMat.transform( rGlyphs[nPos-1].m_aPos );
double fAdvance = aThisPos.X() - aPrevPos.X();
- fAdvance *= 1000.0 / (fXScale * nPixelFontHeight);
- const sal_Int32 nAdjustment = rGlyphs[nPos-1].m_nNativeWidth - sal_Int32(fAdvance+0.5);
+ fAdvance *= 1000.0 / nPixelFontHeight;
+ const sal_Int32 nAdjustment = (sal_Int32)(rGlyphs[nPos-1].m_nNativeWidth - fAdvance + 0.5);
if( nAdjustment != 0 )
{
+ // apply individual glyph positioning
bNeedKern = true;
aKernedLine.append( ">" );
aKernedLine.append( nAdjustment );
@@ -8643,6 +8644,8 @@ void PDFWriterImpl::drawPolyLine( const Polygon& rPoly, const PDFWriter::ExtLine
for(sal_uInt32 a(0); a < nEdgeCount; a++)
{
+ if( a > 0 )
+ aLine.append( " " );
const sal_uInt32 nNextIndex((a + 1) % nPointCount);
const basegfx::B2DPoint aNext(aPoly.getB2DPoint(nNextIndex));
diff --git a/vcl/source/gdi/wall.cxx b/vcl/source/gdi/wall.cxx
index e0c69ce582f4..587395fa783f 100644
--- a/vcl/source/gdi/wall.cxx
+++ b/vcl/source/gdi/wall.cxx
@@ -469,7 +469,7 @@ Gradient Wallpaper::ImplGetApplicationGradient() const
g.SetStyle( GRADIENT_LINEAR );
g.SetStartColor( Application::GetSettings().GetStyleSettings().GetFaceColor() );
// no 'extreme' gradient when high contrast
- if( Application::GetSettings().GetStyleSettings().GetFaceColor().IsDark() )
+ if( Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
g.SetEndColor( Application::GetSettings().GetStyleSettings().GetFaceColor() );
else
g.SetEndColor( Application::GetSettings().GetStyleSettings().GetFaceGradientColor() );
diff --git a/vcl/source/glyphs/graphite_adaptors.cxx b/vcl/source/glyphs/graphite_adaptors.cxx
index 67330698ffdf..9b16318fdc40 100644
--- a/vcl/source/glyphs/graphite_adaptors.cxx
+++ b/vcl/source/glyphs/graphite_adaptors.cxx
@@ -47,7 +47,7 @@
#include <rtl/ustring.hxx>
#include <i18npool/mslangid.hxx>
// Platform
-#ifndef MSC
+#ifndef WNT
#include <saldisp.hxx>
#include <vcl/salgdi.hxx>
diff --git a/vcl/source/glyphs/graphite_cache.cxx b/vcl/source/glyphs/graphite_cache.cxx
index c1bca0f87cb8..8c514c611d2c 100644
--- a/vcl/source/glyphs/graphite_cache.cxx
+++ b/vcl/source/glyphs/graphite_cache.cxx
@@ -28,7 +28,7 @@
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"
-#ifdef MSC
+#ifdef WNT
#include <tools/svwin.h>
#include <svsys.h>
#endif
diff --git a/vcl/source/glyphs/graphite_features.cxx b/vcl/source/glyphs/graphite_features.cxx
index 3c5214d3c420..dae1bfc2866e 100644
--- a/vcl/source/glyphs/graphite_features.cxx
+++ b/vcl/source/glyphs/graphite_features.cxx
@@ -38,7 +38,7 @@
#include <sal/types.h>
-#ifdef MSC
+#ifdef WNT
#include <tools/svwin.h>
#include <svsys.h>
#endif
diff --git a/vcl/source/glyphs/graphite_layout.cxx b/vcl/source/glyphs/graphite_layout.cxx
index 751c3694d033..86dee2749efa 100644
--- a/vcl/source/glyphs/graphite_layout.cxx
+++ b/vcl/source/glyphs/graphite_layout.cxx
@@ -54,7 +54,7 @@
#include <deque>
// Platform
-#ifdef MSC
+#ifdef WNT
#include <tools/svwin.h>
#include <svsys.h>
#endif
@@ -86,7 +86,7 @@
FILE * grLogFile = NULL;
FILE * grLog()
{
-#ifdef MSC
+#ifdef WNT
std::string logFileName(getenv("TEMP"));
logFileName.append("\\graphitelayout.log");
if (grLogFile == NULL) grLogFile = fopen(logFileName.c_str(),"w");
@@ -135,7 +135,7 @@ namespace
UErrorCode status = U_ZERO_ERROR;
UBiDi *ubidi = ubidi_openSized(charCount, 0, &status);
int limit = 0;
- ubidi_setPara(ubidi, buffer, charCount,
+ ubidi_setPara(ubidi, reinterpret_cast<const UChar *>(buffer), charCount,
(rtl)?UBIDI_DEFAULT_RTL:UBIDI_DEFAULT_LTR, NULL, &status);
UBiDiLevel level = 0;
ubidi_getLogicalRun(ubidi, 0, &limit, &level);
diff --git a/vcl/source/glyphs/graphite_serverfont.cxx b/vcl/source/glyphs/graphite_serverfont.cxx
index e8cd152b43ac..be424c94b9d2 100644
--- a/vcl/source/glyphs/graphite_serverfont.cxx
+++ b/vcl/source/glyphs/graphite_serverfont.cxx
@@ -45,7 +45,7 @@
#include "graphite_textsrc.hxx"
#include <vcl/graphite_serverfont.hxx>
-#ifndef MSC
+#ifndef WNT
//
// An implementation of the GraphiteLayout interface to enable Graphite enabled fonts to be used.
diff --git a/vcl/source/helper/lazydelete.cxx b/vcl/source/helper/lazydelete.cxx
index f5a8d8fbb14e..a300aedf8175 100644
--- a/vcl/source/helper/lazydelete.cxx
+++ b/vcl/source/helper/lazydelete.cxx
@@ -84,6 +84,9 @@ template<> bool LazyDeletor<Menu>::is_less( Menu* left, Menu* right )
DeleteOnDeinitBase::~DeleteOnDeinitBase()
{
+ ImplSVData* pSVData = ImplGetSVData();
+ if( pSVData && pSVData->mpDeinitDeleteList != NULL )
+ pSVData->mpDeinitDeleteList->remove( this );
}
void DeleteOnDeinitBase::addDeinitContainer( DeleteOnDeinitBase* i_pContainer )
diff --git a/vcl/source/window/brdwin.cxx b/vcl/source/window/brdwin.cxx
index f8baad0b4137..c9e8d11557e8 100644
--- a/vcl/source/window/brdwin.cxx
+++ b/vcl/source/window/brdwin.cxx
@@ -1840,7 +1840,7 @@ void ImplBorderWindow::ImplInit( Window* pParent,
{
// Alle WindowBits entfernen, die wir nicht haben wollen
WinBits nOrgStyle = nStyle;
- WinBits nTestStyle = (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_PINABLE | WB_CLOSEABLE | WB_STANDALONE | WB_DIALOGCONTROL | WB_NODIALOGCONTROL | WB_SYSTEMFLOATWIN | WB_INTROWIN | WB_DEFAULTWIN | WB_TOOLTIPWIN | WB_NOSHADOW | WB_OWNERDRAWDECORATION | WB_SYSTEMCHILDWINDOW );
+ WinBits nTestStyle = (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_PINABLE | WB_CLOSEABLE | WB_STANDALONE | WB_DIALOGCONTROL | WB_NODIALOGCONTROL | WB_SYSTEMFLOATWIN | WB_INTROWIN | WB_DEFAULTWIN | WB_TOOLTIPWIN | WB_NOSHADOW | WB_OWNERDRAWDECORATION | WB_SYSTEMCHILDWINDOW | WB_NEEDSFOCUS);
if ( nTypeStyle & BORDERWINDOW_STYLE_APP )
nTestStyle |= WB_APP;
nStyle &= nTestStyle;
diff --git a/vcl/source/window/dockmgr.cxx b/vcl/source/window/dockmgr.cxx
index b5f1ada74a98..c587b7ad8441 100644
--- a/vcl/source/window/dockmgr.cxx
+++ b/vcl/source/window/dockmgr.cxx
@@ -1238,8 +1238,8 @@ void ImplDockingWindowWrapper::StartPopupMode( ToolBox *pParentToolBox )
ULONG nFlags = FLOATWIN_POPUPMODE_ALLOWTEAROFF |
FLOATWIN_POPUPMODE_NOFOCUSCLOSE |
FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE |
- FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE |
- FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
+ FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE;
+// |FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
// if the subtoolbar was opened via keyboard make sure that key events
// will go into subtoolbar
diff --git a/vcl/source/window/floatwin.cxx b/vcl/source/window/floatwin.cxx
index 7bcb90bbb8fc..5f1578c4b9e2 100644
--- a/vcl/source/window/floatwin.cxx
+++ b/vcl/source/window/floatwin.cxx
@@ -243,6 +243,13 @@ FloatingWindow::~FloatingWindow()
// -----------------------------------------------------------------------
+Point FloatingWindow::CalcFloatingPosition( Window* pWindow, const Rectangle& rRect, ULONG nFlags, USHORT& rArrangeIndex )
+{
+ return ImplCalcPos( pWindow, rRect, nFlags, rArrangeIndex );
+}
+
+// -----------------------------------------------------------------------
+
Point FloatingWindow::ImplCalcPos( Window* pWindow,
const Rectangle& rRect, ULONG nFlags,
USHORT& rArrangeIndex )
@@ -676,8 +683,6 @@ void FloatingWindow::StartPopupMode( const Rectangle& rRect, ULONG nFlags )
// avoid close on focus change for decorated floating windows only
if( mpWindowImpl->mbFrame && (GetStyle() & WB_MOVEABLE) )
nFlags |= FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
- else
- nFlags &= ~FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
// #102010# For debugging Accessibility
static const char* pEnv = getenv("SAL_FLOATWIN_NOAPPFOCUSCLOSE" );
@@ -751,8 +756,9 @@ void FloatingWindow::StartPopupMode( ToolBox* pBox, ULONG nFlags )
// FLOATWIN_POPUPMODE_NOMOUSECLOSE |
FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE |
// FLOATWIN_POPUPMODE_NOMOUSERECTCLOSE | // #105968# floating toolboxes should close when clicked in (parent's) float rect
- FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE |
- FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
+ FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE;
+// | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
+
/*
* FLOATWIN_POPUPMODE_NOKEYCLOSE |
* don't set since it disables closing floaters with escape
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index ccf75dbd59b3..ebd4475a80fc 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -557,7 +557,7 @@ public:
void DataChanged( const DataChangedEvent& rDCEvt );
- void SetImages( long nMaxHeight = 0 );
+ void SetImages( long nMaxHeight = 0, bool bForce = false );
void calcMinSize();
Size getMinSize();
@@ -591,7 +591,7 @@ void DecoToolBox::DataChanged( const DataChangedEvent& rDCEvt )
{
calcMinSize();
SetBackground();
- SetImages();
+ SetImages( 0, true);
}
}
@@ -625,7 +625,7 @@ Size DecoToolBox::getMinSize()
return maMinSize;
}
-void DecoToolBox::SetImages( long nMaxHeight )
+void DecoToolBox::SetImages( long nMaxHeight, bool bForce )
{
long border = getMinSize().Height() - maImage.GetSizePixel().Height();
@@ -635,13 +635,13 @@ void DecoToolBox::SetImages( long nMaxHeight )
if( nMaxHeight < getMinSize().Height() )
nMaxHeight = getMinSize().Height();
- if( lastSize != nMaxHeight - border )
+ if( (lastSize != nMaxHeight - border) || bForce )
{
lastSize = nMaxHeight - border;
Color aEraseColor( 255, 255, 255, 255 );
BitmapEx aBmpExDst( maImage.GetBitmapEx() );
- BitmapEx aBmpExSrc( GetSettings().GetStyleSettings().GetMenuBarColor().IsDark() ?
+ BitmapEx aBmpExSrc( GetSettings().GetStyleSettings().GetHighContrastMode() ?
maImageHC.GetBitmapEx() : aBmpExDst );
aEraseColor.SetTransparency( 255 );
@@ -2731,7 +2731,14 @@ void Menu::ImplPaint( Window* pWin, USHORT nBorder, long nStartY, MenuItemData*
}
if ( pThisItemOnly && bHighlighted )
- pWin->SetTextColor( rSettings.GetMenuTextColor() );
+ {
+ // This restores the normal menu or menu bar text
+ // color for when it is no longer highlighted.
+ if ( bIsMenuBar )
+ pWin->SetTextColor( rSettings.GetMenuBarTextColor() );
+ else
+ pWin->SetTextColor( rSettings.GetMenuTextColor() );
+ }
}
if( bLayout )
{
@@ -3787,7 +3794,10 @@ static void ImplInitMenuWindow( Window* pWin, BOOL bFont, BOOL bMenuBar )
pWin->SetBackground( Wallpaper( rStyleSettings.GetMenuColor() ) );
}
- pWin->SetTextColor( rStyleSettings.GetMenuTextColor() );
+ if ( bMenuBar )
+ pWin->SetTextColor( rStyleSettings.GetMenuBarTextColor() );
+ else
+ pWin->SetTextColor( rStyleSettings.GetMenuTextColor() );
pWin->SetTextFillColor();
pWin->SetLineColor();
}
@@ -5056,7 +5066,7 @@ MenuBarWindow::MenuBarWindow( Window* pParent ) :
aCloser.SetParentClipMode( PARENTCLIPMODE_NOCLIP );
aCloser.InsertItem( IID_DOCUMENTCLOSE,
- GetSettings().GetStyleSettings().GetMenuBarColor().IsDark() ? aCloser.maImageHC : aCloser.maImage, 0 );
+ GetSettings().GetStyleSettings().GetHighContrastMode() ? aCloser.maImageHC : aCloser.maImage, 0 );
aCloser.SetSelectHdl( LINK( this, MenuBarWindow, CloserHdl ) );
aCloser.AddEventListener( LINK( this, MenuBarWindow, ToolboxEventHdl ) );
aCloser.SetQuickHelpText( IID_DOCUMENTCLOSE, XubString( ResId( SV_HELPTEXT_CLOSEDOCUMENT, *pResMgr ) ) );
@@ -5697,7 +5707,7 @@ void MenuBarWindow::Paint( const Rectangle& )
// in high contrast mode draw a separating line on the lower edge
if( ! IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL) &&
- GetSettings().GetStyleSettings().GetFaceColor().IsDark() )
+ GetSettings().GetStyleSettings().GetHighContrastMode() )
{
Push( PUSH_LINECOLOR | PUSH_MAPMODE );
SetLineColor( Color( COL_WHITE ) );
diff --git a/vcl/source/window/msgbox.cxx b/vcl/source/window/msgbox.cxx
index bd727092a836..3d3245af831f 100644
--- a/vcl/source/window/msgbox.cxx
+++ b/vcl/source/window/msgbox.cxx
@@ -500,7 +500,7 @@ void InfoBox::ImplInitInfoBoxData()
if ( !GetText().Len() )
SetText( Application::GetDisplayName() );
- SetImage( GetSettings().GetStyleSettings().GetDialogColor().IsDark() ?
+ SetImage( GetSettings().GetStyleSettings().GetHighContrastMode() ?
InfoBox::GetStandardImageHC() : InfoBox::GetStandardImage() );
mnSoundType = ((USHORT)SOUND_INFO)+1;
}
@@ -591,7 +591,7 @@ void ErrorBox::ImplInitErrorBoxData()
if ( !GetText().Len() )
SetText( Application::GetDisplayName() );
- SetImage( GetSettings().GetStyleSettings().GetDialogColor().IsDark() ?
+ SetImage( GetSettings().GetStyleSettings().GetHighContrastMode() ?
ErrorBox::GetStandardImageHC() : ErrorBox::GetStandardImage() );
mnSoundType = ((USHORT)SOUND_ERROR)+1;
}
@@ -637,7 +637,7 @@ void QueryBox::ImplInitQueryBoxData()
if ( !GetText().Len() )
SetText( Application::GetDisplayName() );
- SetImage( GetSettings().GetStyleSettings().GetDialogColor().IsDark() ?
+ SetImage( GetSettings().GetStyleSettings().GetHighContrastMode() ?
QueryBox::GetStandardImageHC() : QueryBox::GetStandardImage() );
mnSoundType = ((USHORT)SOUND_QUERY)+1;
}
diff --git a/vcl/source/window/toolbox.cxx b/vcl/source/window/toolbox.cxx
index bb1f428c6626..8aa4926f5e1a 100644
--- a/vcl/source/window/toolbox.cxx
+++ b/vcl/source/window/toolbox.cxx
@@ -397,7 +397,7 @@ void ToolBox::ImplDrawGradientBackground( ToolBox* pThis, ImplDockingWindowWrapp
Color startCol, endCol;
startCol = pThis->GetSettings().GetStyleSettings().GetFaceGradientColor();
endCol = pThis->GetSettings().GetStyleSettings().GetFaceColor();
- if( endCol.IsDark() )
+ if( pThis->GetSettings().GetStyleSettings().GetHighContrastMode() )
// no 'extreme' gradient when high contrast
startCol = endCol;
@@ -1901,37 +1901,78 @@ BOOL ToolBox::ImplCalcItem()
nDefWidth = GetDefaultImageSize().Width();
nDefHeight = GetDefaultImageSize().Height();
+ mnWinHeight = 0;
// determine minimum size necessary in NWF
- if( IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
{
Rectangle aRect( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
- Region aArrowReg = aRect;
+ Region aReg = aRect;
ImplControlValue aVal;
Region aNativeBounds, aNativeContent;
- if( GetNativeControlRegion( CTRL_TOOLBAR, PART_BUTTON,
- aArrowReg,
+ if( IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
+ {
+ if( GetNativeControlRegion( CTRL_TOOLBAR, PART_BUTTON,
+ aReg,
+ CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
+ aVal, OUString(),
+ aNativeBounds, aNativeContent ) )
+ {
+ aRect = aNativeBounds.GetBoundRect();
+ if( aRect.GetWidth() > nMinWidth )
+ nMinWidth = aRect.GetWidth();
+ if( aRect.GetHeight() > nMinHeight )
+ nMinHeight = aRect.GetHeight();
+ if( nDropDownArrowWidth < nMinWidth )
+ nDropDownArrowWidth = nMinWidth;
+ if( nMinWidth > mpData->mnMenuButtonWidth )
+ mpData->mnMenuButtonWidth = nMinWidth;
+ else if( nMinWidth < TB_MENUBUTTON_SIZE )
+ mpData->mnMenuButtonWidth = TB_MENUBUTTON_SIZE;
+ }
+ }
+
+ // also calculate the area for comboboxes, drop down list boxes and spinfields
+ // as these are often inserted into toolboxes; set mnWinHeight to the
+ // greater of those values to prevent toolbar flickering (#i103385#)
+ aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
+ aReg = aRect;
+ if( GetNativeControlRegion( CTRL_COMBOBOX, PART_ENTIRE_CONTROL,
+ aReg,
+ CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
+ aVal, OUString(),
+ aNativeBounds, aNativeContent ) )
+ {
+ aRect = aNativeBounds.GetBoundRect();
+ if( aRect.GetHeight() > mnWinHeight )
+ mnWinHeight = aRect.GetHeight();
+ }
+ aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
+ aReg = aRect;
+ if( GetNativeControlRegion( CTRL_LISTBOX, PART_ENTIRE_CONTROL,
+ aReg,
CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
aVal, OUString(),
aNativeBounds, aNativeContent ) )
{
aRect = aNativeBounds.GetBoundRect();
- if( aRect.GetWidth() > nMinWidth )
- nMinWidth = aRect.GetWidth();
- if( aRect.GetHeight() > nMinHeight )
- nMinHeight = aRect.GetHeight();
- if( nDropDownArrowWidth < nMinWidth )
- nDropDownArrowWidth = nMinWidth;
- if( nMinWidth > mpData->mnMenuButtonWidth )
- mpData->mnMenuButtonWidth = nMinWidth;
- else if( nMinWidth < TB_MENUBUTTON_SIZE )
- mpData->mnMenuButtonWidth = TB_MENUBUTTON_SIZE;
+ if( aRect.GetHeight() > mnWinHeight )
+ mnWinHeight = aRect.GetHeight();
+ }
+ aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
+ aReg = aRect;
+ if( GetNativeControlRegion( CTRL_SPINBOX, PART_ENTIRE_CONTROL,
+ aReg,
+ CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
+ aVal, OUString(),
+ aNativeBounds, aNativeContent ) )
+ {
+ aRect = aNativeBounds.GetBoundRect();
+ if( aRect.GetHeight() > mnWinHeight )
+ mnWinHeight = aRect.GetHeight();
}
}
if ( ! mpData->m_aItems.empty() )
{
- mnWinHeight = 0;
-
std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
while ( it != mpData->m_aItems.end() )
{
diff --git a/vcl/source/window/toolbox2.cxx b/vcl/source/window/toolbox2.cxx
index 7fa8f76e1586..9ec86fab20de 100644
--- a/vcl/source/window/toolbox2.cxx
+++ b/vcl/source/window/toolbox2.cxx
@@ -2413,10 +2413,10 @@ void ToolBox::ImplUpdateImageList()
{
if (mpData->mpImageListProvider != NULL)
{
- BOOL bIsDark = GetSettings().GetStyleSettings().GetFaceColor().IsDark();
+ BOOL bHC = GetSettings().GetStyleSettings().GetHighContrastMode();
try
{
- ImageListType eType = bIsDark ? vcl::HIGHCONTRAST_YES : vcl::HIGHCONTRAST_NO;
+ ImageListType eType = bHC ? vcl::HIGHCONTRAST_YES : vcl::HIGHCONTRAST_NO;
if (eType != mpData->meImageListType)
{
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index 5333d20d4306..6aff4779d8b2 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -292,6 +292,13 @@ bool Window::ImplCheckUIFont( const Font& rFont )
void Window::ImplUpdateGlobalSettings( AllSettings& rSettings, BOOL bCallHdl )
{
+ // reset high contrast to false, so the system can either update it
+ // or AutoDetectSystemHC can kick in (see below)
+ StyleSettings aTmpSt( rSettings.GetStyleSettings() );
+ aTmpSt.SetHighContrastMode( FALSE );
+ rSettings.SetStyleSettings( aTmpSt );
+ ImplGetFrame()->UpdateSettings( rSettings );
+
// Verify availability of the configured UI font, otherwise choose "Andale Sans UI"
String aUserInterfaceFont;
bool bUseSystemFont = rSettings.GetStyleSettings().GetUseSystemUIFonts();
@@ -472,7 +479,8 @@ void Window::ImplUpdateGlobalSettings( AllSettings& rSettings, BOOL bCallHdl )
rSettings.SetStyleSettings( aStyleSettings );
- // #104427# auto detect HC mode ?
+ // auto detect HC mode; if the system already set it to "yes"
+ // (see above) then accept that
if( !rSettings.GetStyleSettings().GetHighContrastMode() )
{
sal_Bool bTmp = sal_False, bAutoHCMode = sal_True;
@@ -728,7 +736,7 @@ void Window::ImplInit( Window* pParent, WinBits nStyle, SystemParentData* pSyste
nBorderTypeStyle |= BORDERWINDOW_STYLE_FRAME;
nStyle |= WB_BORDER;
}
- ImplBorderWindow* pBorderWin = new ImplBorderWindow( pParent, nStyle & (WB_BORDER | WB_DIALOGCONTROL | WB_NODIALOGCONTROL), nBorderTypeStyle );
+ ImplBorderWindow* pBorderWin = new ImplBorderWindow( pParent, nStyle & (WB_BORDER | WB_DIALOGCONTROL | WB_NODIALOGCONTROL | WB_NEEDSFOCUS), nBorderTypeStyle );
((Window*)pBorderWin)->mpWindowImpl->mpClientWindow = this;
pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
mpWindowImpl->mpBorderWindow = pBorderWin;
@@ -783,6 +791,8 @@ void Window::ImplInit( Window* pParent, WinBits nStyle, SystemParentData* pSyste
nFrameStyle = SAL_FRAME_STYLE_FLOAT;
if( nStyle & WB_OWNERDRAWDECORATION )
nFrameStyle |= (SAL_FRAME_STYLE_OWNERDRAWDECORATION | SAL_FRAME_STYLE_NOSHADOW);
+ if( nStyle & WB_NEEDSFOCUS )
+ nFrameStyle |= SAL_FRAME_STYLE_FLOAT_FOCUSABLE;
}
else if( mpWindowImpl->mbFloatWin )
nFrameStyle |= SAL_FRAME_STYLE_TOOLWINDOW;
@@ -923,7 +933,7 @@ void Window::ImplInit( Window* pParent, WinBits nStyle, SystemParentData* pSyste
! (nStyle & (WB_INTROWIN|WB_DEFAULTWIN))
)
{
- mpWindowImpl->mpFrame->UpdateSettings( *pSVData->maAppData.mpSettings );
+ // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
ImplUpdateGlobalSettings( *pSVData->maAppData.mpSettings );
OutputDevice::SetSettings( *pSVData->maAppData.mpSettings );
pSVData->maAppData.mbSettingsInit = TRUE;
diff --git a/vcl/unx/gtk/a11y/atktext.cxx b/vcl/unx/gtk/a11y/atktext.cxx
index 8bdfe1706962..8d83ca008e4a 100644
--- a/vcl/unx/gtk/a11y/atktext.cxx
+++ b/vcl/unx/gtk/a11y/atktext.cxx
@@ -33,12 +33,15 @@
#include "atkwrapper.hxx"
#include "atktextattributes.hxx"
+#include <algorithm>
#include <com/sun/star/accessibility/AccessibleTextType.hpp>
#include <com/sun/star/accessibility/TextSegment.hpp>
#include <com/sun/star/accessibility/XAccessibleMultiLineText.hpp>
#include <com/sun/star/accessibility/XAccessibleText.hpp>
#include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp>
+#include <com/sun/star/accessibility/XAccessibleTextMarkup.hpp>
+#include <com/sun/star/text/TextMarkupType.hpp>
// #define ENABLE_TRACING
@@ -175,6 +178,27 @@ static accessibility::XAccessibleText*
/*****************************************************************************/
+static accessibility::XAccessibleTextMarkup*
+ getTextMarkup( AtkText *pText ) throw (uno::RuntimeException)
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
+ if( pWrap )
+ {
+ if( !pWrap->mpTextMarkup && pWrap->mpContext )
+ {
+ uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleTextMarkup::static_type(NULL) );
+ pWrap->mpTextMarkup = reinterpret_cast< accessibility::XAccessibleTextMarkup * > (any.pReserved);
+ pWrap->mpTextMarkup->acquire();
+ }
+
+ return pWrap->mpTextMarkup;
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
static accessibility::XAccessibleTextAttributes*
getTextAttributes( AtkText *pText ) throw (uno::RuntimeException)
{
@@ -434,6 +458,8 @@ text_wrapper_get_run_attributes( AtkText *text,
AtkAttributeSet *pSet = NULL;
try {
+ bool bOffsetsAreValid = false;
+
accessibility::XAccessibleText* pText = getText( text );
accessibility::XAccessibleTextAttributes* pTextAttributes = getTextAttributes( text );
if( pText && pTextAttributes )
@@ -456,10 +482,47 @@ text_wrapper_get_run_attributes( AtkText *text,
// *end_offset = aTextSegment.SegmentEnd + 1; // FIXME: TESTME
*end_offset = aTextSegment.SegmentEnd;
// <--
+ bOffsetsAreValid = true;
+ }
+ }
+
+ // Special handling for missspelled
+ accessibility::XAccessibleTextMarkup* pTextMarkup = getTextMarkup( text );
+ if( pTextMarkup )
+ {
+ uno::Sequence< accessibility::TextSegment > aTextSegmentSeq =
+ pTextMarkup->getTextMarkupAtIndex( offset, com::sun::star::text::TextMarkupType::SPELLCHECK );
+ if( aTextSegmentSeq.getLength() > 0 )
+ {
+ accessibility::TextSegment aTextSegment = aTextSegmentSeq[0];
+ gint nStartOffsetMisspelled = aTextSegment.SegmentStart;
+ gint nEndOffsetMisspelled = aTextSegment.SegmentEnd;
+
+ // Get attribute run here if it hasn't been done before
+ if( !bOffsetsAreValid )
+ {
+ accessibility::TextSegment aAttributeTextSegment =
+ pText->getTextAtIndex(offset, accessibility::AccessibleTextType::ATTRIBUTE_RUN);
+ *start_offset = aAttributeTextSegment.SegmentStart;
+ *end_offset = aAttributeTextSegment.SegmentEnd;
+ }
+
+ if( nEndOffsetMisspelled <= offset )
+ *start_offset = ::std::max( *start_offset, nEndOffsetMisspelled );
+ else if( nStartOffsetMisspelled <= offset )
+ *start_offset = ::std::max( *start_offset, nStartOffsetMisspelled );
+
+ if( nStartOffsetMisspelled > offset )
+ *end_offset = ::std::min( *end_offset, nStartOffsetMisspelled );
+ else if( nEndOffsetMisspelled > offset )
+ *end_offset = ::std::min( *end_offset, nEndOffsetMisspelled );
+
+ if( nStartOffsetMisspelled <= offset && nEndOffsetMisspelled > offset )
+ pSet = attribute_set_prepend_misspelled( pSet );
}
}
}
- catch(const uno::Exception& e) {
+ catch(const uno::Exception& e){
g_warning( "Exception in get_run_attributes()" );
diff --git a/vcl/unx/gtk/a11y/atktextattributes.cxx b/vcl/unx/gtk/a11y/atktextattributes.cxx
index f6b1eccc882a..58dd5f200bbd 100644
--- a/vcl/unx/gtk/a11y/atktextattributes.cxx
+++ b/vcl/unx/gtk/a11y/atktextattributes.cxx
@@ -76,6 +76,7 @@ static AtkTextAttribute atk_text_attribute_tab_interval = ATK_TEXT_ATTR_INVALID;
static AtkTextAttribute atk_text_attribute_tab_stops = ATK_TEXT_ATTR_INVALID;
static AtkTextAttribute atk_text_attribute_writing_mode = ATK_TEXT_ATTR_INVALID;
static AtkTextAttribute atk_text_attribute_vertical_align = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_misspelled = ATK_TEXT_ATTR_INVALID;
/*****************************************************************************/
@@ -1299,6 +1300,18 @@ attribute_set_new_from_property_values(
}
+AtkAttributeSet* attribute_set_prepend_misspelled( AtkAttributeSet* attribute_set )
+{
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_misspelled )
+ atk_text_attribute_misspelled = atk_text_attribute_register( "text-spelling" );
+
+ attribute_set = attribute_set_prepend( attribute_set, atk_text_attribute_misspelled,
+ g_strdup_printf( "misspelled" ) );
+
+ return attribute_set;
+}
+
+
/*****************************************************************************/
struct AtkTextAttrMapping
diff --git a/vcl/unx/gtk/a11y/atktextattributes.hxx b/vcl/unx/gtk/a11y/atktextattributes.hxx
index 909f09eb1522..ca67fd946a20 100644
--- a/vcl/unx/gtk/a11y/atktextattributes.hxx
+++ b/vcl/unx/gtk/a11y/atktextattributes.hxx
@@ -47,5 +47,6 @@ attribute_set_map_to_property_values(
AtkAttributeSet* attribute_set,
com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& rValueList );
+AtkAttributeSet* attribute_set_prepend_misspelled( AtkAttributeSet* attribute_set );
#endif
diff --git a/vcl/unx/gtk/a11y/atkwrapper.cxx b/vcl/unx/gtk/a11y/atkwrapper.cxx
index 927b8548a77a..8854083e1509 100644
--- a/vcl/unx/gtk/a11y/atkwrapper.cxx
+++ b/vcl/unx/gtk/a11y/atkwrapper.cxx
@@ -40,6 +40,7 @@
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
#include <com/sun/star/accessibility/XAccessible.hpp>
#include <com/sun/star/accessibility/XAccessibleText.hpp>
+#include <com/sun/star/accessibility/XAccessibleTextMarkup.hpp>
#include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp>
#include <com/sun/star/accessibility/XAccessibleValue.hpp>
#include <com/sun/star/accessibility/XAccessibleAction.hpp>
@@ -893,6 +894,7 @@ void atk_object_wrapper_dispose(AtkObjectWrapper* wrapper)
RELEASE( wrapper->mpMultiLineText )
RELEASE( wrapper->mpTable )
RELEASE( wrapper->mpText )
+ RELEASE( wrapper->mpTextMarkup )
RELEASE( wrapper->mpTextAttributes )
RELEASE( wrapper->mpValue )
}
diff --git a/vcl/unx/gtk/a11y/atkwrapper.hxx b/vcl/unx/gtk/a11y/atkwrapper.hxx
index 1003d0d25cc7..95cf30096e7b 100644
--- a/vcl/unx/gtk/a11y/atkwrapper.hxx
+++ b/vcl/unx/gtk/a11y/atkwrapper.hxx
@@ -49,6 +49,7 @@ namespace com { namespace sun { namespace star { namespace accessibility {
class XAccessibleSelection;
class XAccessibleTable;
class XAccessibleText;
+ class XAccessibleTextMarkup;
class XAccessibleTextAttributes;
class XAccessibleValue;
} } } }
@@ -69,6 +70,7 @@ struct _AtkObjectWrapper
::com::sun::star::accessibility::XAccessibleSelection *mpSelection;
::com::sun::star::accessibility::XAccessibleTable *mpTable;
::com::sun::star::accessibility::XAccessibleText *mpText;
+ ::com::sun::star::accessibility::XAccessibleTextMarkup *mpTextMarkup;
::com::sun::star::accessibility::XAccessibleTextAttributes *mpTextAttributes;
::com::sun::star::accessibility::XAccessibleValue *mpValue;
diff --git a/vcl/unx/gtk/app/gtkinst.cxx b/vcl/unx/gtk/app/gtkinst.cxx
index 73b4432342bf..8bed40fa539f 100644
--- a/vcl/unx/gtk/app/gtkinst.cxx
+++ b/vcl/unx/gtk/app/gtkinst.cxx
@@ -134,6 +134,16 @@ extern "C"
VCL_DLLPUBLIC SalInstance* create_SalInstance( oslModule pModule )
{
+ /* #i92121# workaround deadlocks in the X11 implementation
+ */
+ static const char* pNoXInitThreads = getenv( "SAL_NO_XINITTHREADS" );
+ /* #i90094#
+ from now on we know that an X connection will be
+ established, so protect X against itself
+ */
+ if( ! ( pNoXInitThreads && *pNoXInitThreads ) )
+ XInitThreads();
+
#if OSL_DEBUG_LEVEL > 1
int nFd = open( "/home/pl93762/log.txt", O_CREAT | O_TRUNC | O_WRONLY, 0755 );
dup2( nFd, STDERR_FILENO );
diff --git a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
index fdaa102c614b..f922552ce923 100644
--- a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
+++ b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
@@ -3291,12 +3291,38 @@ void GtkSalGraphics::updateSettings( AllSettings& rSettings )
aBackColor = getColor( pMenubarStyle->bg[GTK_STATE_NORMAL] );
aStyleSet.SetMenuBarColor( aBackColor );
aBackColor = getColor( pMenuStyle->bg[GTK_STATE_NORMAL] );
- aTextColor = getColor( pMenuTextStyle->fg[GTK_STATE_NORMAL] );
- if( aBackColor == aTextColor )
- aTextColor = (aBackColor.GetLuminance() < 128) ? Color( COL_WHITE ) : Color( COL_BLACK );
+ aTextColor = getColor( pMenuTextStyle->text[GTK_STATE_NORMAL] );
aStyleSet.SetMenuColor( aBackColor );
aStyleSet.SetMenuTextColor( aTextColor );
+ aTextColor = getColor( pMenubarStyle->text[GTK_STATE_NORMAL] );
+ aStyleSet.SetMenuBarTextColor( aTextColor );
+
+#if OSL_DEBUG_LEVEL > 1
+ std::fprintf( stderr, "==\n" );
+ std::fprintf( stderr, "MenuColor = %x (%d)\n", (int)aStyleSet.GetMenuColor().GetColor(), aStyleSet.GetMenuColor().GetLuminance() );
+ std::fprintf( stderr, "MenuTextColor = %x (%d)\n", (int)aStyleSet.GetMenuTextColor().GetColor(), aStyleSet.GetMenuTextColor().GetLuminance() );
+ std::fprintf( stderr, "MenuBarColor = %x (%d)\n", (int)aStyleSet.GetMenuBarColor().GetColor(), aStyleSet.GetMenuBarColor().GetLuminance() );
+ std::fprintf( stderr, "MenuBarTextColor = %x (%d)\n", (int)aStyleSet.GetMenuBarTextColor().GetColor(), aStyleSet.GetMenuBarTextColor().GetLuminance() );
+ std::fprintf( stderr, "LightColor = %x (%d)\n", (int)aStyleSet.GetLightColor().GetColor(), aStyleSet.GetLightColor().GetLuminance() );
+ std::fprintf( stderr, "ShadowColor = %x (%d)\n", (int)aStyleSet.GetShadowColor().GetColor(), aStyleSet.GetShadowColor().GetLuminance() );
+#endif
+
+ // Awful hack for menu separators in the Sonar and similar themes.
+ // If the menu color is not too dark, and the menu text color is lighter,
+ // make the "light" color lighter than the menu color and the "shadow"
+ // color darker than it.
+ if ( aStyleSet.GetMenuColor().GetLuminance() >= 32 &&
+ aStyleSet.GetMenuColor().GetLuminance() <= aStyleSet.GetMenuTextColor().GetLuminance() )
+ {
+ Color temp = aStyleSet.GetMenuColor();
+ temp.IncreaseLuminance( 8 );
+ aStyleSet.SetLightColor( temp );
+ temp = aStyleSet.GetMenuColor();
+ temp.DecreaseLuminance( 16 );
+ aStyleSet.SetShadowColor( temp );
+ }
+
aHighlightColor = getColor( pMenuItemStyle->bg[ GTK_STATE_SELECTED ] );
aHighlightTextColor = getColor( pMenuTextStyle->fg[ GTK_STATE_PRELIGHT ] );
if( aHighlightColor == aHighlightTextColor )
@@ -3439,13 +3465,6 @@ void GtkSalGraphics::updateSettings( AllSettings& rSettings )
// FIXME: need some way of fetching toolbar icon size.
// aStyleSet.SetToolbarIconSize( STYLE_TOOLBAR_ICONSIZE_SMALL );
- /* #i35482# do not override HC mode per force
- // #i59364# high contrast mode
- bool bHC = ( aStyleSet.GetFaceColor().IsDark() ||
- aStyleSet.GetWindowColor().IsDark() );
- aStyleSet.SetHighContrastMode( bHC );
- */
-
// finally update the collected settings
rSettings.SetStyleSettings( aStyleSet );
diff --git a/vcl/unx/gtk/window/gtkframe.cxx b/vcl/unx/gtk/window/gtkframe.cxx
index b6770ca1a77e..8963ac2e3643 100644
--- a/vcl/unx/gtk/window/gtkframe.cxx
+++ b/vcl/unx/gtk/window/gtkframe.cxx
@@ -1123,7 +1123,7 @@ void GtkSalFrame::SetIcon( USHORT nIcon )
USHORT nIndex;
// Use high contrast icons where appropriate
- if( Application::GetSettings().GetStyleSettings().GetFaceColor().IsDark() )
+ if( Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
{
nOffsets[0] = SV_ICON_LARGE_HC_START;
nOffsets[1] = SV_ICON_SMALL_HC_START;
@@ -1506,7 +1506,7 @@ void GtkSalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight, USHOR
if( isChild( false, true ) )
gtk_widget_set_size_request( m_pWindow, nWidth, nHeight );
- else
+ else if( ! ( m_nState & GDK_WINDOW_STATE_MAXIMIZED ) )
gtk_window_resize( GTK_WINDOW(m_pWindow), nWidth, nHeight );
setMinMaxSize();
}
@@ -1608,6 +1608,7 @@ void GtkSalFrame::SetWindowState( const SalFrameState* pState )
SAL_FRAMESTATE_MASK_MAXIMIZED_WIDTH | SAL_FRAMESTATE_MASK_MAXIMIZED_HEIGHT;
if( (pState->mnMask & SAL_FRAMESTATE_MASK_STATE) &&
+ ! ( m_nState & GDK_WINDOW_STATE_MAXIMIZED ) &&
(pState->mnState & SAL_FRAMESTATE_MAXIMIZED) &&
(pState->mnMask & nMaxGeometryMask) == nMaxGeometryMask )
{
diff --git a/vcl/unx/inc/salinst.h b/vcl/unx/inc/salinst.h
index c0614a78af9b..bef5cfd5e9b4 100644
--- a/vcl/unx/inc/salinst.h
+++ b/vcl/unx/inc/salinst.h
@@ -116,6 +116,11 @@ public:
virtual void* GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes );
void FillFontPathList( std::list< rtl::OString >& o_rFontPaths );
+ // 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();
bool isPrinterInit() const
{
diff --git a/vcl/unx/kde/kdedata.cxx b/vcl/unx/kde/kdedata.cxx
index 15a5ba087ab2..1b5a2f86dcee 100644
--- a/vcl/unx/kde/kdedata.cxx
+++ b/vcl/unx/kde/kdedata.cxx
@@ -232,6 +232,16 @@ void KDEData::Init()
extern "C" {
VCL_DLLPUBLIC SalInstance* create_SalInstance( oslModule )
{
+ /* #i92121# workaround deadlocks in the X11 implementation
+ */
+ static const char* pNoXInitThreads = getenv( "SAL_NO_XINITTHREADS" );
+ /* #i90094#
+ from now on we know that an X connection will be
+ established, so protect X against itself
+ */
+ if( ! ( pNoXInitThreads && *pNoXInitThreads ) )
+ XInitThreads();
+
rtl::OString aVersion( qVersion() );
#if OSL_DEBUG_LEVEL > 1
fprintf( stderr, "qt version string is \"%s\"\n", aVersion.getStr() );
diff --git a/vcl/unx/kde/salnativewidgets-kde.cxx b/vcl/unx/kde/salnativewidgets-kde.cxx
index 24358022d6a1..8046d22d75d3 100644
--- a/vcl/unx/kde/salnativewidgets-kde.cxx
+++ b/vcl/unx/kde/salnativewidgets-kde.cxx
@@ -1996,6 +1996,7 @@ void KDESalFrame::UpdateSettings( AllSettings& rSettings )
}
aStyleSettings.SetMenuTextColor( aMenuFore );
+ aStyleSettings.SetMenuBarTextColor( aMenuFore );
aStyleSettings.SetMenuColor( aMenuBack );
aStyleSettings.SetMenuBarColor( aMenuBack );
@@ -2035,13 +2036,6 @@ void KDESalFrame::UpdateSettings( AllSettings& rSettings )
// Scroll bar size
aStyleSettings.SetScrollBarSize( kapp->style().pixelMetric( QStyle::PM_ScrollBarExtent ) );
- /* #i35482# do not override HC mode
- // #i59364# high contrast mode
- bool bHC = ( aStyleSettings.GetFaceColor().IsDark() ||
- aStyleSettings.GetWindowColor().IsDark() );
- aStyleSettings.SetHighContrastMode( bHC );
- */
-
rSettings.SetStyleSettings( aStyleSettings );
}
diff --git a/vcl/unx/kde4/KDEData.cxx b/vcl/unx/kde4/KDEData.cxx
index 07a10c60d933..91e3a758da3c 100644
--- a/vcl/unx/kde4/KDEData.cxx
+++ b/vcl/unx/kde4/KDEData.cxx
@@ -45,6 +45,8 @@ void KDEData::initNWF()
// draw toolbars on separate lines
pSVData->maNWFData.mbDockingAreaSeparateTB = true;
+ // no borders for menu, theming does that
+ pSVData->maNWFData.mbFlatMenu = true;
}
void KDEData::deInitNWF()
diff --git a/vcl/unx/kde4/KDESalFrame.cxx b/vcl/unx/kde4/KDESalFrame.cxx
index ad8f467ee960..796350a63d50 100644
--- a/vcl/unx/kde4/KDESalFrame.cxx
+++ b/vcl/unx/kde4/KDESalFrame.cxx
@@ -318,6 +318,7 @@ void KDESalFrame::UpdateSettings( AllSettings& rSettings )
aMenuBack = toColor( qMenuCG.color( QPalette::Button ) );
style.SetMenuTextColor( aMenuFore );
+ style.SetMenuBarTextColor( aMenuFore );
style.SetMenuColor( aMenuBack );
style.SetMenuBarColor( aMenuBack );
diff --git a/vcl/unx/kde4/KDESalGraphics.cxx b/vcl/unx/kde4/KDESalGraphics.cxx
index ae917f252b11..2e8f0dcad96b 100644
--- a/vcl/unx/kde4/KDESalGraphics.cxx
+++ b/vcl/unx/kde4/KDESalGraphics.cxx
@@ -35,6 +35,8 @@
#include <QStyle>
#include <QStyleOption>
#include <QPainter>
+#include <QFrame>
+#include <QLabel>
#include <kapplication.h>
@@ -42,10 +44,9 @@
#include "KDESalGraphics.hxx"
-#include <vcl/settings.hxx>
-#include <rtl/ustrbuf.hxx>
-
-#include <stdio.h>
+#include "vcl/settings.hxx"
+#include "vcl/decoview.hxx"
+#include "rtl/ustrbuf.hxx"
using namespace ::rtl;
@@ -150,6 +151,30 @@ BOOL KDESalGraphics::hitTestNativeControl( ControlType, ControlPart,
return FALSE;
}
+void lcl_drawFrame( QRect& i_rRect, QPainter& i_rPainter, QStyle::PrimitiveElement i_nElement,
+ ControlState i_nState, const ImplControlValue& i_rValue )
+{
+ #if ( QT_VERSION >= QT_VERSION_CHECK( 4, 5, 0 ) )
+ QStyleOptionFrameV3 styleOption;
+ styleOption.frameShape = QFrame::StyledPanel;
+ #else
+ QStyleOptionFrame styleOption;
+ QFrame aFrame( NULL );
+ aFrame.setFrameRect( QRect(0, 0, i_rRect.width(), i_rRect.height()) );
+ aFrame.setFrameStyle( QFrame::StyledPanel | QFrame::Sunken );
+ aFrame.ensurePolished();
+ styleOption.initFrom( &aFrame );
+ styleOption.lineWidth = aFrame.lineWidth();
+ styleOption.midLineWidth = aFrame.midLineWidth();
+ #endif
+ styleOption.rect = QRect(0, 0, i_rRect.width(), i_rRect.height());
+ styleOption.state = vclStateValue2StateFlag( i_nState, i_rValue );
+ #if ( QT_VERSION < QT_VERSION_CHECK( 4, 5, 0 ) )
+ styleOption.state |= QStyle::State_Sunken;
+ #endif
+ kapp->style()->drawPrimitive(i_nElement, &styleOption, &i_rPainter);
+}
+
BOOL KDESalGraphics::drawNativeControl( ControlType type, ControlPart part,
const Region& rControlRegion, ControlState nControlState,
const ImplControlValue& value, SalControlHandle&,
@@ -352,18 +377,25 @@ BOOL KDESalGraphics::drawNativeControl( ControlType type, ControlPart part,
}
else if (type == CTRL_LISTBOX)
{
- QStyleOptionComboBox styleOption;
-
- styleOption.rect = QRect(0, 0, widgetRect.width(), widgetRect.height());
- styleOption.state = vclStateValue2StateFlag( nControlState, value );
-
- if (part == PART_SUB_EDIT)
+ if( part == PART_WINDOW )
{
- kapp->style()->drawControl(QStyle::CE_ComboBoxLabel, &styleOption, &painter);
+ lcl_drawFrame( widgetRect, painter, QStyle::PE_Frame, nControlState, value );
}
else
{
- kapp->style()->drawComplexControl(QStyle::CC_ComboBox, &styleOption, &painter);
+ QStyleOptionComboBox styleOption;
+
+ styleOption.rect = QRect(0, 0, widgetRect.width(), widgetRect.height());
+ styleOption.state = vclStateValue2StateFlag( nControlState, value );
+
+ if (part == PART_SUB_EDIT)
+ {
+ kapp->style()->drawControl(QStyle::CE_ComboBoxLabel, &styleOption, &painter);
+ }
+ else
+ {
+ kapp->style()->drawComplexControl(QStyle::CC_ComboBox, &styleOption, &painter);
+ }
}
}
else if (type == CTRL_LISTNODE)
@@ -481,33 +513,11 @@ BOOL KDESalGraphics::drawNativeControl( ControlType type, ControlPart part,
}
else if (type == CTRL_FRAME)
{
- #if ( QT_VERSION >= QT_VERSION_CHECK( 4, 5, 0 ) )
- QStyleOptionFrameV3 styleOption;
- #else
- QStyleOptionFrameV2 styleOption;
- #endif
- styleOption.rect = QRect(0, 0, widgetRect.width(), widgetRect.height());
- styleOption.state = vclStateValue2StateFlag( nControlState, value );
- #if ( QT_VERSION >= QT_VERSION_CHECK( 4, 5, 0 ) )
- styleOption.frameShape = QFrame::StyledPanel;
- #endif
-
- kapp->style()->drawPrimitive(QStyle::PE_FrameWindow, &styleOption, &painter);
+ lcl_drawFrame( widgetRect, painter, QStyle::PE_Frame, nControlState, value );
}
else if (type == CTRL_FIXEDBORDER)
{
- #if ( QT_VERSION >= QT_VERSION_CHECK( 4, 5, 0 ) )
- QStyleOptionFrameV3 styleOption;
- #else
- QStyleOptionFrameV2 styleOption;
- #endif
- styleOption.rect = QRect(0, 0, widgetRect.width(), widgetRect.height());
- styleOption.state = vclStateValue2StateFlag( nControlState, value );
- #if ( QT_VERSION >= QT_VERSION_CHECK( 4, 5, 0 ) )
- styleOption.frameShape = QFrame::StyledPanel;
- #endif
-
- kapp->style()->drawPrimitive(QStyle::PE_FrameWindow, &styleOption, &painter);
+ lcl_drawFrame( widgetRect, painter, QStyle::PE_FrameWindow, nControlState, value );
}
else if (type == CTRL_WINDOW_BACKGROUND)
{
@@ -573,14 +583,21 @@ BOOL KDESalGraphics::getNativeControlRegion( ControlType type, ControlPart part,
break;
case CTRL_EDITBOX:
{
- styleOption.rect = QRect(0, 0, contentRect.width(), contentRect.height());
- styleOption.state = vclStateValue2StateFlag(controlState, val);
-
- int size = kapp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin) - 1;
-
- contentRect.adjust( -size, -size, size, size);
- boundingRect = contentRect;
-
+ int nFontHeight = kapp->fontMetrics().height();
+ //int nFrameSize = kapp->style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ int nLayoutTop = kapp->style()->pixelMetric(QStyle::PM_LayoutTopMargin);
+ int nLayoutBottom = kapp->style()->pixelMetric(QStyle::PM_LayoutBottomMargin);
+ int nLayoutLeft = kapp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin);
+ int nLayoutRight = kapp->style()->pixelMetric(QStyle::PM_LayoutRightMargin);
+
+ int nMinHeight = (nFontHeight + nLayoutTop + nLayoutBottom);
+ if( boundingRect.height() < nMinHeight )
+ {
+ int delta = nMinHeight - boundingRect.height();
+ boundingRect.adjust( 0, 0, 0, delta );
+ }
+ contentRect = boundingRect;
+ contentRect.adjust( -nLayoutLeft+1, -nLayoutTop+1, nLayoutRight-1, nLayoutBottom-1 );
retVal = true;
break;
@@ -621,7 +638,6 @@ BOOL KDESalGraphics::getNativeControlRegion( ControlType type, ControlPart part,
case PART_ENTIRE_CONTROL:
{
int size = kapp->style()->pixelMetric(QStyle::PM_ComboBoxFrameWidth) - 2;
- contentRect.adjust(-size,-size,size,size);
// find out the minimum size that should be used
// assume contents is a text ling
@@ -632,6 +648,11 @@ BOOL KDESalGraphics::getNativeControlRegion( ControlType type, ControlPart part,
if( aMinSize.height() > contentRect.height() )
contentRect.adjust( 0, 0, 0, aMinSize.height() - contentRect.height() );
boundingRect = contentRect;
+ // FIXME: why this difference between comboboxes and listboxes ?
+ // because a combobox has a sub edit and that is positioned
+ // inside the outer bordered control ?
+ if( type == CTRL_COMBOBOX )
+ contentRect.adjust(-size,-size,size,size);
retVal = true;
break;
}
@@ -647,6 +668,9 @@ BOOL KDESalGraphics::getNativeControlRegion( ControlType type, ControlPart part,
retVal = true;
break;
+ case PART_WINDOW:
+ retVal = true;
+ break;
}
break;
}
@@ -703,14 +727,19 @@ BOOL KDESalGraphics::getNativeControlRegion( ControlType type, ControlPart part,
break;
case CTRL_FRAME:
{
- if (part == PART_BORDER)
+ if( part == PART_BORDER )
{
- int size = kapp->style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
- //contentRect.adjust(size, size, size, size);
- boundingRect.adjust(-size, -size, size, size);
+ int size = kapp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin);
+ USHORT nStyle = val.getNumericVal();
+ if( nStyle & FRAME_DRAW_NODRAW )
+ {
+ // in this case the question is: how thick would a frame be
+ // see brdwin.cxx, decoview.cxx
+ // most probably the behavior in decoview.cxx is wrong.
+ contentRect.adjust(size, size, -size, -size);
+ }
retVal = true;
}
-
break;
}
case CTRL_RADIOBUTTON:
diff --git a/vcl/unx/kde4/main.cxx b/vcl/unx/kde4/main.cxx
index 2a48624d9d14..798990c06466 100644
--- a/vcl/unx/kde4/main.cxx
+++ b/vcl/unx/kde4/main.cxx
@@ -45,6 +45,16 @@
extern "C" {
VCL_DLLPUBLIC SalInstance* create_SalInstance( oslModule )
{
+ /* #i92121# workaround deadlocks in the X11 implementation
+ */
+ static const char* pNoXInitThreads = getenv( "SAL_NO_XINITTHREADS" );
+ /* #i90094#
+ from now on we know that an X connection will be
+ established, so protect X against itself
+ */
+ if( ! ( pNoXInitThreads && *pNoXInitThreads ) )
+ XInitThreads();
+
#if QT_VERSION < 0x050000
// Qt 4.x support needs >= 4.1.0
rtl::OString aVersion( qVersion() );
diff --git a/vcl/unx/source/app/salinst.cxx b/vcl/unx/source/app/salinst.cxx
index c160ea4c2fa5..d84b7fa5df6d 100644
--- a/vcl/unx/source/app/salinst.cxx
+++ b/vcl/unx/source/app/salinst.cxx
@@ -103,6 +103,16 @@ extern "C"
{
VCL_DLLPUBLIC SalInstance* create_SalInstance()
{
+ /* #i92121# workaround deadlocks in the X11 implementation
+ */
+ static const char* pNoXInitThreads = getenv( "SAL_NO_XINITTHREADS" );
+ /* #i90094#
+ from now on we know that an X connection will be
+ established, so protect X against itself
+ */
+ if( ! ( pNoXInitThreads && *pNoXInitThreads ) )
+ XInitThreads();
+
X11SalInstance* pInstance = new X11SalInstance( new SalYieldMutex() );
// initialize SalData
diff --git a/vcl/unx/source/app/sm.cxx b/vcl/unx/source/app/sm.cxx
index 7e4e16579623..ff981b04259b 100644
--- a/vcl/unx/source/app/sm.cxx
+++ b/vcl/unx/source/app/sm.cxx
@@ -48,6 +48,7 @@
#include <saldisp.hxx>
#include <salframe.h>
#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
#include <salinst.h>
#include <osl/conditn.h>
@@ -187,6 +188,7 @@ bool SessionManagerClient::bDocSaveDone = false;
static SmProp* pSmProps = NULL;
static SmProp** ppSmProps = NULL;
static int nSmProps = 0;
+static unsigned char *pSmRestartHint = NULL;
static void BuildSmPropertyList()
@@ -195,7 +197,7 @@ static void BuildSmPropertyList()
{
ByteString aExec( SessionManagerClient::getExecName(), osl_getThreadTextEncoding() );
- nSmProps = 4;
+ nSmProps = 5;
pSmProps = new SmProp[ nSmProps ];
pSmProps[ 0 ].name = const_cast<char*>(SmCloneCommand);
@@ -243,6 +245,15 @@ static void BuildSmPropertyList()
pSmProps[ 3 ].vals->value = strdup( aUser.getStr() );
pSmProps[ 3 ].vals->length = strlen( (char *)pSmProps[ 3 ].vals->value )+1;
+ pSmProps[ 4 ].name = const_cast<char*>(SmRestartStyleHint);
+ pSmProps[ 4 ].type = const_cast<char*>(SmCARD8);
+ pSmProps[ 4 ].num_vals = 1;
+ pSmProps[ 4 ].vals = new SmPropValue;
+ pSmProps[ 4 ].vals->value = malloc(1);
+ pSmRestartHint = (unsigned char *)pSmProps[ 4 ].vals->value;
+ *pSmRestartHint = SmRestartIfRunning;
+ pSmProps[ 4 ].vals->length = 1;
+
ppSmProps = new SmProp*[ nSmProps ];
for( int i = 0; i < nSmProps; i++ )
ppSmProps[ i ] = &pSmProps[i];
@@ -257,6 +268,31 @@ bool SessionManagerClient::checkDocumentsSaved()
IMPL_STATIC_LINK( SessionManagerClient, SaveYourselfHdl, void*, EMPTYARG )
{
SMprintf( "posting save documents event shutdown = %s\n", (pThis!=0) ? "true" : "false" );
+
+ static bool bFirstShutdown=true;
+ if (pThis != 0 && bFirstShutdown) //first shutdown request
+ {
+ bFirstShutdown = false;
+ /*
+ If we have no actual frames open, e.g. we launched a quickstarter,
+ and then shutdown all our frames leaving just a quickstarter running,
+ then we don't want to launch an empty toplevel frame on the next
+ start. (The job of scheduling the restart of the quick-starter is a
+ task of the quick-starter)
+ */
+ *pSmRestartHint = SmRestartNever;
+ const std::list< SalFrame* >& rFrames = GetX11SalData()->GetDisplay()->getFrames();
+ for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
+ {
+ Window *pWindow = (*it)->GetWindow();
+ if (pWindow && pWindow->IsVisible())
+ {
+ *pSmRestartHint = SmRestartIfRunning;
+ break;
+ }
+ }
+ }
+
if( pOneInstance )
{
SalSessionSaveRequestEvent aEvent( pThis != 0, false );
@@ -385,7 +421,7 @@ void SessionManagerClient::saveDone()
ICEConnectionObserver::lock();
SmcSetProperties( aSmcConnection, nSmProps, ppSmProps );
SmcSaveYourselfDone( aSmcConnection, True );
- SMprintf( "sent SaveYourselfDone\n" );
+ SMprintf( "sent SaveYourselfDone SmRestartHint of %d\n", *pSmRestartHint );
bDocSaveDone = true;
ICEConnectionObserver::unlock();
}
diff --git a/vcl/unx/source/desktopdetect/desktopdetector.cxx b/vcl/unx/source/desktopdetect/desktopdetector.cxx
new file mode 100644
index 000000000000..07fb18fa8344
--- /dev/null
+++ b/vcl/unx/source/desktopdetect/desktopdetector.cxx
@@ -0,0 +1,346 @@
+/*************************************************************************
+ *
+ * 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: salplug.cxx,v $
+ * $Revision: 1.30 $
+ *
+ * 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 <svunx.h>
+#include <tools/prex.h>
+#include <X11/Xatom.h>
+#include <tools/postx.h>
+
+#include "vcl/dllapi.h"
+
+#include "rtl/ustrbuf.hxx"
+#include "osl/module.h"
+#include "osl/process.h"
+#include "osl/thread.h"
+
+#include <unistd.h>
+
+using namespace rtl;
+
+enum {
+ DESKTOP_NONE = 0,
+ DESKTOP_UNKNOWN,
+ DESKTOP_GNOME,
+ DESKTOP_KDE,
+ DESKTOP_KDE4,
+ DESKTOP_CDE
+};
+
+static const char * desktop_strings[] = { "none", "unknown", "GNOME", "KDE", "KDE4", "CDE" };
+
+static bool is_gnome_desktop( Display* pDisplay )
+{
+ bool ret = false;
+
+ // warning: these checks are coincidental, GNOME does not
+ // explicitly advertise itself
+
+ if ( NULL != getenv( "GNOME_DESKTOP_SESSION_ID" ) )
+ ret = true;
+
+ if( ! ret )
+ {
+ Atom nAtom1 = XInternAtom( pDisplay, "GNOME_SM_PROXY", True );
+ Atom nAtom2 = XInternAtom( pDisplay, "NAUTILUS_DESKTOP_WINDOW_ID", True );
+ if( nAtom1 || nAtom2 )
+ {
+ int nProperties = 0;
+ Atom* pProperties = XListProperties( pDisplay, DefaultRootWindow( pDisplay ), &nProperties );
+ if( pProperties && nProperties )
+ {
+ for( int i = 0; i < nProperties; i++ )
+ if( pProperties[ i ] == nAtom1 ||
+ pProperties[ i ] == nAtom2 )
+ {
+ ret = true;
+ }
+ XFree( pProperties );
+ }
+ }
+ }
+
+ if( ! ret )
+ {
+ Atom nUTFAtom = XInternAtom( pDisplay, "UTF8_STRING", True );
+ Atom nNetWMNameAtom = XInternAtom( pDisplay, "_NET_WM_NAME", True );
+ if( nUTFAtom && nNetWMNameAtom )
+ {
+ // another, more expensive check: search for a gnome-panel
+ XLIB_Window aRoot, aParent, *pChildren = NULL;
+ unsigned int nChildren = 0;
+ XQueryTree( pDisplay, DefaultRootWindow( pDisplay ),
+ &aRoot, &aParent, &pChildren, &nChildren );
+ if( pChildren && nChildren )
+ {
+ for( unsigned int i = 0; i < nChildren && ! ret; i++ )
+ {
+ Atom nType = None;
+ int nFormat = 0;
+ unsigned long nItems = 0, nBytes = 0;
+ unsigned char* pProp = NULL;
+ XGetWindowProperty( pDisplay,
+ pChildren[i],
+ nNetWMNameAtom,
+ 0, 8,
+ False,
+ nUTFAtom,
+ &nType,
+ &nFormat,
+ &nItems,
+ &nBytes,
+ &pProp );
+ if( pProp && nType == nUTFAtom )
+ {
+ OString aWMName( (sal_Char*)pProp );
+ if( aWMName.equalsIgnoreAsciiCase( "gnome-panel" ) )
+ ret = true;
+ }
+ if( pProp )
+ XFree( pProp );
+ }
+ XFree( pChildren );
+ }
+ }
+ }
+
+ return ret;
+}
+
+static bool bWasXError = false;
+
+static inline bool WasXError()
+{
+ bool bRet = bWasXError;
+ bWasXError = false;
+ return bRet;
+}
+
+extern "C"
+{
+ static int autodect_error_handler( Display*, XErrorEvent* )
+ {
+ bWasXError = true;
+ return 0;
+ }
+
+ typedef int(* XErrorHandler)(Display*,XErrorEvent*);
+}
+
+static int KDEVersion( Display* pDisplay )
+{
+ int nRet = 0;
+
+ Atom nFullSession = XInternAtom( pDisplay, "KDE_FULL_SESSION", True );
+ Atom nKDEVersion = XInternAtom( pDisplay, "KDE_SESSION_VERSION", True );
+
+ if( nFullSession )
+ {
+ if( !nKDEVersion )
+ return 3;
+
+ Atom aRealType = None;
+ int nFormat = 8;
+ unsigned long nItems = 0;
+ unsigned long nBytesLeft = 0;
+ unsigned char* pProperty = NULL;
+ XGetWindowProperty( pDisplay,
+ DefaultRootWindow( pDisplay ),
+ nKDEVersion,
+ 0, 1,
+ False,
+ AnyPropertyType,
+ &aRealType,
+ &nFormat,
+ &nItems,
+ &nBytesLeft,
+ &pProperty );
+ if( !WasXError() && nItems != 0 && pProperty )
+ {
+ nRet = *reinterpret_cast< sal_Int32* >( pProperty );
+ }
+ if( pProperty )
+ {
+ XFree( pProperty );
+ pProperty = NULL;
+ }
+ }
+ return nRet;
+}
+
+static bool is_kde_desktop( Display* pDisplay )
+{
+ if ( NULL != getenv( "KDE_FULL_SESSION" ) )
+ {
+ const char *pVer = getenv( "KDE_SESSION_VERSION" );
+ if ( !pVer || pVer[0] == '0' )
+ {
+ return true; // does not exist => KDE3
+ }
+
+ rtl::OUString aVer( RTL_CONSTASCII_USTRINGPARAM( "3" ) );
+ if ( aVer.equalsIgnoreAsciiCaseAscii( pVer ) )
+ {
+ return true;
+ }
+ }
+
+ if ( KDEVersion( pDisplay ) == 3 )
+ return true;
+
+ return false;
+}
+
+static bool is_kde4_desktop( Display* pDisplay )
+{
+ if ( NULL != getenv( "KDE_FULL_SESSION" ) )
+ {
+ rtl::OUString aVer( RTL_CONSTASCII_USTRINGPARAM( "4" ) );
+
+ const char *pVer = getenv( "KDE_SESSION_VERSION" );
+ if ( pVer && aVer.equalsIgnoreAsciiCaseAscii( pVer ) )
+ return true;
+ }
+
+ if ( KDEVersion( pDisplay ) == 4 )
+ return true;
+
+ return false;
+}
+
+static bool is_cde_desktop( Display* pDisplay )
+{
+ void* pLibrary = NULL;
+
+ Atom nDtAtom = XInternAtom( pDisplay, "_DT_WM_READY", True );
+ OUString aPathName( RTL_CONSTASCII_USTRINGPARAM( "file:///usr/dt/lib/libDtSvc.so" ) );
+ if( nDtAtom && ( pLibrary = osl_loadModule( aPathName.pData, SAL_LOADMODULE_DEFAULT ) ) )
+ {
+ osl_unloadModule( (oslModule)pLibrary );
+ return true;
+ }
+
+ return false;
+}
+
+
+extern "C"
+{
+
+VCL_DLLPUBLIC rtl::OUString get_desktop_environment()
+{
+ rtl::OUStringBuffer aRet( 8 );
+ static const char *pOverride = getenv( "OOO_FORCE_DESKTOP" );
+
+ if ( pOverride && *pOverride )
+ {
+ OString aOver( pOverride );
+
+ if ( aOver.equalsIgnoreAsciiCase( "cde" ) )
+ aRet.appendAscii( desktop_strings[DESKTOP_CDE] );
+ if ( aOver.equalsIgnoreAsciiCase( "kde4" ) )
+ aRet.appendAscii( desktop_strings[DESKTOP_KDE4] );
+ if ( aOver.equalsIgnoreAsciiCase( "gnome" ) )
+ aRet.appendAscii( desktop_strings[DESKTOP_GNOME] );
+ if ( aOver.equalsIgnoreAsciiCase( "kde" ) )
+ aRet.appendAscii( desktop_strings[DESKTOP_KDE] );
+ if ( aOver.equalsIgnoreAsciiCase( "none" ) )
+ aRet.appendAscii( desktop_strings[DESKTOP_UNKNOWN] );
+ }
+
+ if( aRet.getLength() == 0 )
+ {
+ // get display to connect to
+ const char* pDisplayStr = getenv( "DISPLAY" );
+ int nParams = osl_getCommandArgCount();
+ OUString aParam;
+ OString aBParm;
+ for( int i = 0; i < nParams; i++ )
+ {
+ osl_getCommandArg( i, &aParam.pData );
+ if( aParam.equalsAscii( "-headless" ) )
+ {
+ pDisplayStr = NULL;
+ break;
+ }
+ if( i < nParams-1 && (aParam.equalsAscii( "-display" ) || aParam.equalsAscii( "--display" )) )
+ {
+ osl_getCommandArg( i+1, &aParam.pData );
+ aBParm = OUStringToOString( aParam, osl_getThreadTextEncoding() );
+ pDisplayStr = aBParm.getStr();
+ break;
+ }
+ }
+
+ // no server at all
+ if( ! pDisplayStr || !*pDisplayStr )
+ aRet.appendAscii( desktop_strings[DESKTOP_NONE] );
+ else
+ {
+ /* #i92121# workaround deadlocks in the X11 implementation
+ */
+ static const char* pNoXInitThreads = getenv( "SAL_NO_XINITTHREADS" );
+ /* #i90094#
+ from now on we know that an X connection will be
+ established, so protect X against itself
+ */
+ if( ! ( pNoXInitThreads && *pNoXInitThreads ) )
+ XInitThreads();
+
+ Display* pDisplay = XOpenDisplay( pDisplayStr );
+ if( pDisplay )
+ {
+ XErrorHandler pOldHdl = XSetErrorHandler( autodect_error_handler );
+
+ if ( is_kde4_desktop( pDisplay ) )
+ aRet.appendAscii( desktop_strings[DESKTOP_KDE4] );
+ else if ( is_gnome_desktop( pDisplay ) )
+ aRet.appendAscii( desktop_strings[DESKTOP_GNOME] );
+ else if ( is_cde_desktop( pDisplay ) )
+ aRet.appendAscii( desktop_strings[DESKTOP_CDE] );
+ else if ( is_kde_desktop( pDisplay ) )
+ aRet.appendAscii( desktop_strings[DESKTOP_KDE] );
+ else
+ aRet.appendAscii( desktop_strings[DESKTOP_UNKNOWN] );
+
+ // set the default handler again
+ XSetErrorHandler( pOldHdl );
+
+ XCloseDisplay( pDisplay );
+ }
+ }
+ }
+
+ return aRet.makeStringAndClear();
+}
+
+}
diff --git a/vcl/unx/source/desktopdetect/makefile.mk b/vcl/unx/source/desktopdetect/makefile.mk
new file mode 100644
index 000000000000..cc845ee34887
--- /dev/null
+++ b/vcl/unx/source/desktopdetect/makefile.mk
@@ -0,0 +1,61 @@
+#*************************************************************************
+#
+# 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.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.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=vcl
+TARGET=dtdetect
+
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile2.pmk
+
+# --- Files --------------------------------------------------------
+
+.IF "$(GUIBASE)"!="unx"
+
+dummy:
+ @echo "Nothing to build for GUIBASE $(GUIBASE)"
+
+.ELSE # "$(GUIBASE)"!="unx"
+
+SLOFILES=$(SLO)$/desktopdetector.obj
+
+.ENDIF # "$(GUIBASE)"!="unx"
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+.INCLUDE : $(PRJ)$/util$/target.pmk
diff --git a/vcl/unx/source/dtrans/X11_clipboard.cxx b/vcl/unx/source/dtrans/X11_clipboard.cxx
new file mode 100644
index 000000000000..0a47076f0d09
--- /dev/null
+++ b/vcl/unx/source/dtrans/X11_clipboard.cxx
@@ -0,0 +1,296 @@
+/*************************************************************************
+ *
+ * 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: X11_clipboard.cxx,v $
+ * $Revision: 1.17 $
+ *
+ * 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 <X11/Xatom.h>
+#include <X11_clipboard.hxx>
+#include <X11_transferable.hxx>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/datatransfer/clipboard/RenderingCapabilities.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/registry/XRegistryKey.hpp>
+#include <uno/dispatcher.h> // declaration of generic uno interface
+#include <uno/mapping.hxx> // mapping stuff
+#include <cppuhelper/factory.hxx>
+#include <rtl/tencinfo.h>
+
+#if OSL_DEBUG_LEVEL > 1
+#include <stdio.h>
+#endif
+
+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 com::sun::star::awt;
+using namespace cppu;
+using namespace osl;
+using namespace rtl;
+using namespace x11;
+
+X11Clipboard::X11Clipboard( SelectionManager& rManager, Atom aSelection ) :
+ ::cppu::WeakComponentImplHelper4<
+ ::com::sun::star::datatransfer::clipboard::XClipboardEx,
+ ::com::sun::star::datatransfer::clipboard::XClipboardNotifier,
+ ::com::sun::star::lang::XServiceInfo,
+ ::com::sun::star::lang::XInitialization
+ >( rManager.getMutex() ),
+
+ m_rSelectionManager( rManager ),
+ m_xSelectionManager( & rManager ),
+ m_aSelection( aSelection )
+{
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "creating instance of X11Clipboard (this=%p)\n", this );
+#endif
+
+ if( m_aSelection != None )
+ {
+ m_rSelectionManager.registerHandler( m_aSelection, *this );
+ }
+ else
+ {
+ m_rSelectionManager.registerHandler( XA_PRIMARY, *this );
+ m_rSelectionManager.registerHandler( m_rSelectionManager.getAtom( OUString::createFromAscii( "CLIPBOARD" ) ), *this );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+X11Clipboard::~X11Clipboard()
+{
+ MutexGuard aGuard( *Mutex::getGlobalMutex() );
+
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "shutting down instance of X11Clipboard (this=%p, Selecttion=\"%s\")\n", this, OUStringToOString( m_rSelectionManager.getString( m_aSelection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
+#endif
+ if( m_aSelection != None )
+ m_rSelectionManager.deregisterHandler( m_aSelection );
+ else
+ {
+ m_rSelectionManager.deregisterHandler( XA_PRIMARY );
+ m_rSelectionManager.deregisterHandler( m_rSelectionManager.getAtom( OUString::createFromAscii( "CLIPBOARD" ) ) );
+ }
+}
+
+
+// ------------------------------------------------------------------------
+
+void X11Clipboard::fireChangedContentsEvent()
+{
+ ClearableMutexGuard aGuard( m_rSelectionManager.getMutex() );
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "X11Clipboard::fireChangedContentsEvent for %s (%d listeners)\n",
+ OUStringToOString( m_rSelectionManager.getString( m_aSelection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(), m_aListeners.size() );
+#endif
+ ::std::list< Reference< XClipboardListener > > listeners( m_aListeners );
+ aGuard.clear();
+
+ ClipboardEvent aEvent( static_cast<OWeakObject*>(this), m_aContents);
+ while( listeners.begin() != listeners.end() )
+ {
+ if( listeners.front().is() )
+ listeners.front()->changedContents(aEvent);
+ listeners.pop_front();
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void X11Clipboard::clearContents()
+{
+ ClearableMutexGuard aGuard(m_rSelectionManager.getMutex());
+ // protect against deletion during outside call
+ Reference< XClipboard > xThis( static_cast<XClipboard*>(this));
+ // copy member references on stack so they can be called
+ // without having the mutex
+ Reference< XClipboardOwner > xOwner( m_aOwner );
+ Reference< XTransferable > xTrans( m_aContents );
+ // clear members
+ m_aOwner.clear();
+ m_aContents.clear();
+
+ // release the mutex
+ aGuard.clear();
+
+ // inform previous owner of lost ownership
+ if ( xOwner.is() )
+ xOwner->lostOwnership(xThis, m_aContents);
+}
+
+// ------------------------------------------------------------------------
+
+Reference< XTransferable > SAL_CALL X11Clipboard::getContents()
+ throw(RuntimeException)
+{
+ MutexGuard aGuard(m_rSelectionManager.getMutex());
+
+ if( ! m_aContents.is() )
+ m_aContents = new X11Transferable( SelectionManager::get(), static_cast< OWeakObject* >(this), m_aSelection );
+ return m_aContents;
+}
+
+// ------------------------------------------------------------------------
+
+void SAL_CALL X11Clipboard::setContents(
+ const Reference< XTransferable >& xTrans,
+ const Reference< XClipboardOwner >& xClipboardOwner )
+ throw(RuntimeException)
+{
+ // remember old values for callbacks before setting the new ones.
+ ClearableMutexGuard aGuard(m_rSelectionManager.getMutex());
+
+ Reference< XClipboardOwner > oldOwner( m_aOwner );
+ m_aOwner = xClipboardOwner;
+
+ Reference< XTransferable > oldContents( m_aContents );
+ m_aContents = xTrans;
+
+ aGuard.clear();
+
+ // for now request ownership for both selections
+ if( m_aSelection != None )
+ m_rSelectionManager.requestOwnership( m_aSelection );
+ else
+ {
+ m_rSelectionManager.requestOwnership( XA_PRIMARY );
+ m_rSelectionManager.requestOwnership( m_rSelectionManager.getAtom( OUString::createFromAscii( "CLIPBOARD" ) ) );
+ }
+
+ // notify old owner on loss of ownership
+ if( oldOwner.is() )
+ oldOwner->lostOwnership(static_cast < XClipboard * > (this), oldContents);
+
+ // notify all listeners on content changes
+ fireChangedContentsEvent();
+}
+
+// ------------------------------------------------------------------------
+
+OUString SAL_CALL X11Clipboard::getName()
+ throw(RuntimeException)
+{
+ return m_rSelectionManager.getString( m_aSelection );
+}
+
+// ------------------------------------------------------------------------
+
+sal_Int8 SAL_CALL X11Clipboard::getRenderingCapabilities()
+ throw(RuntimeException)
+{
+ return RenderingCapabilities::Delayed;
+}
+
+
+// ------------------------------------------------------------------------
+void SAL_CALL X11Clipboard::addClipboardListener( const Reference< XClipboardListener >& listener )
+ throw(RuntimeException)
+{
+ MutexGuard aGuard( m_rSelectionManager.getMutex() );
+ m_aListeners.push_back( listener );
+}
+
+// ------------------------------------------------------------------------
+
+void SAL_CALL X11Clipboard::removeClipboardListener( const Reference< XClipboardListener >& listener )
+ throw(RuntimeException)
+{
+ MutexGuard aGuard( m_rSelectionManager.getMutex() );
+ m_aListeners.remove( listener );
+}
+
+
+// ------------------------------------------------------------------------
+
+Reference< XTransferable > X11Clipboard::getTransferable()
+{
+ return getContents();
+}
+
+// ------------------------------------------------------------------------
+
+void X11Clipboard::clearTransferable()
+{
+ clearContents();
+}
+
+// ------------------------------------------------------------------------
+
+void X11Clipboard::fireContentsChanged()
+{
+ fireChangedContentsEvent();
+}
+
+// ------------------------------------------------------------------------
+
+Reference< XInterface > X11Clipboard::getReference() throw()
+{
+ return Reference< XInterface >( static_cast< OWeakObject* >(this) );
+}
+
+// ------------------------------------------------------------------------
+
+OUString SAL_CALL X11Clipboard::getImplementationName( )
+ throw(RuntimeException)
+{
+ return OUString::createFromAscii(X11_CLIPBOARD_IMPLEMENTATION_NAME);
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool SAL_CALL X11Clipboard::supportsService( const OUString& ServiceName )
+ throw(RuntimeException)
+{
+ Sequence < OUString > SupportedServicesNames = X11Clipboard_getSupportedServiceNames();
+
+ for ( sal_Int32 n = SupportedServicesNames.getLength(); n--; )
+ if (SupportedServicesNames[n].compareTo(ServiceName) == 0)
+ return sal_True;
+
+ return sal_False;
+}
+
+// ------------------------------------------------------------------------
+
+void SAL_CALL X11Clipboard::initialize( const Sequence< Any >& ) throw( ::com::sun::star::uno::Exception )
+{
+}
+
+// ------------------------------------------------------------------------
+
+Sequence< OUString > SAL_CALL X11Clipboard::getSupportedServiceNames( )
+ throw(RuntimeException)
+{
+ return X11Clipboard_getSupportedServiceNames();
+}
+
diff --git a/vcl/unx/source/dtrans/X11_clipboard.hxx b/vcl/unx/source/dtrans/X11_clipboard.hxx
new file mode 100644
index 000000000000..a12064df6cbd
--- /dev/null
+++ b/vcl/unx/source/dtrans/X11_clipboard.hxx
@@ -0,0 +1,154 @@
+/*************************************************************************
+ *
+ * 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: X11_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 _DTRANS_X11_CLIPBOARD_HXX_
+#define _DTRANS_X11_CLIPBOARD_HXX_
+
+#include <X11_selection.hxx>
+
+#ifndef _COM_SUN_STAR_DATATRANSFER_CLIPBAORD_XCLIPBOARDEX_HPP_
+#include <com/sun/star/datatransfer/clipboard/XClipboardEx.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_DATATRANSFER_CLIPBAORD_XCLIPBOARDNOTIFIER_HPP_
+#include <com/sun/star/datatransfer/clipboard/XClipboardNotifier.hpp>
+#endif
+#include <cppuhelper/compbase4.hxx>
+
+// ------------------------------------------------------------------------
+
+#define X11_CLIPBOARD_IMPLEMENTATION_NAME "com.sun.star.datatransfer.X11ClipboardSupport"
+
+namespace x11 {
+
+ class X11Clipboard :
+ public ::cppu::WeakComponentImplHelper4 <
+ ::com::sun::star::datatransfer::clipboard::XClipboardEx,
+ ::com::sun::star::datatransfer::clipboard::XClipboardNotifier,
+ ::com::sun::star::lang::XServiceInfo,
+ ::com::sun::star::lang::XInitialization
+ >,
+ public SelectionAdaptor
+ {
+ Reference< ::com::sun::star::datatransfer::XTransferable > m_aContents;
+ Reference< ::com::sun::star::datatransfer::clipboard::XClipboardOwner > m_aOwner;
+
+ SelectionManager& m_rSelectionManager;
+ Reference< ::com::sun::star::lang::XInitialization > m_xSelectionManager;
+ ::std::list< Reference< ::com::sun::star::datatransfer::clipboard::XClipboardListener > > m_aListeners;
+ Atom m_aSelection;
+
+ protected:
+
+
+ friend class SelectionManager;
+ friend class X11_Transferable;
+
+ void fireChangedContentsEvent();
+ void clearContents();
+
+ public:
+
+ X11Clipboard( SelectionManager& rManager, Atom aSelection );
+ virtual ~X11Clipboard();
+
+ static X11Clipboard* get( const ::rtl::OUString& rDisplayName, Atom aSelection );
+
+ /*
+ * XInitialization
+ */
+ virtual void SAL_CALL initialize( const Sequence< Any >& arguments ) throw( ::com::sun::star::uno::Exception );
+
+ /*
+ * XServiceInfo
+ */
+
+ virtual ::rtl::OUString SAL_CALL getImplementationName( )
+ throw(RuntimeException);
+
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName )
+ throw(RuntimeException);
+
+ virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( )
+ throw(RuntimeException);
+
+ /*
+ * XClipboard
+ */
+
+ virtual Reference< ::com::sun::star::datatransfer::XTransferable > SAL_CALL getContents()
+ throw(RuntimeException);
+
+ virtual void SAL_CALL setContents(
+ const Reference< ::com::sun::star::datatransfer::XTransferable >& xTrans,
+ const Reference< ::com::sun::star::datatransfer::clipboard::XClipboardOwner >& xClipboardOwner )
+ throw(RuntimeException);
+
+ virtual ::rtl::OUString SAL_CALL getName()
+ throw(RuntimeException);
+
+ /*
+ * XClipboardEx
+ */
+
+ virtual sal_Int8 SAL_CALL getRenderingCapabilities()
+ throw(RuntimeException);
+
+ /*
+ * XClipboardNotifier
+ */
+ virtual void SAL_CALL addClipboardListener(
+ const Reference< ::com::sun::star::datatransfer::clipboard::XClipboardListener >& listener )
+ throw(RuntimeException);
+
+ virtual void SAL_CALL removeClipboardListener(
+ const Reference< ::com::sun::star::datatransfer::clipboard::XClipboardListener >& listener )
+ throw(RuntimeException);
+
+ /*
+ * SelectionAdaptor
+ */
+ virtual Reference< ::com::sun::star::datatransfer::XTransferable > getTransferable();
+ virtual void clearTransferable();
+ virtual void fireContentsChanged();
+ virtual Reference< XInterface > getReference() throw();
+ };
+
+// ------------------------------------------------------------------------
+
+ Sequence< ::rtl::OUString > SAL_CALL X11Clipboard_getSupportedServiceNames();
+ Reference< XInterface > SAL_CALL X11Clipboard_createInstance(
+ const Reference< ::com::sun::star::lang::XMultiServiceFactory > & xMultiServiceFactory);
+
+// ------------------------------------------------------------------------
+
+} // namepspace
+
+#endif
diff --git a/vcl/unx/source/dtrans/X11_dndcontext.cxx b/vcl/unx/source/dtrans/X11_dndcontext.cxx
new file mode 100644
index 000000000000..59832c27c2a7
--- /dev/null
+++ b/vcl/unx/source/dtrans/X11_dndcontext.cxx
@@ -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: X11_dndcontext.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 <X11_dndcontext.hxx>
+#include <X11_selection.hxx>
+
+using namespace cppu;
+using namespace x11;
+
+/*
+ * DropTargetDropContext
+ */
+
+DropTargetDropContext::DropTargetDropContext(
+ Window aDropWindow,
+ Time aTimestamp,
+ SelectionManager& rManager ) :
+ m_aDropWindow( aDropWindow ),
+ m_nTimestamp( aTimestamp ),
+ m_rManager( rManager ),
+ m_xManagerRef( static_cast< OWeakObject* >(&rManager) )
+{
+}
+
+DropTargetDropContext::~DropTargetDropContext()
+{
+}
+
+void DropTargetDropContext::acceptDrop( sal_Int8 dragOperation ) throw()
+{
+ m_rManager.accept( dragOperation, m_aDropWindow, m_nTimestamp );
+}
+
+void DropTargetDropContext::rejectDrop() throw()
+{
+ m_rManager.reject( m_aDropWindow, m_nTimestamp );
+}
+
+void DropTargetDropContext::dropComplete( sal_Bool success ) throw()
+{
+ m_rManager.dropComplete( success, m_aDropWindow, m_nTimestamp );
+}
+
+
+/*
+ * DropTargetDragContext
+ */
+
+DropTargetDragContext::DropTargetDragContext(
+ Window aDropWindow,
+ Time aTimestamp,
+ SelectionManager& rManager ) :
+ m_aDropWindow( aDropWindow ),
+ m_nTimestamp( aTimestamp ),
+ m_rManager( rManager ),
+ m_xManagerRef( static_cast< OWeakObject* >(&rManager) )
+{
+}
+
+DropTargetDragContext::~DropTargetDragContext()
+{
+}
+
+void DropTargetDragContext::acceptDrag( sal_Int8 dragOperation ) throw()
+{
+ m_rManager.accept( dragOperation, m_aDropWindow, m_nTimestamp );
+}
+
+void DropTargetDragContext::rejectDrag() throw()
+{
+ m_rManager.reject( m_aDropWindow, m_nTimestamp );
+}
+
+/*
+ * DragSourceContext
+ */
+
+DragSourceContext::DragSourceContext(
+ Window aDropWindow,
+ Time aTimestamp,
+ SelectionManager& rManager ) :
+ m_aDropWindow( aDropWindow ),
+ m_nTimestamp( aTimestamp ),
+ m_rManager( rManager ),
+ m_xManagerRef( static_cast< OWeakObject* >(&rManager) )
+{
+}
+
+DragSourceContext::~DragSourceContext()
+{
+}
+
+sal_Int32 DragSourceContext::getCurrentCursor() throw()
+{
+ return m_rManager.getCurrentCursor();
+}
+
+void DragSourceContext::setCursor( sal_Int32 cursorId ) throw()
+{
+ m_rManager.setCursor( cursorId, m_aDropWindow, m_nTimestamp );
+}
+
+void DragSourceContext::setImage( sal_Int32 imageId ) throw()
+{
+ m_rManager.setImage( imageId, m_aDropWindow, m_nTimestamp );
+}
+
+void DragSourceContext::transferablesFlavorsChanged() throw()
+{
+ m_rManager.transferablesFlavorsChanged();
+}
diff --git a/vcl/unx/source/dtrans/X11_dndcontext.hxx b/vcl/unx/source/dtrans/X11_dndcontext.hxx
new file mode 100644
index 000000000000..f2ecb7b0841b
--- /dev/null
+++ b/vcl/unx/source/dtrans/X11_dndcontext.hxx
@@ -0,0 +1,105 @@
+/*************************************************************************
+ *
+ * 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: X11_dndcontext.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 _DTRANS_X11_DNDCONTEXT_HXX
+#define _DTRANS_X11_DNDCONTEXT_HXX
+
+#include <com/sun/star/datatransfer/dnd/XDragSourceContext.hpp>
+#include <com/sun/star/datatransfer/dnd/XDropTargetDropContext.hpp>
+#include <com/sun/star/datatransfer/dnd/XDropTargetDragContext.hpp>
+#include <cppuhelper/implbase1.hxx>
+
+#include <X11/Xlib.h>
+
+using namespace com::sun::star::uno;
+
+namespace x11 {
+
+ class SelectionManager;
+
+ class DropTargetDropContext :
+ public ::cppu::WeakImplHelper1<
+ ::com::sun::star::datatransfer::dnd::XDropTargetDropContext
+ >
+ {
+ Window m_aDropWindow;
+ Time m_nTimestamp;
+ SelectionManager& m_rManager;
+ Reference< XInterface > m_xManagerRef;
+ public:
+ DropTargetDropContext( Window, Time, SelectionManager& );
+ virtual ~DropTargetDropContext();
+
+ // XDropTargetDropContext
+ virtual void SAL_CALL acceptDrop( sal_Int8 dragOperation ) throw();
+ virtual void SAL_CALL rejectDrop() throw();
+ virtual void SAL_CALL dropComplete( sal_Bool success ) throw();
+ };
+
+ class DropTargetDragContext :
+ public ::cppu::WeakImplHelper1<
+ ::com::sun::star::datatransfer::dnd::XDropTargetDragContext
+ >
+ {
+ Window m_aDropWindow;
+ Time m_nTimestamp;
+ SelectionManager& m_rManager;
+ Reference< XInterface > m_xManagerRef;
+ public:
+ DropTargetDragContext( Window, Time, SelectionManager& );
+ virtual ~DropTargetDragContext();
+
+ // XDropTargetDragContext
+ virtual void SAL_CALL acceptDrag( sal_Int8 dragOperation ) throw();
+ virtual void SAL_CALL rejectDrag() throw();
+ };
+
+ class DragSourceContext :
+ public ::cppu::WeakImplHelper1<
+ ::com::sun::star::datatransfer::dnd::XDragSourceContext
+ >
+ {
+ Window m_aDropWindow;
+ Time m_nTimestamp;
+ SelectionManager& m_rManager;
+ Reference< XInterface > m_xManagerRef;
+ public:
+ DragSourceContext( Window, Time, SelectionManager& );
+ virtual ~DragSourceContext();
+
+ // XDragSourceContext
+ virtual sal_Int32 SAL_CALL getCurrentCursor() throw();
+ virtual void SAL_CALL setCursor( sal_Int32 cursorId ) throw();
+ virtual void SAL_CALL setImage( sal_Int32 imageId ) throw();
+ virtual void SAL_CALL transferablesFlavorsChanged() throw();
+ };
+} // namespace
+
+#endif // _DTRANS_X11_DNDCONTEXT_HXX
diff --git a/vcl/unx/source/dtrans/X11_droptarget.cxx b/vcl/unx/source/dtrans/X11_droptarget.cxx
new file mode 100644
index 000000000000..153514c668a0
--- /dev/null
+++ b/vcl/unx/source/dtrans/X11_droptarget.cxx
@@ -0,0 +1,231 @@
+/*************************************************************************
+ *
+ * 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: X11_droptarget.cxx,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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include <X11_selection.hxx>
+
+using namespace x11;
+using namespace rtl;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::awt;
+using namespace com::sun::star::datatransfer;
+using namespace com::sun::star::datatransfer::dnd;
+
+DropTarget::DropTarget() :
+ ::cppu::WeakComponentImplHelper3<
+ XDropTarget,
+ XInitialization,
+ XServiceInfo
+ >( m_aMutex ),
+ m_bActive( false ),
+ m_nDefaultActions( 0 ),
+ m_aTargetWindow( None ),
+ m_pSelectionManager( NULL )
+{
+}
+
+DropTarget::~DropTarget()
+{
+ if( m_pSelectionManager )
+ m_pSelectionManager->deregisterDropTarget( m_aTargetWindow );
+}
+
+// --------------------------------------------------------------------------
+
+void DropTarget::initialize( const Sequence< Any >& arguments ) throw( ::com::sun::star::uno::Exception )
+{
+ if( arguments.getLength() > 1 )
+ {
+ OUString aDisplayName;
+ Reference< XDisplayConnection > xConn;
+ arguments.getConstArray()[0] >>= xConn;
+ if( xConn.is() )
+ {
+ Any aIdentifier;
+ aIdentifier >>= aDisplayName;
+ }
+
+ m_pSelectionManager = &SelectionManager::get( aDisplayName );
+ m_xSelectionManager = static_cast< XDragSource* >(m_pSelectionManager);
+ m_pSelectionManager->initialize( arguments );
+
+ if( m_pSelectionManager->getDisplay() ) // #136582# sanity check
+ {
+ sal_Size aWindow = None;
+ arguments.getConstArray()[1] >>= aWindow;
+ m_pSelectionManager->registerDropTarget( aWindow, this );
+ m_aTargetWindow = aWindow;
+ m_bActive = true;
+ }
+ }
+}
+
+// --------------------------------------------------------------------------
+
+void DropTarget::addDropTargetListener( const Reference< XDropTargetListener >& xListener ) throw()
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );
+
+ m_aListeners.push_back( xListener );
+}
+
+// --------------------------------------------------------------------------
+
+void DropTarget::removeDropTargetListener( const Reference< XDropTargetListener >& xListener ) throw()
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );
+
+ m_aListeners.remove( xListener );
+}
+
+// --------------------------------------------------------------------------
+
+sal_Bool DropTarget::isActive() throw()
+{
+ return m_bActive;
+}
+
+// --------------------------------------------------------------------------
+
+void DropTarget::setActive( sal_Bool active ) throw()
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );
+
+ m_bActive = active;
+}
+
+// --------------------------------------------------------------------------
+
+sal_Int8 DropTarget::getDefaultActions() throw()
+{
+ return m_nDefaultActions;
+}
+
+// --------------------------------------------------------------------------
+
+void DropTarget::setDefaultActions( sal_Int8 actions ) throw()
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );
+
+ m_nDefaultActions = actions;
+}
+
+// --------------------------------------------------------------------------
+
+void DropTarget::drop( const DropTargetDropEvent& dtde ) throw()
+{
+ osl::ClearableGuard< ::osl::Mutex > aGuard( m_aMutex );
+ std::list< Reference< XDropTargetListener > > aListeners( m_aListeners );
+ aGuard.clear();
+
+ for( std::list< Reference< XDropTargetListener > >::iterator it = aListeners.begin(); it!= aListeners.end(); ++it )
+ {
+ (*it)->drop( dtde );
+ }
+}
+
+// --------------------------------------------------------------------------
+
+void DropTarget::dragEnter( const DropTargetDragEnterEvent& dtde ) throw()
+{
+ osl::ClearableGuard< ::osl::Mutex > aGuard( m_aMutex );
+ std::list< Reference< XDropTargetListener > > aListeners( m_aListeners );
+ aGuard.clear();
+
+ for( std::list< Reference< XDropTargetListener > >::iterator it = aListeners.begin(); it!= aListeners.end(); ++it )
+ {
+ (*it)->dragEnter( dtde );
+ }
+}
+
+// --------------------------------------------------------------------------
+
+void DropTarget::dragExit( const DropTargetEvent& dte ) throw()
+{
+ osl::ClearableGuard< ::osl::Mutex > aGuard( m_aMutex );
+ std::list< Reference< XDropTargetListener > > aListeners( m_aListeners );
+ aGuard.clear();
+
+ for( std::list< Reference< XDropTargetListener > >::iterator it = aListeners.begin(); it!= aListeners.end(); ++it )
+ {
+ (*it)->dragExit( dte );
+ }
+}
+
+// --------------------------------------------------------------------------
+
+void DropTarget::dragOver( const DropTargetDragEvent& dtde ) throw()
+{
+ osl::ClearableGuard< ::osl::Mutex > aGuard( m_aMutex );
+ std::list< Reference< XDropTargetListener > > aListeners( m_aListeners );
+ aGuard.clear();
+
+ for( std::list< Reference< XDropTargetListener > >::iterator it = aListeners.begin(); it!= aListeners.end(); ++it )
+ {
+ (*it)->dragOver( dtde );
+ }
+}
+
+// --------------------------------------------------------------------------
+
+/*
+ * XServiceInfo
+ */
+
+// ------------------------------------------------------------------------
+
+OUString DropTarget::getImplementationName() throw()
+{
+ return OUString::createFromAscii(XDND_DROPTARGET_IMPLEMENTATION_NAME);
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool DropTarget::supportsService( const OUString& ServiceName ) throw()
+{
+ Sequence < OUString > SupportedServicesNames = Xdnd_dropTarget_getSupportedServiceNames();
+
+ for ( sal_Int32 n = SupportedServicesNames.getLength(); n--; )
+ if (SupportedServicesNames[n].compareTo(ServiceName) == 0)
+ return sal_True;
+
+ return sal_False;
+}
+
+// ------------------------------------------------------------------------
+
+Sequence< OUString > DropTarget::getSupportedServiceNames() throw()
+{
+ return Xdnd_dropTarget_getSupportedServiceNames();
+}
+
+
diff --git a/vcl/unx/source/dtrans/X11_selection.cxx b/vcl/unx/source/dtrans/X11_selection.cxx
new file mode 100644
index 000000000000..3f7dfc2df709
--- /dev/null
+++ b/vcl/unx/source/dtrans/X11_selection.cxx
@@ -0,0 +1,4024 @@
+/*************************************************************************
+ *
+ * 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: X11_selection.cxx,v $
+ * $Revision: 1.85 $
+ *
+ * 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 <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include <X11/Xlib.h>
+#include <X11/X.h>
+#include <X11/Xutil.h>
+#if defined(LINUX) || defined(NETBSD) || defined (FREEBSD)
+#include <sys/poll.h>
+#else
+#include <poll.h>
+#endif
+#include <sal/alloca.h>
+
+#include <X11_selection.hxx>
+#include <X11_clipboard.hxx>
+#include <X11_transferable.hxx>
+#include <X11_dndcontext.hxx>
+#include <bmp.hxx>
+
+// pointer bitmaps
+#include <copydata_curs.h>
+#include <copydata_mask.h>
+#include <movedata_curs.h>
+#include <movedata_mask.h>
+#include <linkdata_curs.h>
+#include <linkdata_mask.h>
+#include <nodrop_curs.h>
+#include <nodrop_mask.h>
+#include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
+#include <com/sun/star/awt/MouseEvent.hpp>
+#include <com/sun/star/awt/MouseButton.hpp>
+#include <rtl/tencinfo.h>
+#ifndef OSL_PROCESS_H
+#include <osl/process.h>
+#endif
+
+#define DRAG_EVENT_MASK ButtonPressMask |\
+ ButtonReleaseMask |\
+ PointerMotionMask |\
+ EnterWindowMask |\
+ LeaveWindowMask
+
+using namespace com::sun::star::datatransfer;
+using namespace com::sun::star::datatransfer::dnd;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::awt;
+using namespace com::sun::star::uno;
+using namespace cppu;
+using namespace osl;
+using namespace rtl;
+
+using namespace x11;
+
+// stubs to satisfy solaris compiler's rather rigid linking warning
+extern "C"
+{
+ static void call_SelectionManager_run( void * pMgr )
+ {
+ SelectionManager::run( pMgr );
+ }
+
+ static void call_SelectionManager_runDragExecute( void * pMgr )
+ {
+ SelectionManager::runDragExecute( pMgr );
+ }
+}
+
+
+static const long nXdndProtocolRevision = 5;
+
+// mapping between mime types (or what the office thinks of mime types)
+// and X convention types
+struct NativeTypeEntry
+{
+ Atom nAtom;
+ const char* pType; // Mime encoding on our side
+ const char* pNativeType; // string corresponding to nAtom for the case of nAtom being uninitialized
+ int nFormat; // the corresponding format
+};
+
+// the convention for Xdnd is mime types as specified by the corresponding
+// RFC's with the addition that text/plain without charset tag contains iso8859-1
+// sadly some applications (e.g. gtk) do not honor the mimetype only rule,
+// so for compatibility add UTF8_STRING
+static NativeTypeEntry aXdndConversionTab[] =
+{
+ { 0, "text/plain;charset=iso8859-1", "text/plain", 8 },
+ { 0, "text/plain;charset=utf-8", "UTF8_STRING", 8 }
+};
+
+// for clipboard and primary selections there is only a convention for text
+// that the encoding name of the text is taken as type in all capitalized letters
+static NativeTypeEntry aNativeConversionTab[] =
+{
+ { 0, "text/plain;charset=utf-16", "ISO10646-1", 16 },
+ { 0, "text/plain;charset=utf-8", "UTF8_STRING", 8 },
+ { 0, "text/plain;charset=utf-8", "UTF-8", 8 },
+ { 0, "text/plain;charset=utf-8", "text/plain;charset=UTF-8", 8 },
+ // ISO encodings
+ { 0, "text/plain;charset=iso8859-2", "ISO8859-2", 8 },
+ { 0, "text/plain;charset=iso8859-3", "ISO8859-3", 8 },
+ { 0, "text/plain;charset=iso8859-4", "ISO8859-4", 8 },
+ { 0, "text/plain;charset=iso8859-5", "ISO8859-5", 8 },
+ { 0, "text/plain;charset=iso8859-6", "ISO8859-6", 8 },
+ { 0, "text/plain;charset=iso8859-7", "ISO8859-7", 8 },
+ { 0, "text/plain;charset=iso8859-8", "ISO8859-8", 8 },
+ { 0, "text/plain;charset=iso8859-9", "ISO8859-9", 8 },
+ { 0, "text/plain;charset=iso8859-10", "ISO8859-10", 8 },
+ { 0, "text/plain;charset=iso8859-13", "ISO8859-13", 8 },
+ { 0, "text/plain;charset=iso8859-14", "ISO8859-14", 8 },
+ { 0, "text/plain;charset=iso8859-15", "ISO8859-15", 8 },
+ // asian encodings
+ { 0, "text/plain;charset=jisx0201.1976-0", "JISX0201.1976-0", 8 },
+ { 0, "text/plain;charset=jisx0208.1983-0", "JISX0208.1983-0", 8 },
+ { 0, "text/plain;charset=jisx0208.1990-0", "JISX0208.1990-0", 8 },
+ { 0, "text/plain;charset=jisx0212.1990-0", "JISX0212.1990-0", 8 },
+ { 0, "text/plain;charset=gb2312.1980-0", "GB2312.1980-0", 8 },
+ { 0, "text/plain;charset=ksc5601.1992-0", "KSC5601.1992-0", 8 },
+ // eastern european encodings
+ { 0, "text/plain;charset=koi8-r", "KOI8-R", 8 },
+ { 0, "text/plain;charset=koi8-u", "KOI8-U", 8 },
+ // String (== iso8859-1)
+ { XA_STRING, "text/plain;charset=iso8859-1", "STRING", 8 },
+ // special for compound text
+ { 0, "text/plain;charset=compound_text", "COMPOUND_TEXT", 8 },
+
+ // PIXMAP
+ { XA_PIXMAP, "image/bmp", "PIXMAP", 32 }
+};
+
+rtl_TextEncoding x11::getTextPlainEncoding( const OUString& rMimeType )
+{
+ rtl_TextEncoding aEncoding = RTL_TEXTENCODING_DONTKNOW;
+ OUString aMimeType( rMimeType.toAsciiLowerCase() );
+ sal_Int32 nIndex = 0;
+ if( aMimeType.getToken( 0, ';', nIndex ).equalsAsciiL( "text/plain" , 10 ) )
+ {
+ if( aMimeType.getLength() == 10 ) // only "text/plain"
+ aEncoding = RTL_TEXTENCODING_ISO_8859_1;
+ else
+ {
+ while( nIndex != -1 )
+ {
+ OUString aToken = aMimeType.getToken( 0, ';', nIndex );
+ sal_Int32 nPos = 0;
+ if( aToken.getToken( 0, '=', nPos ).equalsAsciiL( "charset", 7 ) )
+ {
+ OString aEncToken = OUStringToOString( aToken.getToken( 0, '=', nPos ), RTL_TEXTENCODING_ISO_8859_1 );
+ aEncoding = rtl_getTextEncodingFromUnixCharset( aEncToken.getStr() );
+ if( aEncoding == RTL_TEXTENCODING_DONTKNOW )
+ {
+ if( aEncToken.equalsIgnoreAsciiCase( "utf-8" ) )
+ aEncoding = RTL_TEXTENCODING_UTF8;
+ }
+ if( aEncoding != RTL_TEXTENCODING_DONTKNOW )
+ break;
+ }
+ }
+ }
+ }
+#if OSL_DEBUG_LEVEL > 1
+ if( aEncoding == RTL_TEXTENCODING_DONTKNOW )
+ fprintf( stderr, "getTextPlainEncoding( %s ) failed\n", OUStringToOString( rMimeType, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
+#endif
+ return aEncoding;
+}
+
+// ------------------------------------------------------------------------
+
+::std::hash_map< OUString, SelectionManager*, OUStringHash >& SelectionManager::getInstances()
+{
+ static ::std::hash_map< OUString, SelectionManager*, OUStringHash > aInstances;
+ return aInstances;
+}
+
+// ------------------------------------------------------------------------
+
+SelectionManager::SelectionManager() :
+ m_nIncrementalThreshold( 15*1024 ),
+ m_pDisplay( NULL ),
+ m_aThread( NULL ),
+ m_aDragExecuteThread( NULL ),
+ m_aWindow( None ),
+ m_nSelectionTimeout( 0 ),
+ m_nSelectionTimestamp( CurrentTime ),
+ m_aCurrentDropWindow( None ),
+ m_bDropWaitingForCompletion( false ),
+ m_aDropWindow( None ),
+ m_aDropProxy( None ),
+ m_aDragSourceWindow( None ),
+ m_nNoPosX( 0 ),
+ m_nNoPosY( 0 ),
+ m_nNoPosWidth( 0 ),
+ m_nNoPosHeight( 0 ),
+ m_bLastDropAccepted( false ),
+ m_bDropSuccess( false ),
+ m_bDropSent( false ),
+ m_bWaitingForPrimaryConversion( false ),
+ m_aMoveCursor( None ),
+ m_aCopyCursor( None ),
+ m_aLinkCursor( None ),
+ m_aNoneCursor( None ),
+ m_aCurrentCursor( None ),
+ m_nCurrentProtocolVersion( nXdndProtocolRevision )
+{
+ m_aDropEnterEvent.data.l[0] = None;
+ m_bDropEnterSent = true;
+ m_aDragRunning.reset();
+}
+
+Cursor SelectionManager::createCursor( const char* pPointerData, const char* pMaskData, int width, int height, int hotX, int hotY )
+{
+ Pixmap aPointer;
+ Pixmap aMask;
+ XColor aBlack, aWhite;
+
+ aBlack.pixel = BlackPixel( m_pDisplay, 0 );
+ aBlack.red = aBlack.green = aBlack.blue = 0;
+ aBlack.flags = DoRed | DoGreen | DoBlue;
+
+ aWhite.pixel = WhitePixel( m_pDisplay, 0 );
+ aWhite.red = aWhite.green = aWhite.blue = 0xffff;
+ aWhite.flags = DoRed | DoGreen | DoBlue;
+
+ aPointer =
+ XCreateBitmapFromData( m_pDisplay,
+ m_aWindow,
+ pPointerData,
+ width,
+ height );
+ aMask
+ = XCreateBitmapFromData( m_pDisplay,
+ m_aWindow,
+ pMaskData,
+ width,
+ height );
+ Cursor aCursor =
+ XCreatePixmapCursor( m_pDisplay, aPointer, aMask,
+ &aBlack, &aWhite,
+ hotX,
+ hotY );
+ XFreePixmap( m_pDisplay, aPointer );
+ XFreePixmap( m_pDisplay, aMask );
+
+ return aCursor;
+}
+
+void SelectionManager::initialize( const Sequence< Any >& arguments ) throw (::com::sun::star::uno::Exception)
+{
+ MutexGuard aGuard(m_aMutex);
+
+ if( ! m_xDisplayConnection.is() )
+ {
+ /*
+ * first argument must be a ::com::sun::star::awt::XDisplayConnection
+ * from this we will get the XEvents of the vcl event loop by
+ * registering us as XEventHandler on it.
+ *
+ * implementor's note:
+ * FIXME:
+ * finally the clipboard and XDND service is back in the module it belongs
+ * now cleanup and sharing of resources with the normal vcl event loop
+ * needs to be added. The display used whould be that of the normal event loop
+ * and synchronization should be done via the SolarMutex.
+ */
+ if( arguments.getLength() > 0 )
+ arguments.getConstArray()[0] >>= m_xDisplayConnection;
+ if( ! m_xDisplayConnection.is() )
+ {
+#if 0
+ // for the time being try to live without XDisplayConnection
+ // for the sake of clipboard service
+ // clipboard service should be initialized with a XDisplayConnection
+ // in the future
+ Exception aExc;
+ aExc.Message = OUString::createFromAscii( "initialize me with a valid XDisplayConnection" );
+ aExc.Context = static_cast< OWeakObject* >(this);
+ throw aExc;
+#endif
+ }
+ else
+ m_xDisplayConnection->addEventHandler( Any(), this, ~0 );
+ }
+
+ if( !m_xBitmapConverter.is() )
+ {
+ if( arguments.getLength() > 2 )
+ arguments.getConstArray()[2] >>= m_xBitmapConverter;
+ }
+
+ OUString aParam;
+ if( ! m_pDisplay )
+ {
+ OUString aUDisplay;
+ if( m_xDisplayConnection.is() )
+ {
+ Any aIdentifier;
+ aIdentifier = m_xDisplayConnection->getIdentifier();
+ aIdentifier >>= aUDisplay;
+ }
+
+ OString aDisplayName( OUStringToOString( aUDisplay, RTL_TEXTENCODING_ISO_8859_1 ) );
+
+ m_pDisplay = XOpenDisplay( aDisplayName.getLength() ? aDisplayName.getStr() : NULL );
+
+ if( m_pDisplay )
+ {
+#ifdef SYNCHRONIZE
+ XSynchronize( m_pDisplay, True );
+#endif
+ // clipboard selection
+ m_nCLIPBOARDAtom = getAtom( OUString::createFromAscii( "CLIPBOARD" ) );
+
+ // special targets
+ m_nTARGETSAtom = getAtom( OUString::createFromAscii( "TARGETS" ) );
+ m_nTIMESTAMPAtom = getAtom( OUString::createFromAscii( "TIMESTAMP" ) );
+ m_nTEXTAtom = getAtom( OUString::createFromAscii( "TEXT" ) );
+ m_nINCRAtom = getAtom( OUString::createFromAscii( "INCR" ) );
+ m_nCOMPOUNDAtom = getAtom( OUString::createFromAscii( "COMPOUND_TEXT" ) );
+ m_nMULTIPLEAtom = getAtom( OUString::createFromAscii( "MULTIPLE" ) );
+ m_nUTF16Atom = getAtom( OUString::createFromAscii( "ISO10646-1" ) );
+// m_nUTF16Atom = getAtom( OUString::createFromAscii( "text/plain;charset=ISO-10646-UCS-2" ) );
+ m_nImageBmpAtom = getAtom( OUString::createFromAscii( "image/bmp" ) );
+
+ // Atoms for Xdnd protocol
+ m_nXdndAware = getAtom( OUString::createFromAscii( "XdndAware" ) );
+ m_nXdndEnter = getAtom( OUString::createFromAscii( "XdndEnter" ) );
+ m_nXdndLeave = getAtom( OUString::createFromAscii( "XdndLeave" ) );
+ m_nXdndPosition = getAtom( OUString::createFromAscii( "XdndPosition" ) );
+ m_nXdndStatus = getAtom( OUString::createFromAscii( "XdndStatus" ) );
+ m_nXdndDrop = getAtom( OUString::createFromAscii( "XdndDrop" ) );
+ m_nXdndFinished = getAtom( OUString::createFromAscii( "XdndFinished" ) );
+ m_nXdndSelection = getAtom( OUString::createFromAscii( "XdndSelection" ) );
+ m_nXdndTypeList = getAtom( OUString::createFromAscii( "XdndTypeList" ) );
+ m_nXdndProxy = getAtom( OUString::createFromAscii( "XdndProxy" ) );
+ m_nXdndActionCopy = getAtom( OUString::createFromAscii( "XdndActionCopy" ) );
+ m_nXdndActionMove = getAtom( OUString::createFromAscii( "XdndActionMove" ) );
+ m_nXdndActionLink = getAtom( OUString::createFromAscii( "XdndActionLink" ) );
+ m_nXdndActionAsk = getAtom( OUString::createFromAscii( "XdndActionAsk" ) );
+ m_nXdndActionPrivate= getAtom( OUString::createFromAscii( "XdndActionPrivate" ) );
+
+ // initialize map with member none
+ m_aAtomToString[ 0 ]= OUString::createFromAscii( "None" );
+ m_aAtomToString[ XA_PRIMARY ] = OUString::createFromAscii( "PRIMARY" );
+
+ // create a (invisible) message window
+ m_aWindow = XCreateSimpleWindow( m_pDisplay, DefaultRootWindow( m_pDisplay ),
+ 10, 10, 10, 10, 0, 0, 1 );
+
+ // initialize threshold for incremetal transfers
+ // ICCCM says it should be smaller that the max request size
+ // which in turn is guaranteed to be at least 16k bytes
+ m_nIncrementalThreshold = XMaxRequestSize( m_pDisplay ) - 1024;
+
+ if( m_aWindow )
+ {
+ // initialize default cursors
+ m_aMoveCursor = createCursor( movedata_curs_bits,
+ movedata_mask_bits,
+ movedata_curs_width,
+ movedata_curs_height,
+ movedata_curs_x_hot,
+ movedata_curs_y_hot );
+ m_aCopyCursor = createCursor( copydata_curs_bits,
+ copydata_mask_bits,
+ copydata_curs_width,
+ copydata_curs_height,
+ copydata_curs_x_hot,
+ copydata_curs_y_hot );
+ m_aLinkCursor = createCursor( linkdata_curs_bits,
+ linkdata_mask_bits,
+ linkdata_curs_width,
+ linkdata_curs_height,
+ linkdata_curs_x_hot,
+ linkdata_curs_y_hot );
+ m_aNoneCursor = createCursor( nodrop_curs_bits,
+ nodrop_mask_bits,
+ nodrop_curs_width,
+ nodrop_curs_height,
+ nodrop_curs_x_hot,
+ nodrop_curs_y_hot );
+
+
+
+
+ // just interested in SelectionClear/Notify/Request and PropertyChange
+ XSelectInput( m_pDisplay, m_aWindow, PropertyChangeMask );
+ // create the transferable for Drag operations
+ m_xDropTransferable = new X11Transferable( *this, static_cast< OWeakObject* >(this), m_nXdndSelection );
+ registerHandler( m_nXdndSelection, *this );
+
+ m_aThread = osl_createSuspendedThread( call_SelectionManager_run, this );
+ if( m_aThread )
+ osl_resumeThread( m_aThread );
+#if OSL_DEBUG_LEVEL > 1
+ else
+ fprintf( stderr, "SelectionManager::initialize: creation of dispatch thread failed !\n" );
+#endif
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+SelectionManager::~SelectionManager()
+{
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "SelectionManager::~SelectionManager (%s)\n", m_pDisplay ? DisplayString(m_pDisplay) : "no display" );
+#endif
+ {
+ MutexGuard aGuard( *Mutex::getGlobalMutex() );
+
+ ::std::hash_map< OUString, SelectionManager*, OUStringHash >::iterator it;
+ for( it = getInstances().begin(); it != getInstances().end(); ++it )
+ if( it->second == this )
+ {
+ getInstances().erase( it );
+ break;
+ }
+ }
+
+ if( m_aThread )
+ {
+ osl_terminateThread( m_aThread );
+ osl_joinWithThread( m_aThread );
+ osl_destroyThread( m_aThread );
+ }
+
+ if( m_aDragExecuteThread )
+ {
+ osl_terminateThread( m_aDragExecuteThread );
+ osl_joinWithThread( m_aDragExecuteThread );
+ m_aDragExecuteThread = NULL;
+ // thread handle is freed in dragDoDispatch()
+ }
+
+ MutexGuard aGuard(m_aMutex);
+
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "shutting down SelectionManager\n" );
+#endif
+
+ if( m_xDisplayConnection.is() )
+ {
+ m_xDisplayConnection->removeEventHandler( Any(), this );
+ m_xDisplayConnection.clear();
+ }
+
+ if( m_pDisplay )
+ {
+ deregisterHandler( m_nXdndSelection );
+ // destroy message window
+ if( m_aWindow )
+ XDestroyWindow( m_pDisplay, m_aWindow );
+ // release cursors
+ if (m_aMoveCursor != None)
+ XFreeCursor(m_pDisplay, m_aMoveCursor);
+ if (m_aCopyCursor != None)
+ XFreeCursor(m_pDisplay, m_aCopyCursor);
+ if (m_aLinkCursor != None)
+ XFreeCursor(m_pDisplay, m_aLinkCursor);
+ if (m_aNoneCursor != None)
+ XFreeCursor(m_pDisplay, m_aNoneCursor);
+
+ // paranoia setting, the drag thread should have
+ // done that already
+ XUngrabPointer( m_pDisplay, CurrentTime );
+ XUngrabKeyboard( m_pDisplay, CurrentTime );
+
+ XCloseDisplay( m_pDisplay );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+SelectionAdaptor* SelectionManager::getAdaptor( Atom selection )
+{
+ ::std::hash_map< Atom, Selection* >::iterator it =
+ m_aSelections.find( selection );
+ return it != m_aSelections.end() ? it->second->m_pAdaptor : NULL;
+}
+
+// ------------------------------------------------------------------------
+
+OUString SelectionManager::convertFromCompound( const char* pText, int nLen )
+{
+ MutexGuard aGuard( m_aMutex );
+ OUString aRet;
+ if( nLen < 0 )
+ nLen = strlen( pText );
+
+ char** pTextList = NULL;
+ int nTexts = 0;
+
+ XTextProperty aProp;
+ aProp.value = (unsigned char*)pText;
+ aProp.encoding = m_nCOMPOUNDAtom;
+ aProp.format = 8;
+ aProp.nitems = nLen;
+ XmbTextPropertyToTextList( m_pDisplay,
+ &aProp,
+ &pTextList,
+ &nTexts );
+ rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
+ for( int i = 0; i < nTexts; i++ )
+ aRet += OStringToOUString( pTextList[i], aEncoding );
+
+ if( pTextList )
+ XFreeStringList( pTextList );
+
+ return aRet;
+}
+
+// ------------------------------------------------------------------------
+
+OString SelectionManager::convertToCompound( const OUString& rText )
+{
+ MutexGuard aGuard( m_aMutex );
+ XTextProperty aProp;
+ aProp.value = NULL;
+ aProp.encoding = XA_STRING;
+ aProp.format = 8;
+ aProp.nitems = 0;
+
+ OString aRet( rText.getStr(), rText.getLength(), osl_getThreadTextEncoding() );
+ char* pT = const_cast<char*>(aRet.getStr());
+
+ XmbTextListToTextProperty( m_pDisplay,
+ &pT,
+ 1,
+ XCompoundTextStyle,
+ &aProp );
+ if( aProp.value )
+ {
+ aRet = (char*)aProp.value;
+ XFree( aProp.value );
+#ifdef SOLARIS
+ /* #97070#
+ * for currently unknown reasons XmbTextListToTextProperty on Solaris returns
+ * no data in ISO8859-n encodings (at least for n = 1, 15)
+ * in these encodings the directly converted text does the
+ * trick, also.
+ */
+ if( ! aRet.getLength() && rText.getLength() )
+ aRet = OUStringToOString( rText, osl_getThreadTextEncoding() );
+#endif
+ }
+ else
+ aRet = OString();
+
+ return aRet;
+}
+
+// ------------------------------------------------------------------------
+
+bool SelectionManager::convertData(
+ const Reference< XTransferable >& xTransferable,
+ Atom nType,
+ Atom nSelection,
+ int& rFormat,
+ Sequence< sal_Int8 >& rData )
+{
+ bool bSuccess = false;
+
+ if( ! xTransferable.is() )
+ return bSuccess;
+
+ try
+ {
+
+ DataFlavor aFlavor;
+ aFlavor.MimeType = convertTypeFromNative( nType, nSelection, rFormat );
+
+ sal_Int32 nIndex = 0;
+ if( aFlavor.MimeType.getToken( 0, ';', nIndex ).compareToAscii( "text/plain" ) == 0 )
+ {
+ if( aFlavor.MimeType.getToken( 0, ';', nIndex ).compareToAscii( "charset=utf-16" ) == 0 )
+ aFlavor.DataType = getCppuType( (OUString *) 0 );
+ else
+ aFlavor.DataType = getCppuType( (Sequence< sal_Int8 >*)0 );
+ }
+ else
+ aFlavor.DataType = getCppuType( (Sequence< sal_Int8 >*)0 );
+
+ if( xTransferable->isDataFlavorSupported( aFlavor ) )
+ {
+ Any aValue( xTransferable->getTransferData( aFlavor ) );
+ if( aValue.getValueTypeClass() == TypeClass_STRING )
+ {
+ OUString aString;
+ aValue >>= aString;
+ rData = Sequence< sal_Int8 >( (sal_Int8*)aString.getStr(), aString.getLength() * sizeof( sal_Unicode ) );
+ bSuccess = true;
+ }
+ else if( aValue.getValueType() == getCppuType( (Sequence< sal_Int8 >*)0 ) )
+ {
+ aValue >>= rData;
+ bSuccess = true;
+ }
+ }
+ else if( aFlavor.MimeType.compareToAscii( "text/plain", 10 ) == 0 )
+ {
+ rtl_TextEncoding aEncoding = RTL_TEXTENCODING_DONTKNOW;
+ bool bCompoundText = false;
+ if( nType == m_nCOMPOUNDAtom )
+ bCompoundText = true;
+ else
+ aEncoding = getTextPlainEncoding( aFlavor.MimeType );
+ if( aEncoding != RTL_TEXTENCODING_DONTKNOW || bCompoundText )
+ {
+ aFlavor.MimeType = OUString::createFromAscii( "text/plain;charset=utf-16" );
+ aFlavor.DataType = getCppuType( (OUString *) 0 );
+ if( xTransferable->isDataFlavorSupported( aFlavor ) )
+ {
+ Any aValue( xTransferable->getTransferData( aFlavor ) );
+ OUString aString;
+ aValue >>= aString;
+ OString aByteString( bCompoundText ? convertToCompound( aString ) : OUStringToOString( aString, aEncoding ) );
+ rData = Sequence< sal_Int8 >( (sal_Int8*)aByteString.getStr(), aByteString.getLength() * sizeof( sal_Char ) );
+ bSuccess = true;
+ }
+ }
+ }
+ }
+ // various exceptions possible ... which all lead to a failed conversion
+ // so simplify here to a catch all
+ catch(...)
+ {
+ }
+
+ return bSuccess;
+}
+
+// ------------------------------------------------------------------------
+
+SelectionManager& SelectionManager::get( const OUString& rDisplayName )
+{
+ MutexGuard aGuard( *Mutex::getGlobalMutex() );
+
+ OUString aDisplayName( rDisplayName );
+ if( ! aDisplayName.getLength() )
+ aDisplayName = OStringToOUString( getenv( "DISPLAY" ), RTL_TEXTENCODING_ISO_8859_1 );
+ SelectionManager* pInstance = NULL;
+
+ ::std::hash_map< OUString, SelectionManager*, OUStringHash >::iterator it = getInstances().find( aDisplayName );
+ if( it != getInstances().end() )
+ pInstance = it->second;
+ else pInstance = getInstances()[ aDisplayName ] = new SelectionManager();
+
+ return *pInstance;
+}
+
+// ------------------------------------------------------------------------
+
+const OUString& SelectionManager::getString( Atom aAtom )
+{
+ MutexGuard aGuard(m_aMutex);
+
+ ::std::hash_map< Atom, OUString >::const_iterator it;
+ if( ( it = m_aAtomToString.find( aAtom ) ) == m_aAtomToString.end() )
+ {
+ static OUString aEmpty;
+ char* pAtom = m_pDisplay ? XGetAtomName( m_pDisplay, aAtom ) : NULL;
+ if( ! pAtom )
+ return aEmpty;
+ OUString aString( OStringToOUString( pAtom, RTL_TEXTENCODING_ISO_8859_1 ) );
+ XFree( pAtom );
+ m_aStringToAtom[ aString ] = aAtom;
+ m_aAtomToString[ aAtom ] = aString;
+ }
+ return m_aAtomToString[ aAtom ];
+}
+
+// ------------------------------------------------------------------------
+
+Atom SelectionManager::getAtom( const OUString& rString )
+{
+ MutexGuard aGuard(m_aMutex);
+
+ ::std::hash_map< OUString, Atom, OUStringHash >::const_iterator it;
+ if( ( it = m_aStringToAtom.find( rString ) ) == m_aStringToAtom.end() )
+ {
+ static Atom nNoDisplayAtoms = 1;
+ Atom aAtom = m_pDisplay ? XInternAtom( m_pDisplay, OUStringToOString( rString, RTL_TEXTENCODING_ISO_8859_1 ), False ) : nNoDisplayAtoms++;
+ m_aStringToAtom[ rString ] = aAtom;
+ m_aAtomToString[ aAtom ] = rString;
+ }
+ return m_aStringToAtom[ rString ];
+}
+
+// ------------------------------------------------------------------------
+
+bool SelectionManager::requestOwnership( Atom selection )
+{
+ bool bSuccess = false;
+ if( m_pDisplay && m_aWindow )
+ {
+ MutexGuard aGuard(m_aMutex);
+
+ SelectionAdaptor* pAdaptor = getAdaptor( selection );
+ if( pAdaptor )
+ {
+ XSetSelectionOwner( m_pDisplay, selection, m_aWindow, CurrentTime );
+ if( XGetSelectionOwner( m_pDisplay, selection ) == m_aWindow )
+ bSuccess = true;
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "%s ownership for selection %s\n",
+ bSuccess ? "acquired" : "failed to acquire",
+ OUStringToOString( getString( selection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
+#endif
+ Selection* pSel = m_aSelections[ selection ];
+ pSel->m_bOwner = bSuccess;
+ delete pSel->m_pPixmap;
+ pSel->m_pPixmap = NULL;
+ pSel->m_nOrigTimestamp = m_nSelectionTimestamp;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ fprintf( stderr, "no adaptor for selection %s\n",
+ OUStringToOString( getString( selection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
+
+ if( pAdaptor->getTransferable().is() )
+ {
+ Sequence< DataFlavor > aTypes = pAdaptor->getTransferable()->getTransferDataFlavors();
+ for( int i = 0; i < aTypes.getLength(); i++ )
+ {
+ fprintf( stderr, " %s\n", OUStringToOString( aTypes.getConstArray()[i].MimeType, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
+ }
+ }
+#endif
+ }
+ return bSuccess;
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::convertTypeToNative( const OUString& rType, Atom selection, int& rFormat, ::std::list< Atom >& rConversions, bool bPushFront )
+{
+ NativeTypeEntry* pTab = selection == m_nXdndSelection ? aXdndConversionTab : aNativeConversionTab;
+ int nTabEntries = selection == m_nXdndSelection
+ ? sizeof(aXdndConversionTab)/sizeof(aXdndConversionTab[0]) :
+ sizeof(aNativeConversionTab)/sizeof(aNativeConversionTab[0]);
+
+ OString aType( OUStringToOString( rType, RTL_TEXTENCODING_ISO_8859_1 ) );
+ rFormat = 0;
+ for( int i = 0; i < nTabEntries; i++ )
+ {
+ if( aType.equalsIgnoreAsciiCase( pTab[i].pType ) )
+ {
+ if( ! pTab[i].nAtom )
+ pTab[i].nAtom = getAtom( OStringToOUString( pTab[i].pNativeType, RTL_TEXTENCODING_ISO_8859_1 ) );
+ rFormat = pTab[i].nFormat;
+ if( bPushFront )
+ rConversions.push_front( pTab[i].nAtom );
+ else
+ rConversions.push_back( pTab[i].nAtom );
+ if( pTab[i].nFormat == XA_PIXMAP )
+ {
+ if( bPushFront )
+ {
+ rConversions.push_front( XA_VISUALID );
+ rConversions.push_front( XA_COLORMAP );
+ }
+ else
+ {
+ rConversions.push_back( XA_VISUALID );
+ rConversions.push_back( XA_COLORMAP );
+ }
+ }
+ }
+ }
+ if( ! rFormat )
+ rFormat = 8; // byte buffer
+ if( bPushFront )
+ rConversions.push_front( getAtom( rType ) );
+ else
+ rConversions.push_back( getAtom( rType ) );
+};
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::getNativeTypeList( const Sequence< DataFlavor >& rTypes, std::list< Atom >& rOutTypeList, Atom targetselection )
+{
+ rOutTypeList.clear();
+
+ int nFormat;
+ int nFlavors = rTypes.getLength();
+ const DataFlavor* pFlavors = rTypes.getConstArray();
+ bool bHaveText = false;
+ for( int i = 0; i < nFlavors; i++ )
+ {
+ if( pFlavors[i].MimeType.compareToAscii( "text/plain", 10 ) == 0)
+ bHaveText = true;
+ else
+ convertTypeToNative( pFlavors[i].MimeType, targetselection, nFormat, rOutTypeList );
+ }
+ if( bHaveText )
+ {
+ if( targetselection != m_nXdndSelection )
+ {
+ // only mimetypes should go into Xdnd type list
+ rOutTypeList.push_front( XA_STRING );
+ rOutTypeList.push_front( m_nCOMPOUNDAtom );
+ }
+ convertTypeToNative( OUString::createFromAscii( "text/plain;charset=utf-8" ), targetselection, nFormat, rOutTypeList, true );
+ }
+ if( targetselection != m_nXdndSelection )
+ rOutTypeList.push_back( m_nMULTIPLEAtom );
+}
+
+// ------------------------------------------------------------------------
+
+OUString SelectionManager::convertTypeFromNative( Atom nType, Atom selection, int& rFormat )
+{
+ NativeTypeEntry* pTab = selection == m_nXdndSelection ? aXdndConversionTab : aNativeConversionTab;
+ int nTabEntries = selection == m_nXdndSelection
+ ? sizeof(aXdndConversionTab)/sizeof(aXdndConversionTab[0]) :
+ sizeof(aNativeConversionTab)/sizeof(aNativeConversionTab[0]);
+
+ for( int i = 0; i < nTabEntries; i++ )
+ {
+ if( ! pTab[i].nAtom )
+ pTab[i].nAtom = getAtom( OStringToOUString( pTab[i].pNativeType, RTL_TEXTENCODING_ISO_8859_1 ) );
+ if( nType == pTab[i].nAtom )
+ {
+ rFormat = pTab[i].nFormat;
+ return OStringToOUString( pTab[i].pType, RTL_TEXTENCODING_ISO_8859_1 );
+ }
+ }
+ rFormat = 8;
+ return getString( nType );
+}
+
+// ------------------------------------------------------------------------
+
+bool SelectionManager::getPasteData( Atom selection, Atom type, Sequence< sal_Int8 >& rData )
+{
+ ResettableMutexGuard aGuard(m_aMutex);
+ ::std::hash_map< Atom, Selection* >::iterator it;
+ bool bSuccess = false;
+
+#if OSL_DEBUG_LEVEL > 1
+ OUString aSelection( getString( selection ) );
+ OUString aType( getString( type ) );
+ fprintf( stderr, "getPasteData( %s, native: %s )\n",
+ OUStringToOString( aSelection, RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
+ OUStringToOString( aType, RTL_TEXTENCODING_ISO_8859_1 ).getStr()
+ );
+#endif
+
+ if( ! m_pDisplay )
+ return false;
+
+ it = m_aSelections.find( selection );
+ if( it == m_aSelections.end() )
+ return false;
+
+ Window aSelectionOwner = XGetSelectionOwner( m_pDisplay, selection );
+ if( aSelectionOwner == None )
+ return false;
+ if( aSelectionOwner == m_aWindow )
+ {
+ // probably bad timing led us here
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "Innere Nabelschau\n" );
+#endif
+ return false;
+ }
+
+ // ICCCM recommends to destroy property before convert request unless
+ // parameters are transported; we do only in case of MULTIPLE,
+ // so destroy property unless target is MULTIPLE
+ if( type != m_nMULTIPLEAtom )
+ XDeleteProperty( m_pDisplay, m_aWindow, selection );
+
+ XConvertSelection( m_pDisplay, selection, type, selection, m_aWindow, selection == m_nXdndSelection ? m_nDropTime : CurrentTime );
+ it->second->m_eState = Selection::WaitingForResponse;
+ it->second->m_aRequestedType = type;
+ it->second->m_aData = Sequence< sal_Int8 >();
+ it->second->m_aDataArrived.reset();
+ // really start the request; if we don't flush the
+ // queue the request won't leave it because there are no more
+ // X calls after this until the data arrived or timeout
+ XFlush( m_pDisplay );
+
+ // do a reschedule
+ struct timeval tv_last, tv_current;
+ gettimeofday( &tv_last, NULL );
+ tv_current = tv_last;
+
+ XEvent aEvent;
+ do
+ {
+ bool bAdjustTime = false;
+ {
+ bool bHandle = false;
+
+ if( XCheckTypedEvent( m_pDisplay,
+ PropertyNotify,
+ &aEvent
+ ) )
+ {
+ bHandle = true;
+ if( aEvent.xproperty.window == m_aWindow
+ && aEvent.xproperty.atom == selection )
+ bAdjustTime = true;
+ }
+ else
+ if( XCheckTypedEvent( m_pDisplay,
+ SelectionClear,
+ &aEvent
+ ) )
+ {
+ bHandle = true;
+ }
+ else
+ if( XCheckTypedEvent( m_pDisplay,
+ SelectionRequest,
+ &aEvent
+ ) )
+ bHandle = true;
+ else
+ if( XCheckTypedEvent( m_pDisplay,
+ SelectionNotify,
+ &aEvent
+ ) )
+ {
+ bHandle = true;
+ if( aEvent.xselection.selection == selection
+ && ( aEvent.xselection.requestor == m_aWindow ||
+ aEvent.xselection.requestor == m_aCurrentDropWindow )
+ )
+ bAdjustTime = true;
+ }
+ else
+ {
+ TimeValue aTVal;
+ aTVal.Seconds = 0;
+ aTVal.Nanosec = 100000000;
+ aGuard.clear();
+ osl_waitThread( &aTVal );
+ aGuard.reset();
+ }
+ if( bHandle )
+ {
+ aGuard.clear();
+ handleXEvent( aEvent );
+ aGuard.reset();
+ }
+ }
+ gettimeofday( &tv_current, NULL );
+ if( bAdjustTime )
+ tv_last = tv_current;
+ } while( ! it->second->m_aDataArrived.check() && (tv_current.tv_sec - tv_last.tv_sec) < getSelectionTimeout() );
+
+#if OSL_DEBUG_LEVEL > 1
+ if( (tv_current.tv_sec - tv_last.tv_sec) > getSelectionTimeout() )
+ fprintf( stderr, "timed out\n" );
+#endif
+ if( it->second->m_aDataArrived.check() &&
+ it->second->m_aData.getLength() )
+ {
+ rData = it->second->m_aData;
+ bSuccess = true;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ fprintf( stderr, "conversion unsuccessfull\n" );
+#endif
+ return bSuccess;
+}
+
+// ------------------------------------------------------------------------
+
+bool SelectionManager::getPasteData( Atom selection, const ::rtl::OUString& rType, Sequence< sal_Int8 >& rData )
+{
+ int nFormat;
+ bool bSuccess = false;
+
+ ::std::hash_map< Atom, Selection* >::iterator it;
+ {
+ MutexGuard aGuard(m_aMutex);
+
+ it = m_aSelections.find( selection );
+ if( it == m_aSelections.end() )
+ return false;
+ }
+
+ if( it->second->m_aTypes.getLength() == 0 )
+ {
+ Sequence< DataFlavor > aFlavors;
+ getPasteDataTypes( selection, aFlavors );
+ if( it->second->m_aTypes.getLength() == 0 )
+ return false;
+ }
+
+ const Sequence< DataFlavor >& rTypes( it->second->m_aTypes );
+ const std::vector< Atom >& rNativeTypes( it->second->m_aNativeTypes );
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "getPasteData( \"%s\", \"%s\" )\n",
+ OUStringToOString( getString( selection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
+ OUStringToOString( rType, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
+#endif
+
+ if( rType.equalsAsciiL( "text/plain;charset=utf-16", 25 ) )
+ {
+ // lets see if we have UTF16 else try to find something convertible
+ if( it->second->m_aTypes.getLength() && ! it->second->m_bHaveUTF16 )
+ {
+ Sequence< sal_Int8 > aData;
+ if( it->second->m_aUTF8Type != None &&
+ getPasteData( selection,
+ it->second->m_aUTF8Type,
+ aData )
+ )
+ {
+ OUString aRet( (const sal_Char*)aData.getConstArray(), aData.getLength(), RTL_TEXTENCODING_UTF8 );
+ rData = Sequence< sal_Int8 >( (sal_Int8*)aRet.getStr(), (aRet.getLength()+1)*sizeof( sal_Unicode ) );
+ bSuccess = true;
+ }
+ else if( it->second->m_bHaveCompound &&
+ getPasteData( selection,
+ m_nCOMPOUNDAtom,
+ aData )
+ )
+ {
+ OUString aRet( convertFromCompound( (const char*)aData.getConstArray(), aData.getLength() ) );
+ rData = Sequence< sal_Int8 >( (sal_Int8*)aRet.getStr(), (aRet.getLength()+1)*sizeof( sal_Unicode ) );
+ bSuccess = true;
+ }
+ else
+ {
+ for( int i = 0; i < rTypes.getLength(); i++ )
+ {
+ rtl_TextEncoding aEncoding = getTextPlainEncoding( rTypes.getConstArray()[i].MimeType );
+ if( aEncoding != RTL_TEXTENCODING_DONTKNOW &&
+ aEncoding != RTL_TEXTENCODING_UNICODE &&
+ getPasteData( selection,
+ rNativeTypes[i],
+ aData )
+ )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "using \"%s\" instead of \"%s\"\n",
+ OUStringToOString( rTypes.getConstArray()[i].MimeType, RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
+ OUStringToOString( rType, RTL_TEXTENCODING_ISO_8859_1 ).getStr()
+ );
+#endif
+ OString aConvert( (sal_Char*)aData.getConstArray(), aData.getLength() );
+ OUString aUTF( OStringToOUString( aConvert, aEncoding ) );
+ rData = Sequence< sal_Int8 >( (sal_Int8*)aUTF.getStr(), (aUTF.getLength()+1)*sizeof( sal_Unicode ) );
+ bSuccess = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else if( rType.equalsAsciiL( "image/bmp", 9 ) )
+ {
+ // #i83376# try if someone has the data in image/bmp already before
+ // doing the PIXMAP stuff (e.g. the gimp has this)
+ bSuccess = getPasteData( selection, m_nImageBmpAtom, rData );
+ #if OSL_DEBUG_LEVEL > 1
+ if( bSuccess )
+ fprintf( stderr, "got %d bytes of image/bmp\n", (int)rData.getLength() );
+ #endif
+ if( ! bSuccess )
+ {
+ Pixmap aPixmap = None;
+ Colormap aColormap = None;
+
+ // prepare property for MULTIPLE request
+ Sequence< sal_Int8 > aData;
+ Atom pTypes[4] = { XA_PIXMAP, XA_PIXMAP,
+ XA_COLORMAP, XA_COLORMAP };
+ {
+ MutexGuard aGuard(m_aMutex);
+
+ XChangeProperty( m_pDisplay,
+ m_aWindow,
+ selection,
+ XA_ATOM,
+ 32,
+ PropModeReplace,
+ (unsigned char*)pTypes,
+ 4 );
+ }
+
+ // try MULTIPLE request
+ if( getPasteData( selection, m_nMULTIPLEAtom, aData ) )
+ {
+ Atom* pReturnedTypes = (Atom*)aData.getArray();
+ if( pReturnedTypes[0] == XA_PIXMAP && pReturnedTypes[1] == XA_PIXMAP )
+ {
+ MutexGuard aGuard(m_aMutex);
+
+ Atom type = None;
+ int format = 0;
+ unsigned long nItems = 0;
+ unsigned long nBytes = 0;
+ unsigned char* pReturn = NULL;
+ XGetWindowProperty( m_pDisplay, m_aWindow, XA_PIXMAP, 0, 1, True, XA_PIXMAP, &type, &format, &nItems, &nBytes, &pReturn );
+ if( pReturn )
+ {
+ if( type == XA_PIXMAP )
+ aPixmap = *(Pixmap*)pReturn;
+ XFree( pReturn );
+ pReturn = NULL;
+ if( pReturnedTypes[2] == XA_COLORMAP && pReturnedTypes[3] == XA_COLORMAP )
+ {
+ XGetWindowProperty( m_pDisplay, m_aWindow, XA_COLORMAP, 0, 1, True, XA_COLORMAP, &type, &format, &nItems, &nBytes, &pReturn );
+ if( pReturn )
+ {
+ if( type == XA_COLORMAP )
+ aColormap = *(Colormap*)pReturn;
+ XFree( pReturn );
+ }
+ }
+ }
+ #if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ fprintf( stderr, "could not get PIXMAP property: type=%s, format=%d, items=%ld, bytes=%ld, ret=0x%p\n", OUStringToOString( getString( type ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(), format, nItems, nBytes, pReturn );
+ }
+ #endif
+ }
+ }
+
+ if( aPixmap == None )
+ {
+ // perhaps two normal requests will work
+ if( getPasteData( selection, XA_PIXMAP, aData ) )
+ {
+ aPixmap = *(Pixmap*)aData.getArray();
+ if( aColormap == None && getPasteData( selection, XA_COLORMAP, aData ) )
+ aColormap = *(Colormap*)aData.getArray();
+ }
+ }
+
+ // convert data if possible
+ if( aPixmap != None )
+ {
+ MutexGuard aGuard(m_aMutex);
+
+ sal_Int32 nOutSize = 0;
+ sal_uInt8* pBytes = X11_getBmpFromPixmap( m_pDisplay, aPixmap, aColormap, nOutSize );
+ if( pBytes && nOutSize )
+ {
+ rData = Sequence< sal_Int8 >( nOutSize );
+ memcpy( rData.getArray(), pBytes, nOutSize );
+ X11_freeBmp( pBytes );
+ bSuccess = true;
+ }
+ }
+ }
+ }
+
+ if( ! bSuccess )
+ {
+ ::std::list< Atom > aTypes;
+ convertTypeToNative( rType, selection, nFormat, aTypes );
+ ::std::list< Atom >::const_iterator type_it;
+ Atom nSelectedType = None;
+ for( type_it = aTypes.begin(); type_it != aTypes.end() && nSelectedType == None; ++type_it )
+ {
+ for( unsigned int i = 0; i < rNativeTypes.size() && nSelectedType == None; i++ )
+ if( rNativeTypes[i] == *type_it )
+ nSelectedType = *type_it;
+ }
+ if( nSelectedType != None )
+ bSuccess = getPasteData( selection, nSelectedType, rData );
+ }
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "getPasteData for selection %s and data type %s returns %s, returned sequence has length %ld\n",
+ OUStringToOString( getString( selection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
+ OUStringToOString( rType, RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
+ bSuccess ? "true" : "false",
+ rData.getLength()
+ );
+#endif
+ return bSuccess;
+}
+
+// ------------------------------------------------------------------------
+
+bool SelectionManager::getPasteDataTypes( Atom selection, Sequence< DataFlavor >& rTypes )
+{
+ ::std::hash_map< Atom, Selection* >::iterator it;
+ {
+ MutexGuard aGuard(m_aMutex);
+
+ it = m_aSelections.find( selection );
+ if( it != m_aSelections.end() &&
+ it->second->m_aTypes.getLength() &&
+ abs( it->second->m_nLastTimestamp - time( NULL ) ) < 2
+ )
+ {
+ rTypes = it->second->m_aTypes;
+ return true;
+ }
+ }
+
+ bool bSuccess = false;
+ bool bHaveUTF16 = false;
+ Atom aUTF8Type = None;
+ bool bHaveCompound = false;
+ bool bHaveText = false;
+ Sequence< sal_Int8 > aAtoms;
+
+ if( selection == m_nXdndSelection )
+ {
+ // xdnd sends first three types with XdndEnter
+ // if more than three types are supported then the XDndTypeList
+ // property on the source window is used
+ if( m_aDropEnterEvent.data.l[0] && m_aCurrentDropWindow )
+ {
+ if( m_aDropEnterEvent.data.l[1] & 1 )
+ {
+ const unsigned int atomcount = 256;
+ // more than three types; look in property
+ MutexGuard aGuard(m_aMutex);
+
+ Atom nType;
+ int nFormat;
+ unsigned long nItems, nBytes;
+ unsigned char* pBytes = NULL;
+
+ XGetWindowProperty( m_pDisplay, m_aDropEnterEvent.data.l[0],
+ m_nXdndTypeList, 0, atomcount, False,
+ XA_ATOM,
+ &nType, &nFormat, &nItems, &nBytes, &pBytes );
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "have %ld data types in XdndTypeList\n", nItems );
+#endif
+ if( nItems == atomcount && nBytes > 0 )
+ {
+ // wow ... more than 256 types !
+ aAtoms.realloc( sizeof( Atom )*atomcount+nBytes );
+ memcpy( aAtoms.getArray(), pBytes, sizeof( Atom )*atomcount );
+ XFree( pBytes );
+ pBytes = NULL;
+ XGetWindowProperty( m_pDisplay, m_aDropEnterEvent.data.l[0],
+ m_nXdndTypeList, atomcount, nBytes/sizeof(Atom),
+ False, XA_ATOM,
+ &nType, &nFormat, &nItems, &nBytes, &pBytes );
+ {
+ memcpy( aAtoms.getArray()+atomcount*sizeof(Atom), pBytes, nItems*sizeof(Atom) );
+ XFree( pBytes );
+ }
+ }
+ else
+ {
+ aAtoms.realloc( sizeof(Atom)*nItems );
+ memcpy( aAtoms.getArray(), pBytes, nItems*sizeof(Atom) );
+ XFree( pBytes );
+ }
+ }
+ else
+ {
+ // one to three types
+ int n = 0, i;
+ for( i = 0; i < 3; i++ )
+ if( m_aDropEnterEvent.data.l[2+i] )
+ n++;
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "have %d data types in XdndEnter\n", n );
+#endif
+ aAtoms.realloc( sizeof(Atom)*n );
+ for( i = 0, n = 0; i < 3; i++ )
+ if( m_aDropEnterEvent.data.l[2+i] )
+ ((Atom*)aAtoms.getArray())[n++] = m_aDropEnterEvent.data.l[2+i];
+ }
+ }
+ }
+ // get data of type TARGETS
+ else if( ! getPasteData( selection, m_nTARGETSAtom, aAtoms ) )
+ aAtoms = Sequence< sal_Int8 >();
+
+ std::vector< Atom > aNativeTypes;
+ if( aAtoms.getLength() )
+ {
+ sal_Int32 nAtoms = aAtoms.getLength() / sizeof(Atom);
+ Atom* pAtoms = (Atom*)aAtoms.getArray();
+ rTypes.realloc( nAtoms );
+ aNativeTypes.resize( nAtoms );
+ DataFlavor* pFlavors = rTypes.getArray();
+ sal_Int32 nNativeTypesIndex = 0;
+ while( nAtoms-- )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ if( *pAtoms && *pAtoms < 0x01000000 )
+ fprintf( stderr, "native type: %s\n", OUStringToOString( getString( *pAtoms ), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
+#endif
+ if( *pAtoms == m_nCOMPOUNDAtom )
+ bHaveText = bHaveCompound = true;
+ else if( *pAtoms && *pAtoms < 0x01000000 )
+ {
+ int nFormat;
+ pFlavors->MimeType = convertTypeFromNative( *pAtoms, selection, nFormat );
+ pFlavors->DataType = getCppuType( (Sequence< sal_Int8 >*)0 );
+ sal_Int32 nIndex = 0;
+ if( pFlavors->MimeType.getToken( 0, ';', nIndex ).equalsAsciiL( "text/plain", 10 ) )
+ {
+ OUString aToken(pFlavors->MimeType.getToken( 0, ';', nIndex ));
+ // omit text/plain;charset=unicode since it is not well defined
+ if( aToken.compareToAscii( "charset=unicode" ) == 0 )
+ {
+ pAtoms++;
+ continue;
+ }
+ bHaveText = true;
+ if( aToken.compareToAscii( "charset=utf-16" ) == 0 )
+ {
+ bHaveUTF16 = true;
+ pFlavors->DataType = getCppuType( (OUString*)0 );
+ }
+ else if( aToken.compareToAscii( "charset=utf-8" ) == 0 )
+ {
+ aUTF8Type = *pAtoms;
+ }
+ }
+ pFlavors++;
+ aNativeTypes[ nNativeTypesIndex ] = *pAtoms;
+ nNativeTypesIndex++;
+ }
+ pAtoms++;
+ }
+ if( (pFlavors - rTypes.getArray()) < rTypes.getLength() )
+ rTypes.realloc(pFlavors - rTypes.getArray());
+ bSuccess = rTypes.getLength() ? true : false;
+ if( bHaveText && ! bHaveUTF16 )
+ {
+ int i = 0;
+
+ int nNewFlavors = rTypes.getLength()+1;
+ Sequence< DataFlavor > aTemp( nNewFlavors );
+ for( i = 0; i < nNewFlavors-1; i++ )
+ aTemp.getArray()[i+1] = rTypes.getConstArray()[i];
+ aTemp.getArray()[0].MimeType = OUString::createFromAscii( "text/plain;charset=utf-16" );
+ aTemp.getArray()[0].DataType = getCppuType( (OUString*)0 );
+ rTypes = aTemp;
+
+ std::vector< Atom > aNativeTemp( nNewFlavors );
+ for( i = 0; i < nNewFlavors-1; i++ )
+ aNativeTemp[ i + 1 ] = aNativeTypes[ i ];
+ aNativeTemp[0] = None;
+ aNativeTypes = aNativeTemp;
+ }
+ }
+
+ {
+ MutexGuard aGuard(m_aMutex);
+
+ it = m_aSelections.find( selection );
+ if( it != m_aSelections.end() )
+ {
+ if( bSuccess )
+ {
+ it->second->m_aTypes = rTypes;
+ it->second->m_aNativeTypes = aNativeTypes;
+ it->second->m_nLastTimestamp = time( NULL );
+ it->second->m_bHaveUTF16 = bHaveUTF16;
+ it->second->m_aUTF8Type = aUTF8Type;
+ it->second->m_bHaveCompound = bHaveCompound;
+ }
+ else
+ {
+ it->second->m_aTypes = Sequence< DataFlavor >();
+ it->second->m_aNativeTypes = std::vector< Atom >();
+ it->second->m_nLastTimestamp = 0;
+ it->second->m_bHaveUTF16 = false;
+ it->second->m_aUTF8Type = None;
+ it->second->m_bHaveCompound = false;
+ }
+ }
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+// if( selection != m_nCLIPBOARDAtom )
+ {
+ fprintf( stderr, "SelectionManager::getPasteDataTypes( %s ) = %s\n", OUStringToOString( getString( selection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(), bSuccess ? "true" : "false" );
+ for( int i = 0; i < rTypes.getLength(); i++ )
+ fprintf( stderr, "type: %s\n", OUStringToOString( rTypes.getConstArray()[i].MimeType, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
+ }
+#endif
+
+ return bSuccess;
+}
+
+// ------------------------------------------------------------------------
+
+PixmapHolder* SelectionManager::getPixmapHolder( Atom selection )
+{
+ std::hash_map< Atom, Selection* >::const_iterator it = m_aSelections.find( selection );
+ if( it == m_aSelections.end() )
+ return NULL;
+ if( ! it->second->m_pPixmap )
+ it->second->m_pPixmap = new PixmapHolder( m_pDisplay );
+ return it->second->m_pPixmap;
+}
+
+static sal_Size GetTrueFormatSize(int nFormat)
+{
+ // http://mail.gnome.org/archives/wm-spec-list/2003-March/msg00067.html
+ return nFormat == 32 ? sizeof(long) : nFormat/8;
+}
+
+bool SelectionManager::sendData( SelectionAdaptor* pAdaptor,
+ Window requestor,
+ Atom target,
+ Atom property,
+ Atom selection )
+{
+ ResettableMutexGuard aGuard( m_aMutex );
+
+ // handle targets related to image/bmp
+ if( target == XA_COLORMAP || target == XA_PIXMAP || target == XA_BITMAP || target == XA_VISUALID )
+ {
+ PixmapHolder* pPixmap = getPixmapHolder( selection );
+ if( ! pPixmap ) return false;
+ XID nValue = None;
+
+ // handle colormap request
+ if( target == XA_COLORMAP )
+ nValue = (XID)pPixmap->getColormap();
+ else if( target == XA_VISUALID )
+ nValue = (XID)pPixmap->getVisualID();
+ else if( target == XA_PIXMAP || target == XA_BITMAP )
+ {
+ nValue = (XID)pPixmap->getPixmap();
+ if( nValue == None )
+ {
+ // first conversion
+ Sequence< sal_Int8 > aData;
+ int nFormat;
+ aGuard.clear();
+ bool bConverted = convertData( pAdaptor->getTransferable(), target, selection, nFormat, aData );
+ aGuard.reset();
+ if( bConverted )
+ {
+ // get pixmap again since clearing the guard could have invalidated
+ // the pixmap in another thread
+ pPixmap = getPixmapHolder( selection );
+ // conversion succeeded, so aData contains image/bmp now
+ if( pPixmap->needsConversion( (const sal_uInt8*)aData.getConstArray() )
+ && m_xBitmapConverter.is() )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "trying bitmap conversion\n" );
+#endif
+ Reference<XBitmap> xBM( new BmpTransporter( aData ) );
+ Sequence<Any> aArgs(2), aOutArgs;
+ Sequence<sal_Int16> aOutIndex;
+ aArgs.getArray()[0] = makeAny( xBM );
+ aArgs.getArray()[1] = makeAny( (sal_uInt16)pPixmap->getDepth() );
+ aGuard.clear();
+ try
+ {
+ Any aResult =
+ m_xBitmapConverter->invoke( OUString::createFromAscii( "convert-bitmap-depth" ),
+ aArgs, aOutIndex, aOutArgs );
+ if( aResult >>= xBM )
+ aData = xBM->getDIB();
+ }
+ catch(...)
+ {
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "exception in bitmap converter\n" );
+#endif
+ }
+ aGuard.reset();
+ }
+ // get pixmap again since clearing the guard could have invalidated
+ // the pixmap in another thread
+ pPixmap = getPixmapHolder( selection );
+ nValue = (XID)pPixmap->setBitmapData( (const sal_uInt8*)aData.getConstArray() );
+ }
+ if( nValue == None )
+ return false;
+ }
+ if( target == XA_BITMAP )
+ nValue = (XID)pPixmap->getBitmap();
+ }
+
+ XChangeProperty( m_pDisplay,
+ requestor,
+ property,
+ target,
+ 32,
+ PropModeReplace,
+ (const unsigned char*)&nValue,
+ 1);
+ return true;
+ }
+
+ /*
+ * special target TEXT allows us to transfer
+ * the data in an encoding of our choice
+ * COMPOUND_TEXT will work with most applications
+ */
+ if( target == m_nTEXTAtom )
+ target = m_nCOMPOUNDAtom;
+
+ Sequence< sal_Int8 > aData;
+ int nFormat;
+ aGuard.clear();
+ bool bConverted = convertData( pAdaptor->getTransferable(), target, selection, nFormat, aData );
+ aGuard.reset();
+ if( bConverted )
+ {
+ // conversion succeeded
+ if( aData.getLength() > m_nIncrementalThreshold )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "using INCR protocol\n" );
+ std::hash_map< Window, std::hash_map< Atom, IncrementalTransfer > >::const_iterator win_it = m_aIncrementals.find( requestor );
+ if( win_it != m_aIncrementals.end() )
+ {
+ std::hash_map< Atom, IncrementalTransfer >::const_iterator inc_it = win_it->second.find( property );
+ if( inc_it != win_it->second.end() )
+ {
+ const IncrementalTransfer& rInc = inc_it->second;
+ fprintf( stderr, "premature end and new start for INCR transfer for window 0x%lx, property %s, type %s\n",
+ rInc.m_aRequestor,
+ OUStringToOString( getString( rInc.m_aProperty ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
+ OUStringToOString( getString( rInc.m_aTarget ), RTL_TEXTENCODING_ISO_8859_1 ).getStr()
+ );
+ }
+ }
+#endif
+
+ // insert IncrementalTransfer
+ IncrementalTransfer& rInc = m_aIncrementals[ requestor ][ property ];
+ rInc.m_aData = aData;
+ rInc.m_nBufferPos = 0;
+ rInc.m_aRequestor = requestor;
+ rInc.m_aProperty = property;
+ rInc.m_aTarget = target;
+ rInc.m_nFormat = nFormat;
+ rInc.m_nTransferStartTime = time( NULL );
+
+ // use incr protocol, signal start to requestor
+ long nMinSize = m_nIncrementalThreshold;
+ XSelectInput( m_pDisplay, requestor, PropertyChangeMask );
+ XChangeProperty( m_pDisplay, requestor, property,
+ m_nINCRAtom, 32, PropModeReplace, (unsigned char*)&nMinSize, 1 );
+ XFlush( m_pDisplay );
+ }
+ else
+ {
+ sal_Size nUnitSize = GetTrueFormatSize(nFormat);
+ XChangeProperty( m_pDisplay,
+ requestor,
+ property,
+ target,
+ nFormat,
+ PropModeReplace,
+ (const unsigned char*)aData.getConstArray(),
+ aData.getLength()/nUnitSize );
+ }
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ fprintf( stderr, "convertData failed for type: %s \n",
+ OUStringToOString( convertTypeFromNative( target, selection, nFormat ), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
+#endif
+ return bConverted;
+}
+
+// ------------------------------------------------------------------------
+
+bool SelectionManager::handleSelectionRequest( XSelectionRequestEvent& rRequest )
+{
+ ResettableMutexGuard aGuard( m_aMutex );
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "handleSelectionRequest for selection %s and target %s\n",
+ OUStringToOString( getString( rRequest.selection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
+ OUStringToOString( getString( rRequest.target ), RTL_TEXTENCODING_ISO_8859_1 ).getStr()
+ );
+#endif
+
+ XEvent aNotify;
+
+ aNotify.type = SelectionNotify;
+ aNotify.xselection.display = rRequest.display;
+ aNotify.xselection.send_event = True;
+ aNotify.xselection.requestor = rRequest.requestor;
+ aNotify.xselection.selection = rRequest.selection;
+ aNotify.xselection.time = rRequest.time;
+ aNotify.xselection.target = rRequest.target;
+ aNotify.xselection.property = None;
+
+ SelectionAdaptor* pAdaptor = getAdaptor( rRequest.selection );
+ // ensure that we still own that selection
+ if( pAdaptor &&
+ XGetSelectionOwner( m_pDisplay, rRequest.selection ) == m_aWindow )
+ {
+ Reference< XTransferable > xTrans( pAdaptor->getTransferable() );
+ if( rRequest.target == m_nTARGETSAtom )
+ {
+ // someone requests our types
+ if( xTrans.is() )
+ {
+ aGuard.clear();
+ Sequence< DataFlavor > aFlavors = xTrans->getTransferDataFlavors();
+ aGuard.reset();
+
+ ::std::list< Atom > aConversions;
+ getNativeTypeList( aFlavors, aConversions, rRequest.selection );
+
+ int i, nTypes = aConversions.size();
+ Atom* pTypes = (Atom*)alloca( nTypes * sizeof( Atom ) );
+ std::list< Atom >::const_iterator it;
+ for( i = 0, it = aConversions.begin(); i < nTypes; i++, ++it )
+ pTypes[i] = *it;
+ XChangeProperty( m_pDisplay, rRequest.requestor, rRequest.property,
+ XA_ATOM, 32, PropModeReplace, (const unsigned char*)pTypes, nTypes );
+ aNotify.xselection.property = rRequest.property;
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "sending type list:\n" );
+ for( int k = 0; k < nTypes; k++ )
+ fprintf( stderr, " %s\n", pTypes[k] ? XGetAtomName( m_pDisplay, pTypes[k] ) : "<None>" );
+#endif
+ }
+ }
+ else if( rRequest.target == m_nTIMESTAMPAtom )
+ {
+ long nTimeStamp = (long)m_aSelections[rRequest.selection]->m_nOrigTimestamp;
+ XChangeProperty( m_pDisplay, rRequest.requestor, rRequest.property,
+ XA_INTEGER, 32, PropModeReplace, (const unsigned char*)&nTimeStamp, 1 );
+ aNotify.xselection.property = rRequest.property;
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "sending timestamp: %d\n", (int)nTimeStamp );
+#endif
+ }
+ else
+ {
+ bool bEventSuccess = false;
+ if( rRequest.target == m_nMULTIPLEAtom )
+ {
+ // get all targets
+ Atom nType = None;
+ int nFormat = 0;
+ unsigned long nItems = 0, nBytes = 0;
+ unsigned char* pData = NULL;
+
+ // get number of atoms
+ XGetWindowProperty( m_pDisplay,
+ rRequest.requestor,
+ rRequest.property,
+ 0, 0,
+ False,
+ AnyPropertyType,
+ &nType, &nFormat,
+ &nItems, &nBytes,
+ &pData );
+ if( nFormat == 32 && nBytes/4 )
+ {
+ if( pData ) // ?? should not happen
+ {
+ XFree( pData );
+ pData = NULL;
+ }
+ XGetWindowProperty( m_pDisplay,
+ rRequest.requestor,
+ rRequest.property,
+ 0, nBytes/4,
+ False,
+ nType,
+ &nType, &nFormat,
+ &nItems, &nBytes,
+ &pData );
+ if( pData && nItems )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "found %ld atoms in MULTIPLE request\n", nItems );
+#endif
+ bEventSuccess = true;
+ bool bResetAtoms = false;
+ Atom* pAtoms = (Atom*)pData;
+ aGuard.clear();
+ for( unsigned int i = 0; i < nItems; i += 2 )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, " %s => %s: ",
+ OUStringToOString( getString( pAtoms[i] ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
+ OUStringToOString( getString( pAtoms[i+1] ), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
+#endif
+ bool bSuccess = sendData( pAdaptor, rRequest.requestor, pAtoms[i], pAtoms[i+1], rRequest.selection );
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "%s\n", bSuccess ? "succeeded" : "failed" );
+#endif
+ if( ! bSuccess )
+ {
+ pAtoms[i] = None;
+ bResetAtoms = true;
+ }
+ }
+ aGuard.reset();
+ if( bResetAtoms )
+ XChangeProperty( m_pDisplay,
+ rRequest.requestor,
+ rRequest.property,
+ XA_ATOM,
+ 32,
+ PropModeReplace,
+ pData,
+ nBytes/4 );
+ }
+ if( pData )
+ XFree( pData );
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ fprintf( stderr, "could not get type list from \"%s\" of type \"%s\" on requestor 0x%lx, requestor has properties:",
+ OUStringToOString( getString( rRequest.property ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
+ OUStringToOString( getString( nType ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
+ rRequest.requestor );
+ int nProps = 0;
+ Atom* pProps = XListProperties( m_pDisplay, rRequest.requestor, &nProps );
+ if( pProps )
+ {
+ for( int i = 0; i < nProps; i++ )
+ fprintf( stderr, " \"%s\"", OUStringToOString( getString( pProps[i]), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
+ XFree( pProps );
+ }
+ }
+#endif
+ }
+ else
+ {
+ aGuard.clear();
+ bEventSuccess = sendData( pAdaptor, rRequest.requestor, rRequest.target, rRequest.property, rRequest.selection );
+ aGuard.reset();
+ }
+ if( bEventSuccess )
+ {
+ aNotify.xselection.target = rRequest.target;
+ aNotify.xselection.property = rRequest.property;
+ }
+ }
+ aGuard.clear();
+ xTrans.clear();
+ aGuard.reset();
+ }
+ XSendEvent( m_pDisplay, rRequest.requestor, False, 0, &aNotify );
+
+ if( rRequest.selection == XA_PRIMARY &&
+ m_bWaitingForPrimaryConversion &&
+ m_xDragSourceListener.is() )
+ {
+ DragSourceDropEvent dsde;
+ dsde.Source = static_cast< OWeakObject* >(this);
+ dsde.DragSourceContext = new DragSourceContext( m_aDropWindow, rRequest.time, *this );
+ dsde.DragSource = static_cast< XDragSource* >(this);
+ if( aNotify.xselection.property != None )
+ {
+ dsde.DropAction = DNDConstants::ACTION_COPY;
+ dsde.DropSuccess = sal_True;
+ }
+ else
+ {
+ dsde.DropAction = DNDConstants::ACTION_NONE;
+ dsde.DropSuccess = sal_False;
+ }
+ Reference< XDragSourceListener > xListener( m_xDragSourceListener );
+ m_xDragSourceListener.clear();
+ aGuard.clear();
+ if( xListener.is() )
+ xListener->dragDropEnd( dsde );
+ }
+
+ // we handled the event in any case by answering
+ return true;
+}
+
+// ------------------------------------------------------------------------
+
+bool SelectionManager::handleReceivePropertyNotify( XPropertyEvent& rNotify )
+{
+ MutexGuard aGuard( m_aMutex );
+ // data we requested arrived
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "handleReceivePropertyNotify for property %s\n",
+ OUStringToOString( getString( rNotify.atom ), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
+#endif
+ bool bHandled = false;
+
+ ::std::hash_map< Atom, Selection* >::iterator it =
+ m_aSelections.find( rNotify.atom );
+ if( it != m_aSelections.end() &&
+ rNotify.state == PropertyNewValue &&
+ ( it->second->m_eState == Selection::WaitingForResponse ||
+ it->second->m_eState == Selection::WaitingForData ||
+ it->second->m_eState == Selection::IncrementalTransfer
+ )
+ )
+ {
+ // MULTIPLE requests are only complete after selection notify
+ if( it->second->m_aRequestedType == m_nMULTIPLEAtom &&
+ ( it->second->m_eState == Selection::WaitingForResponse ||
+ it->second->m_eState == Selection::WaitingForData ) )
+ return false;
+
+ bHandled = true;
+
+ Atom nType = None;
+ int nFormat = 0;
+ unsigned long nItems = 0, nBytes = 0;
+ unsigned char* pData = NULL;
+
+ // get type and length
+ XGetWindowProperty( m_pDisplay,
+ rNotify.window,
+ rNotify.atom,
+ 0, 0,
+ False,
+ AnyPropertyType,
+ &nType, &nFormat,
+ &nItems, &nBytes,
+ &pData );
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "found %ld bytes data of type %s and format %d, items = %ld\n",
+ nBytes,
+ OUStringToOString( getString( nType ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
+ nFormat, nItems );
+#endif
+ if( pData )
+ {
+ XFree( pData );
+ pData = NULL;
+ }
+
+ if( nType == m_nINCRAtom )
+ {
+ // start data transfer
+ XDeleteProperty( m_pDisplay, rNotify.window, rNotify.atom );
+ it->second->m_eState = Selection::IncrementalTransfer;
+ }
+ else if( nType != None )
+ {
+ XGetWindowProperty( m_pDisplay,
+ rNotify.window,
+ rNotify.atom,
+ 0, nBytes/4 +1,
+ True,
+ nType,
+ &nType, &nFormat,
+ &nItems, &nBytes,
+ &pData );
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "read %ld items data of type %s and format %d, %ld bytes left in property\n",
+ nItems,
+ OUStringToOString( getString( nType ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
+ nFormat, nBytes );
+#endif
+
+ sal_Size nUnitSize = GetTrueFormatSize(nFormat);
+
+ if( it->second->m_eState == Selection::WaitingForData ||
+ it->second->m_eState == Selection::WaitingForResponse )
+ {
+ // copy data
+ it->second->m_aData = Sequence< sal_Int8 >( (sal_Int8*)pData, nItems*nUnitSize );
+ it->second->m_eState = Selection::Inactive;
+ it->second->m_aDataArrived.set();
+ }
+ else if( it->second->m_eState == Selection::IncrementalTransfer )
+ {
+ if( nItems )
+ {
+ // append data
+ Sequence< sal_Int8 > aData( it->second->m_aData.getLength() + nItems*nUnitSize );
+ memcpy( aData.getArray(), it->second->m_aData.getArray(), it->second->m_aData.getLength() );
+ memcpy( aData.getArray() + it->second->m_aData.getLength(), pData, nItems*nUnitSize );
+ it->second->m_aData = aData;
+ }
+ else
+ {
+ it->second->m_eState = Selection::Inactive;
+ it->second->m_aDataArrived.set();
+ }
+ }
+ if( pData )
+ XFree( pData );
+ }
+ else if( it->second->m_eState == Selection::IncrementalTransfer )
+ {
+ it->second->m_eState = Selection::Inactive;
+ it->second->m_aDataArrived.set();
+ }
+ }
+ return bHandled;
+}
+
+// ------------------------------------------------------------------------
+
+bool SelectionManager::handleSendPropertyNotify( XPropertyEvent& rNotify )
+{
+ MutexGuard aGuard( m_aMutex );
+
+ // ready for next part of a IncrementalTransfer
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "handleSendPropertyNotify for property %s (%s)\n",
+ OUStringToOString( getString( rNotify.atom ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
+ rNotify.state == PropertyNewValue ? "new value" : ( rNotify.state == PropertyDelete ? "deleted" : "unknown")
+ );
+#endif
+
+ bool bHandled = false;
+ // feed incrementals
+ if( rNotify.state == PropertyDelete )
+ {
+ std::hash_map< Window, std::hash_map< Atom, IncrementalTransfer > >::iterator it;
+ it = m_aIncrementals.find( rNotify.window );
+ if( it != m_aIncrementals.end() )
+ {
+ bHandled = true;
+ int nCurrentTime = time( NULL );
+ std::hash_map< Atom, IncrementalTransfer >::iterator inc_it;
+ // throw out aborted transfers
+ std::list< Atom > aTimeouts;
+ for( inc_it = it->second.begin(); inc_it != it->second.end(); ++inc_it )
+ {
+ if( (nCurrentTime - inc_it->second.m_nTransferStartTime) > (getSelectionTimeout()+2) )
+ {
+ aTimeouts.push_back( inc_it->first );
+#if OSL_DEBUG_LEVEL > 1
+ const IncrementalTransfer& rInc = inc_it->second;
+ fprintf( stderr, "timeout on INCR transfer for window 0x%lx, property %s, type %s\n",
+ rInc.m_aRequestor,
+ OUStringToOString( getString( rInc.m_aProperty ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
+ OUStringToOString( getString( rInc.m_aTarget ), RTL_TEXTENCODING_ISO_8859_1 ).getStr()
+ );
+#endif
+ }
+ }
+
+ while( aTimeouts.begin() != aTimeouts.end() )
+ {
+ // transfer broken, might even be a new client with the
+ // same window id
+ it->second.erase( aTimeouts.front() );
+ aTimeouts.pop_front();
+ }
+
+ inc_it = it->second.find( rNotify.atom );
+ if( inc_it != it->second.end() )
+ {
+ IncrementalTransfer& rInc = inc_it->second;
+
+ int nBytes = rInc.m_aData.getLength() - rInc.m_nBufferPos;
+ nBytes = (nBytes > m_nIncrementalThreshold) ? m_nIncrementalThreshold : nBytes;
+ if( nBytes < 0 ) // sanity check
+ nBytes = 0;
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "pushing %d bytes: \"%.*s\"...\n",
+ nBytes, nBytes > 32 ? 32 : nBytes,
+ (const unsigned char*)rInc.m_aData.getConstArray()+rInc.m_nBufferPos );
+#endif
+
+ sal_Size nUnitSize = GetTrueFormatSize(rInc.m_nFormat);
+
+ XChangeProperty( m_pDisplay,
+ rInc.m_aRequestor,
+ rInc.m_aProperty,
+ rInc.m_aTarget,
+ rInc.m_nFormat,
+ PropModeReplace,
+ (const unsigned char*)rInc.m_aData.getConstArray()+rInc.m_nBufferPos,
+ nBytes/nUnitSize );
+ rInc.m_nBufferPos += nBytes;
+ rInc.m_nTransferStartTime = nCurrentTime;
+
+ if( nBytes == 0 ) // transfer finished
+ {
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "finished INCR transfer for window 0x%lx, property %s, type %s\n",
+ rInc.m_aRequestor,
+ OUStringToOString( getString( rInc.m_aProperty ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
+ OUStringToOString( getString( rInc.m_aTarget ), RTL_TEXTENCODING_ISO_8859_1 ).getStr()
+ );
+#endif
+ it->second.erase( inc_it );
+ }
+
+ }
+ // eventually clean up the hash map
+ if( it->second.begin() == it->second.end() )
+ m_aIncrementals.erase( it );
+ }
+ }
+ return bHandled;
+}
+
+// ------------------------------------------------------------------------
+
+bool SelectionManager::handleSelectionNotify( XSelectionEvent& rNotify )
+{
+ MutexGuard aGuard( m_aMutex );
+
+ bool bHandled = false;
+
+ // notification about success/failure of one of our conversion requests
+#if OSL_DEBUG_LEVEL > 1
+ OUString aSelection( getString( rNotify.selection ) );
+ OUString aProperty( OUString::createFromAscii( "None" ) );
+ if( rNotify.property )
+ aProperty = getString( rNotify.property );
+ fprintf( stderr, "handleSelectionNotify for selection %s and property %s (0x%lx)\n",
+ OUStringToOString( aSelection, RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
+ OUStringToOString( aProperty, RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
+ rNotify.property
+ );
+ if( rNotify.requestor != m_aWindow && rNotify.requestor != m_aCurrentDropWindow )
+ fprintf( stderr, "Warning: selection notify for unknown window 0x%lx\n", rNotify.requestor );
+#endif
+ ::std::hash_map< Atom, Selection* >::iterator it =
+ m_aSelections.find( rNotify.selection );
+ if (
+ (rNotify.requestor == m_aWindow || rNotify.requestor == m_aCurrentDropWindow) &&
+ it != m_aSelections.end() &&
+ (
+ (it->second->m_eState == Selection::WaitingForResponse) ||
+ (it->second->m_eState == Selection::WaitingForData)
+ )
+ )
+ {
+ bHandled = true;
+ if( it->second->m_aRequestedType == m_nMULTIPLEAtom )
+ {
+ Atom nType = None;
+ int nFormat = 0;
+ unsigned long nItems = 0, nBytes = 0;
+ unsigned char* pData = NULL;
+
+ // get type and length
+ XGetWindowProperty( m_pDisplay,
+ rNotify.requestor,
+ rNotify.property,
+ 0, 256,
+ False,
+ AnyPropertyType,
+ &nType, &nFormat,
+ &nItems, &nBytes,
+ &pData );
+ if( nBytes ) // HUGE request !!!
+ {
+ if( pData )
+ XFree( pData );
+ XGetWindowProperty( m_pDisplay,
+ rNotify.requestor,
+ rNotify.property,
+ 0, 256+(nBytes+3)/4,
+ False,
+ AnyPropertyType,
+ &nType, &nFormat,
+ &nItems, &nBytes,
+ &pData );
+ }
+ it->second->m_eState = Selection::Inactive;
+ sal_Size nUnitSize = GetTrueFormatSize(nFormat);
+ it->second->m_aData = Sequence< sal_Int8 >((sal_Int8*)pData, nItems * nUnitSize);
+ it->second->m_aDataArrived.set();
+ if( pData )
+ XFree( pData );
+ }
+ // WaitingForData can actually happen; some
+ // applications (e.g. cmdtool on Solaris) first send
+ // a success and then cancel it. Weird !
+ else if( rNotify.property == None )
+ {
+ // conversion failed, stop transfer
+ it->second->m_eState = Selection::Inactive;
+ it->second->m_aData = Sequence< sal_Int8 >();
+ it->second->m_aDataArrived.set();
+ }
+ // get the bytes, by INCR if necessary
+ else
+ it->second->m_eState = Selection::WaitingForData;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else if( it != m_aSelections.end() )
+ fprintf( stderr, "Warning: selection in state %d\n", it->second->m_eState );
+#endif
+ return bHandled;
+}
+
+// ------------------------------------------------------------------------
+
+bool SelectionManager::handleDropEvent( XClientMessageEvent& rMessage )
+{
+ ResettableMutexGuard aGuard(m_aMutex);
+
+ // handle drop related events
+ Window aSource = rMessage.data.l[0];
+ Window aTarget = rMessage.window;
+
+ bool bHandled = false;
+
+ ::std::hash_map< Window, DropTargetEntry >::iterator it =
+ m_aDropTargets.find( aTarget );
+
+#if OSL_DEBUG_LEVEL > 1
+ if( rMessage.message_type == m_nXdndEnter ||
+ rMessage.message_type == m_nXdndLeave ||
+ rMessage.message_type == m_nXdndDrop ||
+ rMessage.message_type == m_nXdndPosition )
+ {
+ fprintf( stderr, "got drop event %s, ", OUStringToOString( getString( rMessage.message_type ), RTL_TEXTENCODING_ASCII_US).getStr() );
+ if( it == m_aDropTargets.end() )
+ fprintf( stderr, "but no target found\n" );
+ else if( ! it->second.m_pTarget->m_bActive )
+ fprintf( stderr, "but target is inactive\n" );
+ else if( m_aDropEnterEvent.data.l[0] != None && (Window)m_aDropEnterEvent.data.l[0] != aSource )
+ fprintf( stderr, "but source 0x%lx is unknown (expected 0x%lx or 0)\n", aSource, m_aDropEnterEvent.data.l[0] );
+ else
+ fprintf( stderr, "processing.\n" );
+ }
+#endif
+
+ if( it != m_aDropTargets.end() && it->second.m_pTarget->m_bActive &&
+ m_bDropWaitingForCompletion && m_aDropEnterEvent.data.l[0] )
+ {
+ bHandled = true;
+ OSL_ENSURE( 0, "someone forgot to call dropComplete ?" );
+ // some listener forgot to call dropComplete in the last operation
+ // let us end it now and accept the new enter event
+ aGuard.clear();
+ dropComplete( sal_False, m_aCurrentDropWindow, m_nDropTime );
+ aGuard.reset();
+ }
+
+ if( it != m_aDropTargets.end() &&
+ it->second.m_pTarget->m_bActive &&
+ ( m_aDropEnterEvent.data.l[0] == None || Window(m_aDropEnterEvent.data.l[0]) == aSource )
+ )
+ {
+ if( rMessage.message_type == m_nXdndEnter )
+ {
+ bHandled = true;
+ m_aDropEnterEvent = rMessage;
+ m_bDropEnterSent = false;
+ m_aCurrentDropWindow = aTarget;
+ m_nCurrentProtocolVersion = m_aDropEnterEvent.data.l[1] >> 24;
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "received XdndEnter on 0x%lx\n", aTarget );
+#endif
+ }
+ else if(
+ rMessage.message_type == m_nXdndPosition &&
+ aSource == Window(m_aDropEnterEvent.data.l[0])
+ )
+ {
+ bHandled = true;
+ m_nDropTime = m_nCurrentProtocolVersion > 0 ? rMessage.data.l[3] : CurrentTime;
+ if( ! m_bDropEnterSent )
+ m_nDropTimestamp = m_nDropTime;
+
+ Window aChild;
+ XTranslateCoordinates( m_pDisplay,
+ it->second.m_aRootWindow,
+ it->first,
+ rMessage.data.l[2] >> 16,
+ rMessage.data.l[2] & 0xffff,
+ &m_nLastX, &m_nLastY,
+ &aChild );
+
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "received XdndPosition on 0x%lx (%d, %d)\n", aTarget, m_nLastX, m_nLastY );
+#endif
+ DropTargetDragEnterEvent aEvent;
+ aEvent.Source = static_cast< XDropTarget* >(it->second.m_pTarget);
+ aEvent.Context = new DropTargetDragContext( m_aCurrentDropWindow, m_nDropTimestamp, *this );
+ aEvent.LocationX = m_nLastX;
+ aEvent.LocationY = m_nLastY;
+ aEvent.SourceActions = m_nSourceActions;
+ if( m_nCurrentProtocolVersion < 2 )
+ aEvent.DropAction = DNDConstants::ACTION_COPY;
+ else if( Atom(rMessage.data.l[4]) == m_nXdndActionCopy )
+ aEvent.DropAction = DNDConstants::ACTION_COPY;
+ else if( Atom(rMessage.data.l[4]) == m_nXdndActionMove )
+ aEvent.DropAction = DNDConstants::ACTION_MOVE;
+ else if( Atom(rMessage.data.l[4]) == m_nXdndActionLink )
+ aEvent.DropAction = DNDConstants::ACTION_LINK;
+ else if( Atom(rMessage.data.l[4]) == m_nXdndActionAsk )
+ // currently no interface to implement ask
+ aEvent.DropAction = ~0;
+ else
+ aEvent.DropAction = DNDConstants::ACTION_NONE;
+
+ m_nLastDropAction = aEvent.DropAction;
+ if( ! m_bDropEnterSent )
+ {
+ m_bDropEnterSent = true;
+ aEvent.SupportedDataFlavors = m_xDropTransferable->getTransferDataFlavors();
+ aGuard.clear();
+ it->second->dragEnter( aEvent );
+ }
+ else
+ {
+ aGuard.clear();
+ it->second->dragOver( aEvent );
+ }
+ }
+ else if(
+ rMessage.message_type == m_nXdndLeave &&
+ aSource == Window(m_aDropEnterEvent.data.l[0])
+ )
+ {
+ bHandled = true;
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "received XdndLeave on 0x%lx\n", aTarget );
+#endif
+ DropTargetEvent aEvent;
+ aEvent.Source = static_cast< XDropTarget* >(it->second.m_pTarget);
+ m_aDropEnterEvent.data.l[0] = None;
+ if( m_aCurrentDropWindow == aTarget )
+ m_aCurrentDropWindow = None;
+ m_nCurrentProtocolVersion = nXdndProtocolRevision;
+ aGuard.clear();
+ it->second->dragExit( aEvent );
+ }
+ else if(
+ rMessage.message_type == m_nXdndDrop &&
+ aSource == Window(m_aDropEnterEvent.data.l[0])
+ )
+ {
+ bHandled = true;
+ m_nDropTime = m_nCurrentProtocolVersion > 0 ? rMessage.data.l[2] : CurrentTime;
+
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "received XdndDrop on 0x%lx (%d, %d)\n", aTarget, m_nLastX, m_nLastY );
+#endif
+ if( m_bLastDropAccepted )
+ {
+ DropTargetDropEvent aEvent;
+ aEvent.Source = static_cast< XDropTarget* >(it->second.m_pTarget);
+ aEvent.Context = new DropTargetDropContext( m_aCurrentDropWindow, m_nDropTimestamp, *this );
+ aEvent.LocationX = m_nLastX;
+ aEvent.LocationY = m_nLastY;
+ aEvent.DropAction = m_nLastDropAction;
+ // there is nothing corresponding to source supported actions
+ // every source can do link, copy and move
+ aEvent.SourceActions= m_nLastDropAction;
+ aEvent.Transferable = m_xDropTransferable;
+
+ m_bDropWaitingForCompletion = true;
+ aGuard.clear();
+ it->second->drop( aEvent );
+ }
+ else
+ {
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "XdndDrop canceled due to m_bLastDropAccepted = fale\n" );
+#endif
+ DropTargetEvent aEvent;
+ aEvent.Source = static_cast< XDropTarget* >(it->second.m_pTarget);
+ aGuard.clear();
+ it->second->dragExit( aEvent );
+ // reset the drop status, notify source
+ dropComplete( sal_False, m_aCurrentDropWindow, m_nDropTime );
+ }
+ }
+ }
+ return bHandled;
+}
+
+/*
+ * methods for XDropTargetDropContext
+ */
+
+void SelectionManager::dropComplete( sal_Bool bSuccess, Window aDropWindow, Time )
+{
+ ClearableMutexGuard aGuard(m_aMutex);
+
+ if( aDropWindow == m_aCurrentDropWindow )
+ {
+ if( m_xDragSourceListener.is() )
+ {
+ DragSourceDropEvent dsde;
+ dsde.Source = static_cast< OWeakObject* >(this);
+ dsde.DragSourceContext = new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
+ dsde.DragSource = static_cast< XDragSource* >(this);
+ dsde.DropAction = getUserDragAction();
+ dsde.DropSuccess = bSuccess;
+ Reference< XDragSourceListener > xListener = m_xDragSourceListener;
+ m_xDragSourceListener.clear();
+
+ aGuard.clear();
+ xListener->dragDropEnd( dsde );
+ }
+ else if( m_aDropEnterEvent.data.l[0] && m_aCurrentDropWindow )
+ {
+ XEvent aEvent;
+ aEvent.xclient.type = ClientMessage;
+ aEvent.xclient.display = m_pDisplay;
+ aEvent.xclient.window = m_aDropEnterEvent.data.l[0];
+ aEvent.xclient.message_type = m_nXdndFinished;
+ aEvent.xclient.format = 32;
+ aEvent.xclient.data.l[0] = m_aCurrentDropWindow;
+ aEvent.xclient.data.l[1] = bSuccess ? 1 : 0;
+ aEvent.xclient.data.l[2] = 0;
+ aEvent.xclient.data.l[3] = 0;
+ aEvent.xclient.data.l[4] = 0;
+ if( bSuccess )
+ {
+ if( m_nLastDropAction & DNDConstants::ACTION_MOVE )
+ aEvent.xclient.data.l[2] = m_nXdndActionMove;
+ else if( m_nLastDropAction & DNDConstants::ACTION_COPY )
+ aEvent.xclient.data.l[2] = m_nXdndActionCopy;
+ else if( m_nLastDropAction & DNDConstants::ACTION_LINK )
+ aEvent.xclient.data.l[2] = m_nXdndActionLink;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "Sending XdndFinished to 0x%lx\n",
+ m_aDropEnterEvent.data.l[0]
+ );
+#endif
+
+ XSendEvent( m_pDisplay, m_aDropEnterEvent.data.l[0],
+ False, NoEventMask, & aEvent );
+
+ m_aDropEnterEvent.data.l[0] = None;
+ m_aCurrentDropWindow = None;
+ m_nCurrentProtocolVersion = nXdndProtocolRevision;
+ }
+ m_bDropWaitingForCompletion = false;
+ }
+ else
+ OSL_ASSERT( "dropComplete from invalid DropTargetDropContext" );
+}
+
+/*
+ * methods for XDropTargetDragContext
+ */
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::sendDragStatus( Atom nDropAction )
+{
+ ClearableMutexGuard aGuard(m_aMutex);
+
+ if( m_xDragSourceListener.is() )
+ {
+ sal_Int8 nNewDragAction;
+ if( nDropAction == m_nXdndActionMove )
+ nNewDragAction = DNDConstants::ACTION_MOVE;
+ else if( nDropAction == m_nXdndActionCopy )
+ nNewDragAction = DNDConstants::ACTION_COPY;
+ else if( nDropAction == m_nXdndActionLink )
+ nNewDragAction = DNDConstants::ACTION_LINK;
+ else
+ nNewDragAction = DNDConstants::ACTION_NONE;
+ nNewDragAction &= m_nSourceActions;
+
+ if( nNewDragAction != m_nTargetAcceptAction )
+ {
+ setCursor( getDefaultCursor( nNewDragAction ), m_aDropWindow, m_nDragTimestamp );
+ m_nTargetAcceptAction = nNewDragAction;
+ }
+
+ DragSourceDragEvent dsde;
+ dsde.Source = static_cast< OWeakObject* >(this);
+ dsde.DragSourceContext = new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
+ dsde.DragSource = static_cast< XDragSource* >(this);
+ dsde.DropAction = m_nSourceActions;
+ dsde.UserAction = getUserDragAction();
+
+ Reference< XDragSourceListener > xListener( m_xDragSourceListener );
+ // caution: do not change anything after this
+ aGuard.clear();
+ if( xListener.is() )
+ xListener->dragOver( dsde );
+ }
+ else if( m_aDropEnterEvent.data.l[0] && m_aCurrentDropWindow )
+ {
+ XEvent aEvent;
+ aEvent.xclient.type = ClientMessage;
+ aEvent.xclient.display = m_pDisplay;
+ aEvent.xclient.window = m_aDropEnterEvent.data.l[0];
+ aEvent.xclient.message_type = m_nXdndStatus;
+ aEvent.xclient.format = 32;
+ aEvent.xclient.data.l[0] = m_aCurrentDropWindow;
+ aEvent.xclient.data.l[1] = 2;
+ if( nDropAction == m_nXdndActionMove ||
+ nDropAction == m_nXdndActionLink ||
+ nDropAction == m_nXdndActionCopy )
+ aEvent.xclient.data.l[1] |= 1;
+ aEvent.xclient.data.l[2] = 0;
+ aEvent.xclient.data.l[3] = 0;
+ aEvent.xclient.data.l[4] = m_nCurrentProtocolVersion > 1 ? nDropAction : 0;
+
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "Sending XdndStatus to 0x%lx with action %s\n",
+ m_aDropEnterEvent.data.l[0],
+ OUStringToOString( getString( nDropAction ), RTL_TEXTENCODING_ISO_8859_1 ).getStr()
+ );
+#endif
+
+ XSendEvent( m_pDisplay, m_aDropEnterEvent.data.l[0],
+ False, NoEventMask, & aEvent );
+ XFlush( m_pDisplay );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+sal_Int8 SelectionManager::getUserDragAction() const
+{
+ return (m_nTargetAcceptAction != DNDConstants::ACTION_DEFAULT) ? m_nTargetAcceptAction : m_nUserDragAction;
+}
+
+// ------------------------------------------------------------------------
+
+bool SelectionManager::updateDragAction( int modifierState )
+{
+ bool bRet = false;
+
+ sal_Int8 nNewDropAction = DNDConstants::ACTION_MOVE;
+ if( ( modifierState & ShiftMask ) && ! ( modifierState & ControlMask ) )
+ nNewDropAction = DNDConstants::ACTION_MOVE;
+ else if( ( modifierState & ControlMask ) && ! ( modifierState & ShiftMask ) )
+ nNewDropAction = DNDConstants::ACTION_COPY;
+ else if( ( modifierState & ShiftMask ) && ( modifierState & ControlMask ) )
+ nNewDropAction = DNDConstants::ACTION_LINK;
+ if( m_nCurrentProtocolVersion < 0 && m_aDropWindow != None )
+ nNewDropAction = DNDConstants::ACTION_COPY;
+ nNewDropAction &= m_nSourceActions;
+
+ if( ! ( modifierState & ( ControlMask | ShiftMask ) ) )
+ {
+ if( ! nNewDropAction )
+ {
+ // default to an action so the user does not have to press
+ // keys explicitly
+ if( m_nSourceActions & DNDConstants::ACTION_MOVE )
+ nNewDropAction = DNDConstants::ACTION_MOVE;
+ else if( m_nSourceActions & DNDConstants::ACTION_COPY )
+ nNewDropAction = DNDConstants::ACTION_COPY;
+ else if( m_nSourceActions & DNDConstants::ACTION_LINK )
+ nNewDropAction = DNDConstants::ACTION_LINK;
+ }
+ nNewDropAction |= DNDConstants::ACTION_DEFAULT;
+ }
+
+ if( nNewDropAction != m_nUserDragAction || m_nTargetAcceptAction != DNDConstants::ACTION_DEFAULT )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "updateDragAction: %x -> %x\n", (int)m_nUserDragAction, (int)nNewDropAction );
+#endif
+ bRet = true;
+ m_nUserDragAction = nNewDropAction;
+
+ DragSourceDragEvent dsde;
+ dsde.Source = static_cast< OWeakObject* >(this);
+ dsde.DragSourceContext = new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
+ dsde.DragSource = static_cast< XDragSource* >(this);
+ dsde.DropAction = m_nUserDragAction;
+ dsde.UserAction = m_nUserDragAction;
+ m_nTargetAcceptAction = DNDConstants::ACTION_DEFAULT; // invalidate last accept
+ m_xDragSourceListener->dropActionChanged( dsde );
+ }
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::sendDropPosition( bool bForce, Time eventTime )
+{
+ ClearableMutexGuard aGuard(m_aMutex);
+
+ if( m_bDropSent )
+ return;
+
+ ::std::hash_map< Window, DropTargetEntry >::const_iterator it =
+ m_aDropTargets.find( m_aDropWindow );
+ if( it != m_aDropTargets.end() )
+ {
+ if( it->second.m_pTarget->m_bActive )
+ {
+ int x, y;
+ Window aChild;
+ XTranslateCoordinates( m_pDisplay, it->second.m_aRootWindow, m_aDropWindow, m_nLastDragX, m_nLastDragY, &x, &y, &aChild );
+ DropTargetDragEvent dtde;
+ dtde.Source = static_cast< OWeakObject* >(it->second.m_pTarget );
+ dtde.Context = new DropTargetDragContext( m_aCurrentDropWindow, m_nDropTimestamp, *this );
+ dtde.LocationX = x;
+ dtde.LocationY = y;
+ dtde.DropAction = getUserDragAction();
+ dtde.SourceActions = m_nSourceActions;
+ aGuard.clear();
+ it->second->dragOver( dtde );
+ }
+ }
+ else if( bForce ||
+
+ m_nLastDragX < m_nNoPosX || m_nLastDragX >= m_nNoPosX+m_nNoPosWidth ||
+ m_nLastDragY < m_nNoPosY || m_nLastDragY >= m_nNoPosY+m_nNoPosHeight
+ )
+ {
+ // send XdndPosition
+ XEvent aEvent;
+ aEvent.type = ClientMessage;
+ aEvent.xclient.display = m_pDisplay;
+ aEvent.xclient.format = 32;
+ aEvent.xclient.message_type = m_nXdndPosition;
+ aEvent.xclient.window = m_aDropWindow;
+ aEvent.xclient.data.l[0] = m_aWindow;
+ aEvent.xclient.data.l[1] = 0;
+ aEvent.xclient.data.l[2] = m_nLastDragX << 16 | (m_nLastDragY&0xffff);
+ aEvent.xclient.data.l[3] = eventTime;
+
+ if( m_nUserDragAction & DNDConstants::ACTION_COPY )
+ aEvent.xclient.data.l[4]=m_nXdndActionCopy;
+ else if( m_nUserDragAction & DNDConstants::ACTION_MOVE )
+ aEvent.xclient.data.l[4]=m_nXdndActionMove;
+ else if( m_nUserDragAction & DNDConstants::ACTION_LINK )
+ aEvent.xclient.data.l[4]=m_nXdndActionLink;
+ else
+ aEvent.xclient.data.l[4]=m_nXdndActionCopy;
+ XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
+ m_nNoPosX = m_nNoPosY = m_nNoPosWidth = m_nNoPosHeight = 0;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+bool SelectionManager::handleDragEvent( XEvent& rMessage )
+{
+ if( ! m_xDragSourceListener.is() )
+ return false;
+
+ ResettableMutexGuard aGuard(m_aMutex);
+
+ bool bHandled = false;
+
+ // for shortcut
+ ::std::hash_map< Window, DropTargetEntry >::const_iterator it =
+ m_aDropTargets.find( m_aDropWindow );
+#if OSL_DEBUG_LEVEL > 1
+ switch( rMessage.type )
+ {
+ case ClientMessage:
+ fprintf( stderr, "handleDragEvent: %s\n", OUStringToOString( getString( rMessage.xclient.message_type ), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
+ break;
+ case MotionNotify:
+// fprintf( stderr, "handleDragEvent: MotionNotify\n" );
+ break;
+ case EnterNotify:
+ fprintf( stderr, "handleDragEvent: EnterNotify\n" );
+ break;
+ case LeaveNotify:
+ fprintf( stderr, "handleDragEvent: LeaveNotify\n" );
+ break;
+ case ButtonPress:
+ fprintf( stderr, "handleDragEvent: ButtonPress %d (m_nDragButton = %d)\n", rMessage.xbutton.button, m_nDragButton );
+ break;
+ case ButtonRelease:
+ fprintf( stderr, "handleDragEvent: ButtonRelease %d (m_nDragButton = %d)\n", rMessage.xbutton.button, m_nDragButton );
+ break;
+ case KeyPress:
+ fprintf( stderr, "handleDragEvent: KeyPress\n" );
+ break;
+ case KeyRelease:
+ fprintf( stderr, "handleDragEvent: KeyRelease\n" );
+ break;
+ default:
+ fprintf( stderr, "handleDragEvent: <unknown type %d>\n", rMessage.type );
+ break;
+ }
+#endif
+
+ // handle drag related events
+ if( rMessage.type == ClientMessage )
+ {
+ if( Atom(rMessage.xclient.message_type) == m_nXdndStatus && Atom(rMessage.xclient.data.l[0]) == m_aDropWindow )
+ {
+ bHandled = true;
+ DragSourceDragEvent dsde;
+ dsde.Source = static_cast< OWeakObject* >(this);
+ dsde.DragSourceContext = new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
+ dsde.DragSource = static_cast< XDragSource* >( this );
+ dsde.UserAction = getUserDragAction();
+ dsde.DropAction = DNDConstants::ACTION_NONE;
+ m_bDropSuccess = rMessage.xclient.data.l[1] & 1 ? true : false;
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "status drop action: accept = %s, %s\n",
+ m_bDropSuccess ? "true" : "false",
+ OUStringToOString( getString( rMessage.xclient.data.l[4] ), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
+#endif
+ if( rMessage.xclient.data.l[1] & 1 )
+ {
+ if( m_nCurrentProtocolVersion > 1 )
+ {
+ if( Atom(rMessage.xclient.data.l[4]) == m_nXdndActionCopy )
+ dsde.DropAction = DNDConstants::ACTION_COPY;
+ else if( Atom(rMessage.xclient.data.l[4]) == m_nXdndActionMove )
+ dsde.DropAction = DNDConstants::ACTION_MOVE;
+ else if( Atom(rMessage.xclient.data.l[4]) == m_nXdndActionLink )
+ dsde.DropAction = DNDConstants::ACTION_LINK;
+ }
+ else
+ dsde.DropAction = DNDConstants::ACTION_COPY;
+ }
+ m_nTargetAcceptAction = dsde.DropAction;
+
+ if( ! ( rMessage.xclient.data.l[1] & 2 ) )
+ {
+ m_nNoPosX = rMessage.xclient.data.l[2] >> 16;
+ m_nNoPosY = rMessage.xclient.data.l[2] & 0xffff;
+ m_nNoPosWidth = rMessage.xclient.data.l[3] >> 16;
+ m_nNoPosHeight = rMessage.xclient.data.l[3] & 0xffff;
+ }
+ else
+ m_nNoPosX = m_nNoPosY = m_nNoPosWidth = m_nNoPosHeight = 0;
+
+ setCursor( getDefaultCursor( dsde.DropAction ), m_aDropWindow, m_nDragTimestamp );
+ aGuard.clear();
+ m_xDragSourceListener->dragOver( dsde );
+ }
+ else if( Atom(rMessage.xclient.message_type) == m_nXdndFinished && m_aDropWindow == Atom(rMessage.xclient.data.l[0]) )
+ {
+ bHandled = true;
+ // notify the listener
+ DragSourceDropEvent dsde;
+ dsde.Source = static_cast< OWeakObject* >(this);
+ dsde.DragSourceContext = new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
+ dsde.DragSource = static_cast< XDragSource* >(this);
+ dsde.DropAction = m_nTargetAcceptAction;
+ dsde.DropSuccess = m_bDropSuccess;
+ Reference< XDragSourceListener > xListener( m_xDragSourceListener );
+ m_xDragSourceListener.clear();
+ aGuard.clear();
+ xListener->dragDropEnd( dsde );
+ }
+ }
+ else if( rMessage.type == MotionNotify ||
+ rMessage.type == EnterNotify || rMessage.type == LeaveNotify
+ )
+ {
+ bHandled = true;
+ bool bForce = false;
+ int root_x = rMessage.type == MotionNotify ? rMessage.xmotion.x_root : rMessage.xcrossing.x_root;
+ int root_y = rMessage.type == MotionNotify ? rMessage.xmotion.y_root : rMessage.xcrossing.y_root;
+ Window root = rMessage.type == MotionNotify ? rMessage.xmotion.root : rMessage.xcrossing.root;
+ m_nDragTimestamp = rMessage.type == MotionNotify ? rMessage.xmotion.time : rMessage.xcrossing.time;
+
+ aGuard.clear();
+ if( rMessage.type == MotionNotify )
+ {
+ bForce = updateDragAction( rMessage.xmotion.state );
+ }
+ updateDragWindow( root_x, root_y, root );
+ aGuard.reset();
+
+ if( m_nCurrentProtocolVersion >= 0 && m_aDropProxy != None )
+ {
+ aGuard.clear();
+ sendDropPosition( bForce, rMessage.type == MotionNotify ? rMessage.xmotion.time : rMessage.xcrossing.time );
+ }
+ }
+ else if( rMessage.type == KeyPress || rMessage.type == KeyRelease )
+ {
+ bHandled = true;
+ KeySym aKey = XKeycodeToKeysym( m_pDisplay, rMessage.xkey.keycode, 0 );
+ if( aKey == XK_Escape )
+ {
+ // abort drag
+ if( it != m_aDropTargets.end() )
+ {
+ DropTargetEvent dte;
+ dte.Source = static_cast< OWeakObject* >( it->second.m_pTarget );
+ aGuard.clear();
+ it->second.m_pTarget->dragExit( dte );
+ }
+ else if( m_aDropProxy != None && m_nCurrentProtocolVersion >= 0 )
+ {
+ // send XdndLeave
+ XEvent aEvent;
+ aEvent.type = ClientMessage;
+ aEvent.xclient.display = m_pDisplay;
+ aEvent.xclient.format = 32;
+ aEvent.xclient.message_type = m_nXdndLeave;
+ aEvent.xclient.window = m_aDropWindow;
+ aEvent.xclient.data.l[0] = m_aWindow;
+ memset( aEvent.xclient.data.l+1, 0, sizeof(long)*4);
+ m_aDropWindow = m_aDropProxy = None;
+ XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
+ }
+ // notify the listener
+ DragSourceDropEvent dsde;
+ dsde.Source = static_cast< OWeakObject* >(this);
+ dsde.DragSourceContext = new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
+ dsde.DragSource = static_cast< XDragSource* >(this);
+ dsde.DropAction = DNDConstants::ACTION_NONE;
+ dsde.DropSuccess = sal_False;
+ Reference< XDragSourceListener > xListener( m_xDragSourceListener );
+ m_xDragSourceListener.clear();
+ aGuard.clear();
+ xListener->dragDropEnd( dsde );
+ }
+ else
+ {
+ /*
+ * man page says: state is state immediate PRIOR to the
+ * event. It would seem that this is a somewhat arguable
+ * design decision.
+ */
+ int nState = rMessage.xkey.state;
+ int nNewState = 0;
+ switch( aKey )
+ {
+ case XK_Shift_R:
+ case XK_Shift_L: nNewState = ShiftMask;break;
+ case XK_Control_R:
+ case XK_Control_L: nNewState = ControlMask;break;
+ // just interested in shift and ctrl for dnd
+ }
+ if( rMessage.type == KeyPress )
+ nState |= nNewState;
+ else
+ nState &= ~nNewState;
+ aGuard.clear();
+ if( updateDragAction( nState ) )
+ sendDropPosition( true, rMessage.xkey.time );
+ }
+ }
+ else if(
+ ( rMessage.type == ButtonPress || rMessage.type == ButtonRelease ) &&
+ rMessage.xbutton.button == m_nDragButton )
+ {
+ bool bCancel = true;
+ if( m_aDropWindow != None )
+ {
+ if( it != m_aDropTargets.end() )
+ {
+ if( it->second.m_pTarget->m_bActive && m_nUserDragAction != DNDConstants::ACTION_NONE && m_bLastDropAccepted )
+ {
+ bHandled = true;
+ int x, y;
+ Window aChild;
+ XTranslateCoordinates( m_pDisplay, rMessage.xbutton.root, m_aDropWindow, rMessage.xbutton.x_root, rMessage.xbutton.y_root, &x, &y, &aChild );
+ DropTargetDropEvent dtde;
+ dtde.Source = static_cast< OWeakObject* >(it->second.m_pTarget );
+ dtde.Context = new DropTargetDropContext( m_aCurrentDropWindow, m_nDropTimestamp, *this );
+ dtde.LocationX = x;
+ dtde.LocationY = y;
+ dtde.DropAction = m_nUserDragAction;
+ dtde.SourceActions = m_nSourceActions;
+ dtde.Transferable = m_xDragSourceTransferable;
+ m_bDropSent = true;
+ m_nDropTimeout = time( NULL );
+ m_bDropWaitingForCompletion = true;
+ aGuard.clear();
+ it->second->drop( dtde );
+ bCancel = false;
+ }
+ else bCancel = true;
+ }
+ else if( m_nCurrentProtocolVersion >= 0 )
+ {
+ bHandled = true;
+
+ XEvent aEvent;
+ aEvent.type = ClientMessage;
+ aEvent.xclient.display = m_pDisplay;
+ aEvent.xclient.format = 32;
+ aEvent.xclient.message_type = m_nXdndDrop;
+ aEvent.xclient.window = m_aDropWindow;
+ aEvent.xclient.data.l[0] = m_aWindow;
+ aEvent.xclient.data.l[1] = 0;
+ aEvent.xclient.data.l[2] = rMessage.xbutton.time;
+ aEvent.xclient.data.l[3] = 0;
+ aEvent.xclient.data.l[4] = 0;
+
+ m_bDropSent = true;
+ m_nDropTimeout = time( NULL );
+ XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
+ bCancel = false;
+ }
+ else
+ {
+ // dropping on non XdndWindows: acquire ownership of
+ // PRIMARY and send a middle mouse button click down/up to
+ // target window
+ SelectionAdaptor* pAdaptor = getAdaptor( XA_PRIMARY );
+ if( pAdaptor )
+ {
+ bHandled = true;
+
+ Window aDummy;
+ XEvent aEvent;
+ aEvent.type = ButtonPress;
+ aEvent.xbutton.display = m_pDisplay;
+ aEvent.xbutton.window = m_aDropWindow;
+ aEvent.xbutton.root = rMessage.xbutton.root;
+ aEvent.xbutton.subwindow = m_aDropWindow;
+ aEvent.xbutton.time = rMessage.xbutton.time+1;
+ aEvent.xbutton.x_root = rMessage.xbutton.x_root;
+ aEvent.xbutton.y_root = rMessage.xbutton.y_root;
+ aEvent.xbutton.state = rMessage.xbutton.state;
+ aEvent.xbutton.button = Button2;
+ aEvent.xbutton.same_screen = True;
+ XTranslateCoordinates( m_pDisplay,
+ rMessage.xbutton.root, m_aDropWindow,
+ rMessage.xbutton.x_root, rMessage.xbutton.y_root,
+ &aEvent.xbutton.x, &aEvent.xbutton.y,
+ &aDummy );
+ XSendEvent( m_pDisplay, m_aDropWindow, False, ButtonPressMask, &aEvent );
+ aEvent.xbutton.type = ButtonRelease;
+ aEvent.xbutton.time++;
+ aEvent.xbutton.state |= Button2Mask;
+ XSendEvent( m_pDisplay, m_aDropWindow, False, ButtonReleaseMask, &aEvent );
+
+ m_bDropSent = true;
+ m_nDropTimeout = time( NULL );
+ XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
+ m_bWaitingForPrimaryConversion = true;
+ m_bDropSent = true;
+ m_nDropTimeout = time( NULL );
+ // HACK :-)
+ aGuard.clear();
+ static_cast< X11Clipboard* >( pAdaptor )->setContents( m_xDragSourceTransferable, Reference< ::com::sun::star::datatransfer::clipboard::XClipboardOwner >() );
+ aGuard.reset();
+ bCancel = false;
+ }
+ }
+ }
+ if( bCancel )
+ {
+ // cancel drag
+ DragSourceDropEvent dsde;
+ dsde.Source = static_cast< OWeakObject* >(this);
+ dsde.DragSourceContext = new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
+ dsde.DragSource = static_cast< XDragSource* >(this);
+ dsde.DropAction = DNDConstants::ACTION_NONE;
+ dsde.DropSuccess = sal_False;
+ Reference< XDragSourceListener > xListener( m_xDragSourceListener );
+ m_xDragSourceListener.clear();
+ aGuard.clear();
+ xListener->dragDropEnd( dsde );
+ bHandled = true;
+ }
+ }
+ return bHandled;
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::accept( sal_Int8 dragOperation, Window aDropWindow, Time )
+{
+ if( aDropWindow == m_aCurrentDropWindow )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "accept: %x\n", dragOperation );
+#endif
+ Atom nAction = None;
+ dragOperation &= (DNDConstants::ACTION_MOVE | DNDConstants::ACTION_COPY | DNDConstants::ACTION_LINK);
+ if( dragOperation & DNDConstants::ACTION_MOVE )
+ nAction = m_nXdndActionMove;
+ else if( dragOperation & DNDConstants::ACTION_COPY )
+ nAction = m_nXdndActionCopy;
+ else if( dragOperation & DNDConstants::ACTION_LINK )
+ nAction = m_nXdndActionLink;
+ m_bLastDropAccepted = true;
+ sendDragStatus( nAction );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::reject( Window aDropWindow, Time )
+{
+ if( aDropWindow == m_aCurrentDropWindow )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "reject\n" );
+#endif
+ m_bLastDropAccepted = false;
+ sendDragStatus( None );
+ if( m_bDropSent && m_xDragSourceListener.is() )
+ {
+ DragSourceDropEvent dsde;
+ dsde.Source = static_cast< OWeakObject* >(this);
+ dsde.DragSourceContext = new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
+ dsde.DragSource = static_cast< XDragSource* >(this);
+ dsde.DropAction = DNDConstants::ACTION_NONE;
+ dsde.DropSuccess = sal_False;
+ m_xDragSourceListener->dragDropEnd( dsde );
+ m_xDragSourceListener.clear();
+ }
+ }
+}
+
+/*
+ * XDragSource
+ */
+
+sal_Bool SelectionManager::isDragImageSupported() throw()
+{
+ return sal_False;
+}
+
+// ------------------------------------------------------------------------
+
+sal_Int32 SelectionManager::getDefaultCursor( sal_Int8 dragAction ) throw()
+{
+ Cursor aCursor = m_aNoneCursor;
+ if( dragAction & DNDConstants::ACTION_MOVE )
+ aCursor = m_aMoveCursor;
+ else if( dragAction & DNDConstants::ACTION_COPY )
+ aCursor = m_aCopyCursor;
+ else if( dragAction & DNDConstants::ACTION_LINK )
+ aCursor = m_aLinkCursor;
+ return aCursor;
+}
+
+// ------------------------------------------------------------------------
+
+int SelectionManager::getXdndVersion( Window aWindow, Window& rProxy )
+{
+ Atom* pProperties = NULL;
+ int nProperties = 0;
+ Atom nType;
+ int nFormat;
+ unsigned long nItems, nBytes;
+ unsigned char* pBytes = NULL;
+
+ int nVersion = -1;
+ rProxy = None;
+
+ /*
+ * XListProperties is used here to avoid unnecessary XGetWindowProperty calls
+ * and therefore reducing latency penalty
+ */
+ pProperties = XListProperties( m_pDisplay, aWindow, &nProperties );
+ // first look for proxy
+ int i;
+ for( i = 0; i < nProperties; i++ )
+ {
+ if( pProperties[i] == m_nXdndProxy )
+ {
+ XGetWindowProperty( m_pDisplay, aWindow, m_nXdndProxy, 0, 1, False, XA_WINDOW,
+ &nType, &nFormat, &nItems, &nBytes, &pBytes );
+ if( pBytes )
+ {
+ if( nType == XA_WINDOW )
+ rProxy = *(Window*)pBytes;
+ XFree( pBytes );
+ pBytes = NULL;
+ if( rProxy != None )
+ {
+ // now check proxy wether it points to itself
+ XGetWindowProperty( m_pDisplay, rProxy, m_nXdndProxy, 0, 1, False, XA_WINDOW,
+ &nType, &nFormat, &nItems, &nBytes, &pBytes );
+ if( pBytes )
+ {
+ if( nType == XA_WINDOW && *(Window*)pBytes != rProxy )
+ rProxy = None;
+ XFree( pBytes );
+ pBytes = NULL;
+ }
+ else
+ rProxy = None;
+ }
+ }
+ break;
+ }
+ }
+ Window aAwareWindow = rProxy != None ? rProxy : aWindow;
+
+ XGetWindowProperty( m_pDisplay, aAwareWindow, m_nXdndAware, 0, 1, False, XA_ATOM,
+ &nType, &nFormat, &nItems, &nBytes, &pBytes );
+ if( pBytes )
+ {
+ if( nType == XA_ATOM )
+ nVersion = *(Atom*)pBytes;
+ XFree( pBytes );
+ }
+
+ nVersion = nVersion > nXdndProtocolRevision ? nXdndProtocolRevision : nVersion;
+
+ return nVersion;
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::updateDragWindow( int nX, int nY, Window aRoot )
+{
+ ResettableMutexGuard aGuard( m_aMutex );
+
+ Reference< XDragSourceListener > xListener( m_xDragSourceListener );
+
+ m_nLastDragX = nX;
+ m_nLastDragY = nY;
+
+ Window aParent = aRoot;
+ Window aChild;
+ Window aNewProxy = None, aNewCurrentWindow = None;
+ int nNewProtocolVersion = -1;
+ int nWinX, nWinY;
+
+ // find the first XdndAware window or check if root window is
+ // XdndAware or has XdndProxy
+ do
+ {
+ XTranslateCoordinates( m_pDisplay, aRoot, aParent, nX, nY, &nWinX, &nWinY, &aChild );
+ if( aChild != None )
+ {
+ if( aChild == m_aCurrentDropWindow && aChild != aRoot && m_nCurrentProtocolVersion >= 0 )
+ {
+ aParent = aChild;
+ break;
+ }
+ nNewProtocolVersion = getXdndVersion( aChild, aNewProxy );
+ aParent = aChild;
+ }
+ } while( aChild != None && nNewProtocolVersion < 0 );
+
+ aNewCurrentWindow = aParent;
+ if( aNewCurrentWindow == aRoot )
+ {
+ // no children, try root drop
+ nNewProtocolVersion = getXdndVersion( aNewCurrentWindow, aNewProxy );
+ if( nNewProtocolVersion < 3 )
+ {
+ aNewCurrentWindow = aNewProxy = None;
+ nNewProtocolVersion = nXdndProtocolRevision;
+ }
+ }
+
+
+ DragSourceDragEvent dsde;
+ dsde.Source = static_cast< OWeakObject* >(this);
+ dsde.DragSourceContext = new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
+ dsde.DragSource = static_cast< XDragSource* >(this);
+ dsde.DropAction = nNewProtocolVersion >= 0 ? m_nUserDragAction : DNDConstants::ACTION_COPY;
+ dsde.UserAction = nNewProtocolVersion >= 0 ? m_nUserDragAction : DNDConstants::ACTION_COPY;
+
+ ::std::hash_map< Window, DropTargetEntry >::const_iterator it;
+ if( aNewCurrentWindow != m_aDropWindow )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "drag left window 0x%lx (rev. %d), entered window 0x%lx (rev %d)\n", m_aDropWindow, m_nCurrentProtocolVersion, aNewCurrentWindow, nNewProtocolVersion );
+#endif
+
+ if( m_aDropWindow != None )
+ {
+ it = m_aDropTargets.find( m_aDropWindow );
+ if( it != m_aDropTargets.end() )
+ // shortcut for own drop targets
+ {
+ DropTargetEvent dte;
+ dte.Source = static_cast< OWeakObject* >( it->second.m_pTarget );
+ aGuard.clear();
+ it->second.m_pTarget->dragExit( dte );
+ aGuard.reset();
+ }
+ else
+ {
+ // send old drop target a XdndLeave
+ XEvent aEvent;
+ aEvent.type = ClientMessage;
+ aEvent.xclient.display = m_pDisplay;
+ aEvent.xclient.format = 32;
+ aEvent.xclient.message_type = m_nXdndLeave;
+ aEvent.xclient.window = m_aDropWindow;
+ aEvent.xclient.data.l[0] = m_aWindow;
+ aEvent.xclient.data.l[1] = 0;
+ XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
+ }
+ if( xListener.is() )
+ {
+ aGuard.clear();
+ xListener->dragExit( dsde );
+ aGuard.reset();
+ }
+ }
+
+ m_nCurrentProtocolVersion = nNewProtocolVersion;
+ m_aDropWindow = aNewCurrentWindow;
+ m_aDropProxy = aNewProxy != None ? aNewProxy : m_aDropWindow;
+
+ it = m_aDropTargets.find( m_aDropWindow );
+ if( it != m_aDropTargets.end() && ! it->second.m_pTarget->m_bActive )
+ m_aDropProxy = None;
+
+ if( m_aDropProxy != None && xListener.is() )
+ {
+ aGuard.clear();
+ xListener->dragEnter( dsde );
+ aGuard.reset();
+ }
+ // send XdndEnter
+ if( m_aDropProxy != None && m_nCurrentProtocolVersion >= 0 )
+ {
+ it = m_aDropTargets.find( m_aDropWindow );
+ if( it != m_aDropTargets.end() )
+ {
+ XTranslateCoordinates( m_pDisplay, aRoot, m_aDropWindow, nX, nY, &nWinX, &nWinY, &aChild );
+ DropTargetDragEnterEvent dtde;
+ dtde.Source = static_cast< OWeakObject* >( it->second.m_pTarget );
+ dtde.Context = new DropTargetDragContext( m_aCurrentDropWindow, m_nDropTimestamp, *this );
+ dtde.LocationX = nWinX;
+ dtde.LocationY = nWinY;
+ dtde.DropAction = m_nUserDragAction;
+ dtde.SourceActions = m_nSourceActions;
+ dtde.SupportedDataFlavors = m_xDragSourceTransferable->getTransferDataFlavors();
+ aGuard.clear();
+ it->second.m_pTarget->dragEnter( dtde );
+ aGuard.reset();
+ }
+ else
+ {
+ XEvent aEvent;
+ aEvent.type = ClientMessage;
+ aEvent.xclient.display = m_pDisplay;
+ aEvent.xclient.format = 32;
+ aEvent.xclient.message_type = m_nXdndEnter;
+ aEvent.xclient.window = m_aDropWindow;
+ aEvent.xclient.data.l[0] = m_aWindow;
+ aEvent.xclient.data.l[1] = m_nCurrentProtocolVersion << 24;
+ memset( aEvent.xclient.data.l + 2, 0, sizeof( long )*3 );
+ // fill in data types
+ ::std::list< Atom > aConversions;
+ getNativeTypeList( m_aDragFlavors, aConversions, m_nXdndSelection );
+ if( aConversions.size() > 3 )
+ aEvent.xclient.data.l[1] |= 1;
+ ::std::list< Atom >::const_iterator type_it = aConversions.begin();
+ for( int i = 0; type_it != aConversions.end() && i < 3; i++, ++type_it )
+ aEvent.xclient.data.l[i+2] = *type_it;
+ XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
+ }
+ }
+ m_nNoPosX = m_nNoPosY = m_nNoPosWidth = m_nNoPosHeight = 0;
+ }
+ else if( m_aDropProxy != None && xListener.is() )
+ {
+ aGuard.clear();
+ // drag over for XdndAware windows comes when receiving XdndStatus
+ xListener->dragOver( dsde );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::startDrag(
+ const DragGestureEvent& trigger,
+ sal_Int8 sourceActions,
+ sal_Int32,
+ sal_Int32,
+ const Reference< XTransferable >& transferable,
+ const Reference< XDragSourceListener >& listener
+ ) throw()
+{
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "startDrag( sourceActions = %x )\n", (int)sourceActions );
+#endif
+
+ DragSourceDropEvent aDragFailedEvent;
+ aDragFailedEvent.Source = static_cast< OWeakObject* >(this);
+ aDragFailedEvent.DragSource = static_cast< XDragSource* >(this);
+ aDragFailedEvent.DragSourceContext = new DragSourceContext( None, CurrentTime, *this );
+ aDragFailedEvent.DropAction = DNDConstants::ACTION_NONE;
+ aDragFailedEvent.DropSuccess = sal_False;
+
+ if( m_aDragRunning.check() )
+ {
+ if( listener.is() )
+ listener->dragDropEnd( aDragFailedEvent );
+
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "*** ERROR *** second drag and drop started.\n" );
+ if( m_xDragSourceListener.is() )
+ fprintf( stderr, "*** ERROR *** drag source listener already set.\n" );
+ else
+ fprintf( stderr, "*** ERROR *** drag thread already running.\n" );
+#endif
+ return;
+ }
+
+ {
+ ClearableMutexGuard aGuard(m_aMutex);
+
+ // first get the current pointer position and the window that
+ // the pointer is located in. since said window should be one
+ // of our DropTargets at the time of executeDrag we can use
+ // them for a start
+ Window aRoot, aParent, aChild;
+ int root_x, root_y, win_x, win_y;
+ unsigned int mask;
+
+ ::std::hash_map< Window, DropTargetEntry >::const_iterator it;
+ it = m_aDropTargets.begin();
+ while( it != m_aDropTargets.end() )
+ {
+ if( XQueryPointer( m_pDisplay, it->second.m_aRootWindow,
+ &aRoot, &aParent,
+ &root_x, &root_y,
+ &win_x, &win_y,
+ &mask ) )
+ {
+ aParent = it->second.m_aRootWindow;
+ break;
+ }
+ ++it;
+ }
+
+ // don't start DnD if there is none of our windows on the same screen as
+ // the pointer or if no mouse button is pressed
+ if( it == m_aDropTargets.end() || (mask & (Button1Mask|Button2Mask|Button3Mask)) == 0 )
+ {
+ aGuard.clear();
+ if( listener.is() )
+ listener->dragDropEnd( aDragFailedEvent );
+ return;
+ }
+
+ // try to find which of our drop targets is the drag source
+ // if that drop target is deregistered we should stop executing
+ // the drag (actually this is a poor substitute for an "endDrag"
+ // method ).
+ m_aDragSourceWindow = None;
+ aParent = aRoot = it->second.m_aRootWindow;
+ do
+ {
+ XTranslateCoordinates( m_pDisplay, aRoot, aParent, root_x, root_y, &win_x, &win_y, &aChild );
+ if( aChild != None && m_aDropTargets.find( aChild ) != m_aDropTargets.end() )
+ {
+ m_aDragSourceWindow = aChild;
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "found drag source window 0x%lx\n", m_aDragSourceWindow );
+#endif
+ break;
+ }
+ aParent = aChild;
+ } while( aChild != None );
+
+
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "try to grab pointer ... " );
+#endif
+ int nPointerGrabSuccess =
+ XGrabPointer( m_pDisplay, it->second.m_aRootWindow, True,
+ DRAG_EVENT_MASK,
+ GrabModeAsync, GrabModeAsync,
+ None,
+ None,
+ CurrentTime );
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "%d\n", nPointerGrabSuccess );
+#endif
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "try to grab keyboard ... " );
+#endif
+ int nKeyboardGrabSuccess =
+ XGrabKeyboard( m_pDisplay, it->second.m_aRootWindow, True,
+ GrabModeAsync, GrabModeAsync, CurrentTime );
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "%d\n", nKeyboardGrabSuccess );
+#endif
+ if( nPointerGrabSuccess != GrabSuccess || nKeyboardGrabSuccess != GrabSuccess )
+ {
+ if( nPointerGrabSuccess == GrabSuccess )
+ XUngrabPointer( m_pDisplay, CurrentTime );
+ if( nKeyboardGrabSuccess == GrabSuccess )
+ XUngrabKeyboard( m_pDisplay, CurrentTime );
+ XFlush( m_pDisplay );
+ aGuard.clear();
+ if( listener.is() )
+ listener->dragDropEnd( aDragFailedEvent );
+ return;
+ }
+
+ m_xDragSourceTransferable = transferable;
+ m_xDragSourceListener = listener;
+ m_aDragFlavors = transferable->getTransferDataFlavors();
+ m_aCurrentCursor = None;
+
+ requestOwnership( m_nXdndSelection );
+
+ ::std::list< Atom > aConversions;
+ ::std::list< Atom >::const_iterator type_it;
+ getNativeTypeList( m_aDragFlavors, aConversions, m_nXdndSelection );
+
+ int nTypes = aConversions.size();
+ Atom* pTypes = (Atom*)alloca( sizeof(Atom)*nTypes );
+ type_it = aConversions.begin();
+ for( int n = 0; n < nTypes; n++, ++type_it )
+ pTypes[n] = *type_it;
+
+ XChangeProperty( m_pDisplay, m_aWindow, m_nXdndTypeList, XA_ATOM, 32, PropModeReplace, (unsigned char*)pTypes, nTypes );
+
+ m_nSourceActions = sourceActions | DNDConstants::ACTION_DEFAULT;
+ m_nUserDragAction = DNDConstants::ACTION_MOVE & m_nSourceActions;
+ if( ! m_nUserDragAction )
+ m_nUserDragAction = DNDConstants::ACTION_COPY & m_nSourceActions;
+ if( ! m_nUserDragAction )
+ m_nUserDragAction = DNDConstants::ACTION_LINK & m_nSourceActions;
+ m_nTargetAcceptAction = DNDConstants::ACTION_DEFAULT;
+ m_bDropSent = false;
+ m_bDropSuccess = false;
+ m_bWaitingForPrimaryConversion = false;
+ m_nDragButton = Button1; // default to left button
+ if( trigger.Event.getValueTypeName().equalsAsciiL( "com.sun.star.awt.MouseEvent", 27 ) )
+ {
+ MouseEvent aEvent;
+ trigger.Event >>= aEvent;
+ if( aEvent.Buttons & MouseButton::LEFT )
+ m_nDragButton = Button1;
+ else if( aEvent.Buttons & MouseButton::RIGHT )
+ m_nDragButton = Button3;
+ else if( aEvent.Buttons & MouseButton::MIDDLE )
+ m_nDragButton = Button2;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "m_nUserDragAction = %x\n", (int)m_nUserDragAction );
+#endif
+ updateDragWindow( root_x, root_y, aRoot );
+ m_nUserDragAction = ~0;
+ updateDragAction( mask );
+ }
+
+ m_aDragRunning.set();
+ m_aDragExecuteThread = osl_createSuspendedThread( call_SelectionManager_runDragExecute, this );
+ if( m_aDragExecuteThread )
+ osl_resumeThread( m_aDragExecuteThread );
+ else
+ {
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "osl_createSuspendedThread failed for drag execute\n" );
+#endif
+ m_xDragSourceListener.clear();
+ m_xDragSourceTransferable.clear();
+
+ m_bDropSent = false;
+ m_bDropSuccess = false;
+ m_bWaitingForPrimaryConversion = false;
+ m_aDropWindow = None;
+ m_aDropProxy = None;
+ m_nCurrentProtocolVersion = nXdndProtocolRevision;
+ m_nNoPosX = 0;
+ m_nNoPosY = 0;
+ m_nNoPosWidth = 0;
+ m_nNoPosHeight = 0;
+ m_aCurrentCursor = None;
+
+ XUngrabPointer( m_pDisplay, CurrentTime );
+ XUngrabKeyboard( m_pDisplay, CurrentTime );
+ XFlush( m_pDisplay );
+
+ m_aDragRunning.reset();
+
+ if( listener.is() )
+ listener->dragDropEnd( aDragFailedEvent );
+ }
+}
+
+void SelectionManager::runDragExecute( void* pThis )
+{
+ SelectionManager* This = (SelectionManager*)pThis;
+ This->dragDoDispatch();
+}
+
+void SelectionManager::dragDoDispatch()
+{
+
+ // do drag
+ // m_xDragSourceListener will be cleared on finished drop
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "begin executeDrag dispatching\n" );
+#endif
+ TimeValue aTVal;
+ aTVal.Seconds = 0;
+ aTVal.Nanosec = 200000000;
+ oslThread aThread = m_aDragExecuteThread;
+ while( m_xDragSourceListener.is() && ( ! m_bDropSent || time(NULL)-m_nDropTimeout < 5 ) && osl_scheduleThread( aThread ) )
+ {
+ // let the thread in the run method do the dispatching
+ // just look occasionally here whether drop timed out or is completed
+ osl_waitThread( &aTVal );
+ }
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "end executeDrag dispatching\n" );
+#endif
+ {
+ ClearableMutexGuard aGuard(m_aMutex);
+
+ Reference< XDragSourceListener > xListener( m_xDragSourceListener );
+ Reference< XTransferable > xTransferable( m_xDragSourceTransferable );
+ m_xDragSourceListener.clear();
+ m_xDragSourceTransferable.clear();
+
+ DragSourceDropEvent dsde;
+ dsde.Source = static_cast< OWeakObject* >(this);
+ dsde.DragSourceContext = new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
+ dsde.DragSource = static_cast< XDragSource* >(this);
+ dsde.DropAction = DNDConstants::ACTION_NONE;
+ dsde.DropSuccess = sal_False;
+
+ // cleanup after drag
+ if( m_bWaitingForPrimaryConversion )
+ getAdaptor( XA_PRIMARY )->clearTransferable();
+
+ m_bDropSent = false;
+ m_bDropSuccess = false;
+ m_bWaitingForPrimaryConversion = false;
+ m_aDropWindow = None;
+ m_aDropProxy = None;
+ m_nCurrentProtocolVersion = nXdndProtocolRevision;
+ m_nNoPosX = 0;
+ m_nNoPosY = 0;
+ m_nNoPosWidth = 0;
+ m_nNoPosHeight = 0;
+ m_aCurrentCursor = None;
+
+ XUngrabPointer( m_pDisplay, CurrentTime );
+ XUngrabKeyboard( m_pDisplay, CurrentTime );
+ XFlush( m_pDisplay );
+
+ m_aDragExecuteThread = NULL;
+ m_aDragRunning.reset();
+
+ aGuard.clear();
+ if( xListener.is() )
+ {
+ xTransferable.clear();
+ xListener->dragDropEnd( dsde );
+ }
+ }
+ osl_destroyThread( aThread );
+}
+
+/*
+ * XDragSourceContext
+ */
+
+sal_Int32 SelectionManager::getCurrentCursor()
+{
+ return m_aCurrentCursor;
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::setCursor( sal_Int32 cursor, Window aDropWindow, Time )
+{
+ MutexGuard aGuard( m_aMutex );
+ if( aDropWindow == m_aDropWindow && Cursor(cursor) != m_aCurrentCursor )
+ {
+ if( m_xDragSourceListener.is() && ! m_bDropSent )
+ {
+ m_aCurrentCursor = cursor;
+ XChangeActivePointerGrab( m_pDisplay, DRAG_EVENT_MASK, cursor, CurrentTime );
+ XFlush( m_pDisplay );
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::setImage( sal_Int32, Window, Time )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::transferablesFlavorsChanged()
+{
+ MutexGuard aGuard(m_aMutex);
+
+ m_aDragFlavors = m_xDragSourceTransferable->getTransferDataFlavors();
+ int i;
+
+ std::list< Atom > aConversions;
+ std::list< Atom >::const_iterator type_it;
+
+ getNativeTypeList( m_aDragFlavors, aConversions, m_nXdndSelection );
+
+ int nTypes = aConversions.size();
+ Atom* pTypes = (Atom*)alloca( sizeof(Atom)*aConversions.size() );
+ for( i = 0, type_it = aConversions.begin(); type_it != aConversions.end(); ++type_it, i++ )
+ pTypes[i] = *type_it;
+ XChangeProperty( m_pDisplay, m_aWindow, m_nXdndTypeList, XA_ATOM, 32, PropModeReplace, (unsigned char*)pTypes, nTypes );
+
+ if( m_aCurrentDropWindow != None && m_nCurrentProtocolVersion >= 0 )
+ {
+ // send synthetic leave and enter events
+
+ XEvent aEvent;
+
+ aEvent.type = ClientMessage;
+ aEvent.xclient.display = m_pDisplay;
+ aEvent.xclient.format = 32;
+ aEvent.xclient.window = m_aDropWindow;
+ aEvent.xclient.data.l[0] = m_aWindow;
+
+ aEvent.xclient.message_type = m_nXdndLeave;
+ aEvent.xclient.data.l[1] = 0;
+ XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
+
+ aEvent.xclient.message_type = m_nXdndEnter;
+ aEvent.xclient.data.l[1] = m_nCurrentProtocolVersion << 24;
+ memset( aEvent.xclient.data.l + 2, 0, sizeof( long )*3 );
+ // fill in data types
+ if( nTypes > 3 )
+ aEvent.xclient.data.l[1] |= 1;
+ for( int j = 0; j < nTypes && j < 3; j++ )
+ aEvent.xclient.data.l[j+2] = pTypes[j];
+
+ XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
+ }
+}
+
+/*
+ * dispatch loop
+ */
+
+// ------------------------------------------------------------------------
+
+bool SelectionManager::handleXEvent( XEvent& rEvent )
+{
+ /*
+ * since we are XConnectionListener to a second X display
+ * to get client messages it is essential not to dispatch
+ * events twice that we get on both connections
+ *
+ * #95201# between dispatching ButtonPress and startDrag
+ * the user can already have released the mouse. The ButtonRelease
+ * will then be dispatched in VCLs queue and never turn up here.
+ * Which is not so good, since startDrag will XGrabPointer and
+ * XGrabKeyboard -> solid lock.
+ */
+ if( rEvent.xany.display != m_pDisplay
+ && rEvent.type != ClientMessage
+ && rEvent.type != ButtonPress
+ && rEvent.type != ButtonRelease
+ )
+ return false;
+
+ bool bHandled = false;
+ switch (rEvent.type)
+ {
+ case SelectionClear:
+ {
+ ClearableMutexGuard aGuard(m_aMutex);
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "SelectionClear for selection %s\n",
+ OUStringToOString( getString( rEvent.xselectionclear.selection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr()
+ );
+#endif
+ SelectionAdaptor* pAdaptor = getAdaptor( rEvent.xselectionclear.selection );
+ std::hash_map< Atom, Selection* >::iterator it( m_aSelections.find( rEvent.xselectionclear.selection ) );
+ if( it != m_aSelections.end() )
+ it->second->m_bOwner = false;
+ aGuard.clear();
+ if ( pAdaptor )
+ pAdaptor->clearTransferable();
+ }
+ break;
+
+ case SelectionRequest:
+ bHandled = handleSelectionRequest( rEvent.xselectionrequest );
+ break;
+ case PropertyNotify:
+ if( rEvent.xproperty.window == m_aWindow ||
+ rEvent.xproperty.window == m_aCurrentDropWindow
+ )
+ bHandled = handleReceivePropertyNotify( rEvent.xproperty );
+ else
+ bHandled = handleSendPropertyNotify( rEvent.xproperty );
+ break;
+ case SelectionNotify:
+ bHandled = handleSelectionNotify( rEvent.xselection );
+ break;
+ case ClientMessage:
+ // messages from drag target
+ if( rEvent.xclient.message_type == m_nXdndStatus ||
+ rEvent.xclient.message_type == m_nXdndFinished )
+ bHandled = handleDragEvent( rEvent );
+ // messages from drag source
+ else if(
+ rEvent.xclient.message_type == m_nXdndEnter ||
+ rEvent.xclient.message_type == m_nXdndLeave ||
+ rEvent.xclient.message_type == m_nXdndPosition ||
+ rEvent.xclient.message_type == m_nXdndDrop
+ )
+ bHandled = handleDropEvent( rEvent.xclient );
+ break;
+ case EnterNotify:
+ case LeaveNotify:
+ case MotionNotify:
+ case ButtonPress:
+ case ButtonRelease:
+ case KeyPress:
+ case KeyRelease:
+ bHandled = handleDragEvent( rEvent );
+ break;
+ default:
+ ;
+ }
+ return bHandled;
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::dispatchEvent( int millisec )
+{
+ pollfd aPollFD;
+ XEvent event;
+
+ // query socket handle to poll on
+ aPollFD.fd = ConnectionNumber( m_pDisplay );
+ aPollFD.events = POLLIN;
+ aPollFD.revents = 0;
+
+ // wait for activity (outside the xlib)
+ if( poll( &aPollFD, 1, millisec ) > 0 )
+ {
+ // now acquire the mutex to prevent other threads
+ // from using the same X connection
+ ResettableMutexGuard aGuard(m_aMutex);
+
+ // prevent that another thread already ate the input
+ // this can happen if e.g. another thread does
+ // an X request getting a response. the response
+ // would be removed from the queue and we would end up
+ // with an empty socket here
+ if( poll( &aPollFD, 1, 0 ) > 0 )
+ {
+ int nPending = 1;
+ while( nPending )
+ {
+ nPending = XPending( m_pDisplay );
+ if( nPending )
+ {
+ XNextEvent( m_pDisplay, &event );
+ aGuard.clear();
+ handleXEvent( event );
+ aGuard.reset();
+ }
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::run( void* pThis )
+{
+#if OSL_DEBUG_LEVEL > 1
+ fprintf(stderr, "SelectionManager::run\n" );
+#endif
+ // dispatch until the cows come home
+
+ SelectionManager* This = (SelectionManager*)pThis;
+
+ timeval aLast;
+ gettimeofday( &aLast, 0 );
+
+ while( osl_scheduleThread(This->m_aThread) )
+ {
+ This->dispatchEvent( 1000 );
+
+ timeval aNow;
+ gettimeofday( &aNow, 0 );
+
+ if( (aNow.tv_sec - aLast.tv_sec) > 0 )
+ {
+ ClearableMutexGuard aGuard(This->m_aMutex);
+ std::list< std::pair< SelectionAdaptor*, Reference< XInterface > > > aChangeList;
+
+ for( std::hash_map< Atom, Selection* >::iterator it = This->m_aSelections.begin(); it != This->m_aSelections.end(); ++it )
+ {
+ if( it->first != This->m_nXdndSelection && ! it->second->m_bOwner )
+ {
+ Window aOwner = XGetSelectionOwner( This->m_pDisplay, it->first );
+ if( aOwner != it->second->m_aLastOwner )
+ {
+ it->second->m_aLastOwner = aOwner;
+ std::pair< SelectionAdaptor*, Reference< XInterface > >
+ aKeep( it->second->m_pAdaptor, it->second->m_pAdaptor->getReference() );
+ aChangeList.push_back( aKeep );
+ }
+ }
+ }
+ aGuard.clear();
+ while( aChangeList.begin() != aChangeList.end() )
+ {
+ aChangeList.front().first->fireContentsChanged();
+ aChangeList.pop_front();
+ }
+ aLast = aNow;
+ }
+ }
+#if OSL_DEBUG_LEVEL > 1
+ fprintf(stderr, "SelectionManager::run end\n" );
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool SelectionManager::handleEvent( const Any& event ) throw()
+{
+ Sequence< sal_Int8 > aSeq;
+ if( (event >>= aSeq) )
+ {
+ XEvent* pEvent = (XEvent*)aSeq.getArray();
+ Time nTimestamp = CurrentTime;
+ if( pEvent->type == ButtonPress || pEvent->type == ButtonRelease )
+ nTimestamp = pEvent->xbutton.time;
+ else if( pEvent->type == KeyPress || pEvent->type == KeyRelease )
+ nTimestamp = pEvent->xkey.time;
+ else if( pEvent->type == MotionNotify )
+ nTimestamp = pEvent->xmotion.time;
+ else if( pEvent->type == PropertyNotify )
+ nTimestamp = pEvent->xproperty.time;
+
+ if( nTimestamp != CurrentTime )
+ {
+ MutexGuard aGuard(m_aMutex);
+
+ m_nSelectionTimestamp = nTimestamp;
+ }
+
+ return sal_Bool( handleXEvent( *pEvent ) );
+ }
+ else
+ {
+ #if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "SelectionManager got downing event\n" );
+ #endif
+ MutexGuard aGuard(m_aMutex);
+ // stop dispatching
+ if( m_aThread )
+ osl_terminateThread( m_aThread );
+ m_xDisplayConnection->removeEventHandler( Any(), this );
+ m_xDisplayConnection.clear();
+ }
+ return sal_True;
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::registerHandler( Atom selection, SelectionAdaptor& rAdaptor )
+{
+ MutexGuard aGuard(m_aMutex);
+
+ Selection* pNewSelection = new Selection();
+ pNewSelection->m_pAdaptor = &rAdaptor;
+ pNewSelection->m_aAtom = selection;
+ m_aSelections[ selection ] = pNewSelection;
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::deregisterHandler( Atom selection )
+{
+ MutexGuard aGuard(m_aMutex);
+
+ ::std::hash_map< Atom, Selection* >::iterator it =
+ m_aSelections.find( selection );
+ if( it != m_aSelections.end() )
+ {
+ delete it->second->m_pPixmap;
+ delete it->second;
+ m_aSelections.erase( it );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::registerDropTarget( Window aWindow, DropTarget* pTarget )
+{
+ MutexGuard aGuard(m_aMutex);
+
+ // sanity check
+ ::std::hash_map< Window, DropTargetEntry >::const_iterator it =
+ m_aDropTargets.find( aWindow );
+ if( it != m_aDropTargets.end() )
+ OSL_ASSERT( "attempt to register window as drop target twice" );
+ else if( aWindow && m_pDisplay )
+ {
+ XSelectInput( m_pDisplay, aWindow, PropertyChangeMask );
+
+ // set XdndAware
+ XChangeProperty( m_pDisplay, aWindow, m_nXdndAware, XA_ATOM, 32, PropModeReplace, (unsigned char*)&nXdndProtocolRevision, 1 );
+
+ DropTargetEntry aEntry( pTarget );
+ // get root window of window (in 99.999% of all cases this will be
+ // DefaultRootWindow( m_pDisplay )
+ int x, y;
+ unsigned int w, h, bw, d;
+ XGetGeometry( m_pDisplay, aWindow, &aEntry.m_aRootWindow,
+ &x, &y, &w, &h, &bw, &d );
+ m_aDropTargets[ aWindow ] = aEntry;
+ }
+ else
+ OSL_ASSERT( "attempt to register None as drop target" );
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::deregisterDropTarget( Window aWindow )
+{
+ ClearableMutexGuard aGuard(m_aMutex);
+
+ m_aDropTargets.erase( aWindow );
+ if( aWindow == m_aDragSourceWindow && m_aDragRunning.check() )
+ {
+ // abort drag
+ std::hash_map< Window, DropTargetEntry >::const_iterator it =
+ m_aDropTargets.find( m_aDropWindow );
+ if( it != m_aDropTargets.end() )
+ {
+ DropTargetEvent dte;
+ dte.Source = static_cast< OWeakObject* >( it->second.m_pTarget );
+ aGuard.clear();
+ it->second.m_pTarget->dragExit( dte );
+ }
+ else if( m_aDropProxy != None && m_nCurrentProtocolVersion >= 0 )
+ {
+ // send XdndLeave
+ XEvent aEvent;
+ aEvent.type = ClientMessage;
+ aEvent.xclient.display = m_pDisplay;
+ aEvent.xclient.format = 32;
+ aEvent.xclient.message_type = m_nXdndLeave;
+ aEvent.xclient.window = m_aDropWindow;
+ aEvent.xclient.data.l[0] = m_aWindow;
+ memset( aEvent.xclient.data.l+1, 0, sizeof(long)*4);
+ m_aDropWindow = m_aDropProxy = None;
+ XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
+ }
+ // notify the listener
+ DragSourceDropEvent dsde;
+ dsde.Source = static_cast< OWeakObject* >(this);
+ dsde.DragSourceContext = new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
+ dsde.DragSource = static_cast< XDragSource* >(this);
+ dsde.DropAction = DNDConstants::ACTION_NONE;
+ dsde.DropSuccess = sal_False;
+ Reference< XDragSourceListener > xListener( m_xDragSourceListener );
+ m_xDragSourceListener.clear();
+ aGuard.clear();
+ xListener->dragDropEnd( dsde );
+ }
+}
+
+/*
+ * SelectionAdaptor
+ */
+
+Reference< XTransferable > SelectionManager::getTransferable() throw()
+{
+ return m_xDragSourceTransferable;
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::clearTransferable() throw()
+{
+ m_xDragSourceTransferable.clear();
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManager::fireContentsChanged() throw()
+{
+}
+
+// ------------------------------------------------------------------------
+
+Reference< XInterface > SelectionManager::getReference() throw()
+{
+ return Reference< XInterface >( static_cast<OWeakObject*>(this) );
+}
+
+// ------------------------------------------------------------------------
+
+/*
+ * SelectionManagerHolder
+ */
+
+SelectionManagerHolder::SelectionManagerHolder() :
+ ::cppu::WeakComponentImplHelper3<
+ XDragSource,
+ XInitialization,
+ XServiceInfo > (m_aMutex)
+{
+}
+
+// ------------------------------------------------------------------------
+
+SelectionManagerHolder::~SelectionManagerHolder()
+{
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManagerHolder::initialize( const Sequence< Any >& arguments ) throw( ::com::sun::star::uno::Exception )
+{
+ OUString aDisplayName;
+
+ if( arguments.getLength() > 0 )
+ {
+ Reference< XDisplayConnection > xConn;
+ arguments.getConstArray()[0] >>= xConn;
+ if( xConn.is() )
+ {
+ Any aIdentifier;
+ aIdentifier >>= aDisplayName;
+ }
+ }
+
+ SelectionManager& rManager = SelectionManager::get( aDisplayName );
+ rManager.initialize( arguments );
+ m_xRealDragSource = static_cast< XDragSource* >(&rManager);
+}
+
+/*
+ * XDragSource
+ */
+
+sal_Bool SelectionManagerHolder::isDragImageSupported() throw()
+{
+ return m_xRealDragSource.is() ? m_xRealDragSource->isDragImageSupported() : sal_False;
+}
+
+// ------------------------------------------------------------------------
+
+sal_Int32 SelectionManagerHolder::getDefaultCursor( sal_Int8 dragAction ) throw()
+{
+ return m_xRealDragSource.is() ? m_xRealDragSource->getDefaultCursor( dragAction ) : 0;
+}
+
+// ------------------------------------------------------------------------
+
+void SelectionManagerHolder::startDrag(
+ const ::com::sun::star::datatransfer::dnd::DragGestureEvent& trigger,
+ sal_Int8 sourceActions, sal_Int32 cursor, sal_Int32 image,
+ const Reference< ::com::sun::star::datatransfer::XTransferable >& transferable,
+ const Reference< ::com::sun::star::datatransfer::dnd::XDragSourceListener >& listener
+ ) throw()
+{
+ if( m_xRealDragSource.is() )
+ m_xRealDragSource->startDrag( trigger, sourceActions, cursor, image, transferable, listener );
+}
+
+// ------------------------------------------------------------------------
+
+/*
+ * XServiceInfo
+ */
+
+// ------------------------------------------------------------------------
+
+OUString SelectionManagerHolder::getImplementationName() throw()
+{
+ return OUString::createFromAscii(XDND_IMPLEMENTATION_NAME);
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool SelectionManagerHolder::supportsService( const OUString& ServiceName ) throw()
+{
+ Sequence < OUString > SupportedServicesNames = Xdnd_getSupportedServiceNames();
+
+ for ( sal_Int32 n = SupportedServicesNames.getLength(); n--; )
+ if (SupportedServicesNames[n].compareTo(ServiceName) == 0)
+ return sal_True;
+
+ return sal_False;
+}
+
+// ------------------------------------------------------------------------
+
+Sequence< OUString > SelectionManagerHolder::getSupportedServiceNames() throw()
+{
+ return Xdnd_getSupportedServiceNames();
+}
+
+
+// ------------------------------------------------------------------------
+
diff --git a/vcl/unx/source/dtrans/X11_selection.hxx b/vcl/unx/source/dtrans/X11_selection.hxx
new file mode 100644
index 000000000000..dc6c41247bbd
--- /dev/null
+++ b/vcl/unx/source/dtrans/X11_selection.hxx
@@ -0,0 +1,518 @@
+/*************************************************************************
+ *
+ * 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: X11_selection.hxx,v $
+ * $Revision: 1.37 $
+ *
+ * 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 _DTRANS_X11_SELECTION_HXX_
+#define _DTRANS_X11_SELECTION_HXX_
+
+#include <cppuhelper/compbase3.hxx>
+#include <com/sun/star/datatransfer/XTransferable.hpp>
+#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
+#include <com/sun/star/datatransfer/dnd/XDragSource.hpp>
+#include <com/sun/star/awt/XDisplayConnection.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/script/XInvocation.hpp>
+#include <osl/thread.h>
+
+#ifndef _OSL_CONDITION_HXX_
+#include <osl/conditn.hxx>
+#endif
+
+#include <hash_map>
+#include <list>
+
+#include <X11/Xlib.h>
+
+#define XDND_IMPLEMENTATION_NAME "com.sun.star.datatransfer.dnd.XdndSupport"
+#define XDND_DROPTARGET_IMPLEMENTATION_NAME "com.sun.star.datatransfer.dnd.XdndDropTarget"
+
+using namespace ::com::sun::star::uno;
+
+namespace x11 {
+
+ class PixmapHolder; // in bmp.hxx
+
+// ------------------------------------------------------------------------
+ rtl_TextEncoding getTextPlainEncoding( const ::rtl::OUString& rMimeType );
+
+ class SelectionAdaptor
+ {
+ public:
+ virtual Reference< ::com::sun::star::datatransfer::XTransferable > getTransferable() = 0;
+ virtual void clearTransferable() = 0;
+ virtual void fireContentsChanged() = 0;
+ virtual Reference< XInterface > getReference() = 0;
+ // returns a reference that will keep the SelectionAdaptor alive until the
+ // refernce is released
+ };
+
+ class DropTarget :
+ public ::cppu::WeakComponentImplHelper3<
+ ::com::sun::star::datatransfer::dnd::XDropTarget,
+ ::com::sun::star::lang::XInitialization,
+ ::com::sun::star::lang::XServiceInfo
+ >
+ {
+ public:
+ ::osl::Mutex m_aMutex;
+ bool m_bActive;
+ sal_Int8 m_nDefaultActions;
+ Window m_aTargetWindow;
+ class SelectionManager* m_pSelectionManager;
+ Reference< ::com::sun::star::datatransfer::dnd::XDragSource >
+ m_xSelectionManager;
+ ::std::list< Reference< ::com::sun::star::datatransfer::dnd::XDropTargetListener > >
+ m_aListeners;
+
+ DropTarget();
+ virtual ~DropTarget();
+
+ // convenience functions that loop over listeners
+ void dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent& dtde ) throw();
+ void dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent& dte ) throw();
+ void dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent& dtde ) throw();
+ void drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent& dtde ) throw();
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const Sequence< Any >& args ) throw ( ::com::sun::star::uno::Exception );
+
+ // XDropTarget
+ virtual void SAL_CALL addDropTargetListener( const Reference< ::com::sun::star::datatransfer::dnd::XDropTargetListener >& ) throw();
+ virtual void SAL_CALL removeDropTargetListener( const Reference< ::com::sun::star::datatransfer::dnd::XDropTargetListener >& ) throw();
+ virtual sal_Bool SAL_CALL isActive() throw();
+ virtual void SAL_CALL setActive( sal_Bool active ) throw();
+ virtual sal_Int8 SAL_CALL getDefaultActions() throw();
+ virtual void SAL_CALL setDefaultActions( sal_Int8 actions ) throw();
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName() throw();
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw();
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString >
+ SAL_CALL getSupportedServiceNames() throw();
+ };
+
+ class SelectionManagerHolder :
+ public ::cppu::WeakComponentImplHelper3<
+ ::com::sun::star::datatransfer::dnd::XDragSource,
+ ::com::sun::star::lang::XInitialization,
+ ::com::sun::star::lang::XServiceInfo
+ >
+ {
+ ::osl::Mutex m_aMutex;
+ Reference< ::com::sun::star::datatransfer::dnd::XDragSource >
+ m_xRealDragSource;
+ public:
+ SelectionManagerHolder();
+ virtual ~SelectionManagerHolder();
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName() throw();
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw();
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString >
+ SAL_CALL getSupportedServiceNames() throw();
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const Sequence< Any >& arguments ) throw( ::com::sun::star::uno::Exception );
+
+ // XDragSource
+ virtual sal_Bool SAL_CALL isDragImageSupported() throw();
+ virtual sal_Int32 SAL_CALL getDefaultCursor( sal_Int8 dragAction ) throw();
+ virtual void SAL_CALL startDrag(
+ const ::com::sun::star::datatransfer::dnd::DragGestureEvent& trigger,
+ sal_Int8 sourceActions, sal_Int32 cursor, sal_Int32 image,
+ const Reference< ::com::sun::star::datatransfer::XTransferable >& transferable,
+ const Reference< ::com::sun::star::datatransfer::dnd::XDragSourceListener >& listener
+ ) throw();
+
+ };
+
+
+ class SelectionManager :
+ public ::cppu::WeakImplHelper3<
+ ::com::sun::star::datatransfer::dnd::XDragSource,
+ ::com::sun::star::lang::XInitialization,
+ ::com::sun::star::awt::XEventHandler
+ >,
+ public SelectionAdaptor
+ {
+ static ::std::hash_map< ::rtl::OUString, SelectionManager*, ::rtl::OUStringHash >& getInstances();
+
+ // for INCR type selection transfer
+ // INCR protocol is used if the data cannot
+ // be transported at once but in parts
+ // IncrementalTransfer holds the bytes to be transmitted
+ // as well a the current position
+ // INCR triggers the delivery of the next part by deleting the
+ // property used to transfer the data
+ struct IncrementalTransfer
+ {
+ Sequence< sal_Int8 > m_aData;
+ int m_nBufferPos;
+ Window m_aRequestor;
+ Atom m_aProperty;
+ Atom m_aTarget;
+ int m_nFormat;
+ int m_nTransferStartTime;
+ };
+ int m_nIncrementalThreshold;
+
+ // a struct to hold the data associated with a selection
+ struct Selection
+ {
+ enum State
+ {
+ Inactive, WaitingForResponse, WaitingForData, IncrementalTransfer
+ };
+
+ State m_eState;
+ SelectionAdaptor* m_pAdaptor;
+ Atom m_aAtom;
+ ::osl::Condition m_aDataArrived;
+ Sequence< sal_Int8 > m_aData;
+ Sequence< ::com::sun::star::datatransfer::DataFlavor >
+ m_aTypes;
+ std::vector< Atom > m_aNativeTypes;
+ // this is used for caching
+ // m_aTypes is invalid after 2 seconds
+ // m_aNativeTypes contains the corresponding original atom
+ Atom m_aRequestedType;
+ // m_aRequestedType is only valid while WaitingForResponse and WaitingFotData
+ int m_nLastTimestamp;
+ bool m_bHaveUTF16;
+ Atom m_aUTF8Type;
+ bool m_bHaveCompound;
+ bool m_bOwner;
+ Window m_aLastOwner;
+ PixmapHolder* m_pPixmap;
+ // m_nOrigTimestamp contains the timestamp at which the seclection
+ // was acquired; needed for TIMESTAMP target
+ Time m_nOrigTimestamp;
+
+ Selection() : m_eState( Inactive ),
+ m_pAdaptor( NULL ),
+ m_aAtom( None ),
+ m_aRequestedType( None ),
+ m_nLastTimestamp( 0 ),
+ m_bHaveUTF16( false ),
+ m_aUTF8Type( None ),
+ m_bHaveCompound( false ),
+ m_bOwner( false ),
+ m_aLastOwner( None ),
+ m_pPixmap( NULL ),
+ m_nOrigTimestamp( CurrentTime )
+ {}
+ };
+
+ // a struct to hold data associated with a XDropTarget
+ struct DropTargetEntry
+ {
+ DropTarget* m_pTarget;
+ Window m_aRootWindow;
+
+ DropTargetEntry() : m_pTarget( NULL ), m_aRootWindow( None ) {}
+ DropTargetEntry( DropTarget* pTarget ) :
+ m_pTarget( pTarget ),
+ m_aRootWindow( None )
+ {}
+ DropTargetEntry( const DropTargetEntry& rEntry ) :
+ m_pTarget( rEntry.m_pTarget ),
+ m_aRootWindow( rEntry.m_aRootWindow )
+ {}
+ ~DropTargetEntry() {}
+
+ DropTarget* operator->() const { return m_pTarget; }
+ DropTargetEntry& operator=(const DropTargetEntry& rEntry)
+ { m_pTarget = rEntry.m_pTarget; m_aRootWindow = rEntry.m_aRootWindow; return *this; }
+ };
+
+ // internal data
+ Display* m_pDisplay;
+ oslThread m_aThread;
+ oslThread m_aDragExecuteThread;
+ ::osl::Condition m_aDragRunning;
+ Window m_aWindow;
+ Reference< ::com::sun::star::awt::XDisplayConnection >
+ m_xDisplayConnection;
+ Reference< com::sun::star::script::XInvocation >
+ m_xBitmapConverter;
+ sal_Int32 m_nSelectionTimeout;
+ Time m_nSelectionTimestamp;
+
+
+ // members used for Xdnd
+
+ // drop only
+
+ // contains the XdndEnterEvent of a drop action running
+ // with one of our targets. The data.l[0] member
+ // (conatining the drag source window) is set
+ // to None while that is not the case
+ XClientMessageEvent m_aDropEnterEvent;
+ // set to false on XdndEnter
+ // set to true on first XdndPosition or XdndLeave
+ bool m_bDropEnterSent;
+ Window m_aCurrentDropWindow;
+ // time code of XdndDrop
+ Time m_nDropTime;
+ sal_Int8 m_nLastDropAction;
+ // XTransferable for Xdnd with foreign drag source
+ Reference< ::com::sun::star::datatransfer::XTransferable >
+ m_xDropTransferable;
+ int m_nLastX, m_nLastY;
+ Time m_nDropTimestamp;
+ // set to true when calling drop()
+ // if another XdndEnter is received this shows that
+ // someone forgot to call dropComplete - we should reset
+ // and react to the new drop
+ bool m_bDropWaitingForCompletion;
+
+ // drag only
+
+ // None if no Dnd action is running with us as source
+ Window m_aDropWindow;
+ // either m_aDropWindow or its XdndProxy
+ Window m_aDropProxy;
+ Window m_aDragSourceWindow;
+ // XTransferable for Xdnd when we are drag source
+ Reference< ::com::sun::star::datatransfer::XTransferable >
+ m_xDragSourceTransferable;
+ Reference< ::com::sun::star::datatransfer::dnd::XDragSourceListener >
+ m_xDragSourceListener;
+ // root coordinates
+ int m_nLastDragX, m_nLastDragY;
+ Sequence< ::com::sun::star::datatransfer::DataFlavor >
+ m_aDragFlavors;
+ // the rectangle the pointer must leave until a new XdndPosition should
+ // be sent. empty unless the drop target told to fill
+ int m_nNoPosX, m_nNoPosY, m_nNoPosWidth, m_nNoPosHeight;
+ unsigned int m_nDragButton;
+ sal_Int8 m_nUserDragAction;
+ sal_Int8 m_nTargetAcceptAction;
+ sal_Int8 m_nSourceActions;
+ bool m_bLastDropAccepted;
+ bool m_bDropSuccess;
+ bool m_bDropSent;
+ time_t m_nDropTimeout;
+ bool m_bWaitingForPrimaryConversion;
+ Time m_nDragTimestamp;
+
+ // drag cursors
+ Cursor m_aMoveCursor;
+ Cursor m_aCopyCursor;
+ Cursor m_aLinkCursor;
+ Cursor m_aNoneCursor;
+ Cursor m_aCurrentCursor;
+
+
+ // drag and drop
+
+ int m_nCurrentProtocolVersion;
+ ::std::hash_map< Window, DropTargetEntry >
+ m_aDropTargets;
+
+
+ // some special atoms that are needed often
+ Atom m_nCLIPBOARDAtom;
+ Atom m_nTARGETSAtom;
+ Atom m_nTIMESTAMPAtom;
+ Atom m_nTEXTAtom;
+ Atom m_nINCRAtom;
+ Atom m_nCOMPOUNDAtom;
+ Atom m_nMULTIPLEAtom;
+ Atom m_nUTF16Atom;
+ Atom m_nImageBmpAtom;
+ Atom m_nXdndAware;
+ Atom m_nXdndEnter;
+ Atom m_nXdndLeave;
+ Atom m_nXdndPosition;
+ Atom m_nXdndStatus;
+ Atom m_nXdndDrop;
+ Atom m_nXdndFinished;
+ Atom m_nXdndSelection;
+ Atom m_nXdndTypeList;
+ Atom m_nXdndProxy;
+ Atom m_nXdndActionCopy;
+ Atom m_nXdndActionMove;
+ Atom m_nXdndActionLink;
+ Atom m_nXdndActionAsk;
+ Atom m_nXdndActionPrivate;
+
+ // caching for atoms
+ ::std::hash_map< Atom, ::rtl::OUString >
+ m_aAtomToString;
+ ::std::hash_map< ::rtl::OUString, Atom, ::rtl::OUStringHash >
+ m_aStringToAtom;
+
+ // the registered selections
+ ::std::hash_map< Atom, Selection* >
+ m_aSelections;
+ // IncrementalTransfers in progress
+ std::hash_map< Window, std::hash_map< Atom, IncrementalTransfer > >
+ m_aIncrementals;
+
+ // do not use X11 multithreading capabilities
+ // since this leads to deadlocks in different Xlib implentations
+ // (XFree as well as Xsun) use an own mutex instead
+ ::osl::Mutex m_aMutex;
+
+ SelectionManager();
+ ~SelectionManager();
+
+ SelectionAdaptor* getAdaptor( Atom selection );
+ PixmapHolder* getPixmapHolder( Atom selection );
+
+ // handle various events
+ bool handleSelectionRequest( XSelectionRequestEvent& rRequest );
+ bool handleSendPropertyNotify( XPropertyEvent& rNotify );
+ bool handleReceivePropertyNotify( XPropertyEvent& rNotify );
+ bool handleSelectionNotify( XSelectionEvent& rNotify );
+ bool handleDragEvent( XEvent& rMessage );
+ bool handleDropEvent( XClientMessageEvent& rMessage );
+
+ // dnd helpers
+ void sendDragStatus( Atom nDropAction );
+ void sendDropPosition( bool bForce, Time eventTime );
+ bool updateDragAction( int modifierState );
+ int getXdndVersion( Window aWindow, Window& rProxy );
+ Cursor createCursor( const char* pPointerData, const char* pMaskData, int width, int height, int hotX, int hotY );
+ // coordinates on root window
+ void updateDragWindow( int nX, int nY, Window aRoot );
+
+ bool getPasteData( Atom selection, Atom type, Sequence< sal_Int8 >& rData );
+ // returns true if conversion was successful
+ bool convertData( const Reference< ::com::sun::star::datatransfer::XTransferable >& xTransferable,
+ Atom nType,
+ Atom nSelection,
+ int & rFormat,
+ Sequence< sal_Int8 >& rData );
+ bool sendData( SelectionAdaptor* pAdaptor, Window requestor, Atom target, Atom property, Atom selection );
+
+ // thread dispatch loop
+ public:
+ // public for extern "C" stub
+ static void run( void* );
+ private:
+ void dispatchEvent( int millisec );
+ // drag thread dispatch
+ public:
+ // public for extern "C" stub
+ static void runDragExecute( void* );
+ private:
+ void dragDoDispatch();
+ bool handleXEvent( XEvent& rEvent );
+
+ // compound text conversion
+ ::rtl::OString convertToCompound( const ::rtl::OUString& rText );
+ ::rtl::OUString convertFromCompound( const char* pText, int nLen = -1 );
+
+ sal_Int8 getUserDragAction() const;
+ sal_Int32 getSelectionTimeout();
+ public:
+ static SelectionManager& get( const ::rtl::OUString& rDisplayName = ::rtl::OUString() );
+
+ Display * getDisplay() { return m_pDisplay; };
+ Window getWindow() { return m_aWindow; };
+
+
+ void registerHandler( Atom selection, SelectionAdaptor& rAdaptor );
+ void deregisterHandler( Atom selection );
+ bool requestOwnership( Atom selection );
+
+ // allow for synchronization over one mutex for XClipboard
+ osl::Mutex& getMutex() { return m_aMutex; }
+
+
+ Atom getAtom( const ::rtl::OUString& rString );
+ const ::rtl::OUString& getString( Atom nAtom );
+
+ // type conversion
+ // note: convertTypeToNative does NOT clear the list, so you can append
+ // multiple types to the same list
+ void convertTypeToNative( const ::rtl::OUString& rType, Atom selection, int& rFormat, ::std::list< Atom >& rConversions, bool bPushFront = false );
+ ::rtl::OUString convertTypeFromNative( Atom nType, Atom selection, int& rFormat );
+ void getNativeTypeList( const Sequence< com::sun::star::datatransfer::DataFlavor >& rTypes, std::list< Atom >& rOutTypeList, Atom targetselection );
+
+ // methods for transferable
+ bool getPasteDataTypes( Atom selection, Sequence< ::com::sun::star::datatransfer::DataFlavor >& rTypes );
+ bool getPasteData( Atom selection, const ::rtl::OUString& rType, Sequence< sal_Int8 >& rData );
+
+ // for XDropTarget to register/deregister itself
+ void registerDropTarget( Window aWindow, DropTarget* pTarget );
+ void deregisterDropTarget( Window aWindow );
+
+ // for XDropTarget{Drag|Drop}Context
+ void accept( sal_Int8 dragOperation, Window aDropWindow, Time aTimestamp );
+ void reject( Window aDropWindow, Time aTimestamp );
+ void dropComplete( sal_Bool success, Window aDropWindow, Time aTimestamp );
+
+ // for XDragSourceContext
+ sal_Int32 getCurrentCursor();
+ void setCursor( sal_Int32 cursor, Window aDropWindow, Time aTimestamp );
+ void setImage( sal_Int32 image, Window aDropWindow, Time aTimestamp );
+ void transferablesFlavorsChanged();
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const Sequence< Any >& arguments ) throw( ::com::sun::star::uno::Exception );
+
+ // XEventHandler
+ virtual sal_Bool SAL_CALL handleEvent( const Any& event ) throw();
+
+ // XDragSource
+ virtual sal_Bool SAL_CALL isDragImageSupported() throw();
+ virtual sal_Int32 SAL_CALL getDefaultCursor( sal_Int8 dragAction ) throw();
+ virtual void SAL_CALL startDrag(
+ const ::com::sun::star::datatransfer::dnd::DragGestureEvent& trigger,
+ sal_Int8 sourceActions, sal_Int32 cursor, sal_Int32 image,
+ const Reference< ::com::sun::star::datatransfer::XTransferable >& transferable,
+ const Reference< ::com::sun::star::datatransfer::dnd::XDragSourceListener >& listener
+ ) throw();
+
+ // SelectionAdaptor for XdndSelection Drag (we are drag source)
+ virtual Reference< ::com::sun::star::datatransfer::XTransferable > getTransferable() throw();
+ virtual void clearTransferable() throw();
+ virtual void fireContentsChanged() throw();
+ virtual Reference< XInterface > getReference() throw();
+ };
+
+// ------------------------------------------------------------------------
+
+ ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL Xdnd_getSupportedServiceNames();
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL Xdnd_createInstance(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & xMultiServiceFactory);
+
+ ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL Xdnd_dropTarget_getSupportedServiceNames();
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL Xdnd_dropTarget_createInstance(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & xMultiServiceFactory);
+
+// ------------------------------------------------------------------------
+
+}
+
+#endif
diff --git a/vcl/unx/source/dtrans/X11_service.cxx b/vcl/unx/source/dtrans/X11_service.cxx
new file mode 100644
index 000000000000..cf971a2f8eb6
--- /dev/null
+++ b/vcl/unx/source/dtrans/X11_service.cxx
@@ -0,0 +1,138 @@
+/*************************************************************************
+ *
+ * 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: X11_service.cxx,v $
+ * $Revision: 1.11 $
+ *
+ * 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 "salinst.h"
+
+#include <X11_clipboard.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/registry/XRegistryKey.hpp>
+#include <uno/dispatcher.h> // declaration of generic uno interface
+#include <uno/mapping.hxx> // mapping stuff
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/compbase1.hxx>
+
+using namespace rtl;
+using namespace cppu;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::datatransfer::clipboard;
+using namespace com::sun::star::awt;
+using namespace x11;
+
+Sequence< OUString > SAL_CALL x11::X11Clipboard_getSupportedServiceNames()
+{
+ Sequence< OUString > aRet(1);
+ aRet[0] = OUString::createFromAscii("com.sun.star.datatransfer.clipboard.SystemClipboard");
+ return aRet;
+}
+
+Sequence< OUString > SAL_CALL x11::Xdnd_getSupportedServiceNames()
+{
+ Sequence< OUString > aRet(1);
+ aRet[0] = OUString::createFromAscii("com.sun.star.datatransfer.dnd.X11DragSource");
+ return aRet;
+}
+
+Sequence< OUString > SAL_CALL x11::Xdnd_dropTarget_getSupportedServiceNames()
+{
+ Sequence< OUString > aRet(1);
+ aRet[0] = OUString::createFromAscii("com.sun.star.datatransfer.dnd.X11DropTarget");
+ return aRet;
+}
+
+// ------------------------------------------------------------------------
+
+Reference< XInterface > X11SalInstance::CreateClipboard( const Sequence< Any >& arguments )
+{
+ static std::hash_map< OUString, ::std::hash_map< Atom, Reference< XClipboard > >, ::rtl::OUStringHash > m_aInstances;
+
+ OUString aDisplayName;
+ Atom nSelection;
+
+ // extract display name from connection argument. An exception is thrown
+ // by SelectionManager.initialize() if no display connection is given.
+ if( arguments.getLength() > 0 )
+ {
+ Reference< XDisplayConnection > xConn;
+ arguments.getConstArray()[0] >>= xConn;
+
+ if( xConn.is() )
+ {
+ Any aIdentifier = xConn->getIdentifier();
+ aIdentifier >>= aDisplayName;
+ }
+ }
+
+ SelectionManager& rManager = SelectionManager::get( aDisplayName );
+ rManager.initialize( arguments );
+
+ // check if any other selection than clipboard selection is specified
+ if( arguments.getLength() > 1 )
+ {
+ OUString aSelectionName;
+
+ arguments.getConstArray()[1] >>= aSelectionName;
+ nSelection = rManager.getAtom( aSelectionName );
+ }
+ else
+ {
+ // default atom is clipboard selection
+ nSelection = rManager.getAtom( OUString::createFromAscii( "CLIPBOARD" ) );
+ }
+
+ ::std::hash_map< Atom, Reference< XClipboard > >& rMap( m_aInstances[ aDisplayName ] );
+ ::std::hash_map< Atom, Reference< XClipboard > >::iterator it = rMap.find( nSelection );
+ if( it != rMap.end() )
+ return it->second;
+
+ X11Clipboard* pClipboard = new X11Clipboard( rManager, nSelection );
+ rMap[ nSelection ] = pClipboard;
+
+ return static_cast<OWeakObject*>(pClipboard);
+}
+
+// ------------------------------------------------------------------------
+
+Reference< XInterface > X11SalInstance::CreateDragSource()
+{
+ return Reference < XInterface >( ( OWeakObject * ) new SelectionManagerHolder() );
+}
+
+// ------------------------------------------------------------------------
+
+Reference< XInterface > X11SalInstance::CreateDropTarget()
+{
+ return Reference < XInterface >( ( OWeakObject * ) new DropTarget() );
+}
+
+
diff --git a/vcl/unx/source/dtrans/X11_transferable.cxx b/vcl/unx/source/dtrans/X11_transferable.cxx
new file mode 100644
index 000000000000..a95b87fe1c15
--- /dev/null
+++ b/vcl/unx/source/dtrans/X11_transferable.cxx
@@ -0,0 +1,137 @@
+/*************************************************************************
+ *
+ * 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: X11_transferable.cxx,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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+#include <stdio.h>
+#endif
+
+#include <X11_transferable.hxx>
+#include <X11/Xatom.h>
+#include <com/sun/star/io/IOException.hpp>
+
+using namespace com::sun::star::datatransfer;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::io;
+using namespace com::sun::star::uno;
+using namespace cppu;
+using namespace osl;
+using namespace rtl;
+
+
+using namespace x11;
+
+
+X11Transferable::X11Transferable(
+ SelectionManager& rManager,
+ const Reference< XInterface >& xCreator,
+ Atom selection
+ ) :
+ m_rManager( rManager ),
+ m_xCreator( xCreator ),
+ m_aSelection( selection )
+{
+}
+
+//==================================================================================================
+
+X11Transferable::~X11Transferable()
+{
+}
+
+//==================================================================================================
+
+Any SAL_CALL X11Transferable::getTransferData( const DataFlavor& rFlavor )
+ throw(UnsupportedFlavorException, IOException, RuntimeException)
+{
+ Any aRet;
+ Sequence< sal_Int8 > aData;
+ bool bSuccess = m_rManager.getPasteData( m_aSelection ? m_aSelection : XA_PRIMARY, rFlavor.MimeType, aData );
+ if( ! bSuccess && m_aSelection == 0 )
+ bSuccess = m_rManager.getPasteData( m_rManager.getAtom( OUString::createFromAscii( "CLIPBOARD" ) ), rFlavor.MimeType, aData );
+
+ if( ! bSuccess )
+ {
+ throw UnsupportedFlavorException( rFlavor.MimeType, static_cast < XTransferable * > ( this ) );
+ }
+ if( rFlavor.MimeType.equalsIgnoreAsciiCase( OUString::createFromAscii( "text/plain;charset=utf-16" ) ) )
+ {
+ int nLen = aData.getLength()/2;
+ if( ((sal_Unicode*)aData.getConstArray())[nLen-1] == 0 )
+ nLen--;
+ OUString aString( (sal_Unicode*)aData.getConstArray(), nLen );
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "X11Transferable::getTransferData( \"%s\" )\n -> \"%s\"\n",
+ OUStringToOString( rFlavor.MimeType, RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
+ OUStringToOString( aString, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
+#endif
+ aRet <<= aString;
+ }
+ else
+ aRet <<= aData;
+ return aRet;
+}
+
+//==================================================================================================
+
+Sequence< DataFlavor > SAL_CALL X11Transferable::getTransferDataFlavors()
+ throw(RuntimeException)
+{
+ Sequence< DataFlavor > aFlavorList;
+ bool bSuccess = m_rManager.getPasteDataTypes( m_aSelection ? m_aSelection : XA_PRIMARY, aFlavorList );
+ if( ! bSuccess && m_aSelection == 0 )
+ bSuccess = m_rManager.getPasteDataTypes( m_rManager.getAtom( OUString::createFromAscii( "CLIPBOARD" ) ), aFlavorList );
+
+ return aFlavorList;
+}
+
+//==================================================================================================
+
+sal_Bool SAL_CALL X11Transferable::isDataFlavorSupported( const DataFlavor& aFlavor )
+ throw(RuntimeException)
+{
+ if( aFlavor.DataType != getCppuType( (Sequence< sal_Int8 >*)0 ) )
+ {
+ if( ! aFlavor.MimeType.equalsIgnoreAsciiCase( OUString::createFromAscii( "text/plain;charset=utf-16" ) ) &&
+ aFlavor.DataType == getCppuType( (OUString*)0 ) )
+ return false;
+ }
+
+ Sequence< DataFlavor > aFlavors( getTransferDataFlavors() );
+ for( int i = 0; i < aFlavors.getLength(); i++ )
+ if( aFlavor.MimeType.equalsIgnoreAsciiCase( aFlavors.getConstArray()[i].MimeType ) &&
+ aFlavor.DataType == aFlavors.getConstArray()[i].DataType )
+ return sal_True;
+
+ return sal_False;
+}
+
diff --git a/vcl/unx/source/dtrans/X11_transferable.hxx b/vcl/unx/source/dtrans/X11_transferable.hxx
new file mode 100644
index 000000000000..8e8367f666e2
--- /dev/null
+++ b/vcl/unx/source/dtrans/X11_transferable.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: X11_transferable.hxx,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.
+ *
+ ************************************************************************/
+
+#ifndef _DTRANS_X11_TRANSFERABLE_HXX_
+#define _DTRANS_X11_TRANSFERABLE_HXX_
+
+#include <X11_selection.hxx>
+#include <com/sun/star/datatransfer/XTransferable.hpp>
+
+#ifndef _COM_SUN_STAR_LANG_XEVENTLISTENER_HDL_
+#include <com/sun/star/lang/XEventListener.hpp>
+#endif
+#include <cppuhelper/implbase1.hxx>
+
+namespace x11 {
+
+ class X11Transferable : public ::cppu::WeakImplHelper1 <
+ ::com::sun::star::datatransfer::XTransferable >
+ {
+ ::osl::Mutex m_aMutex;
+
+ SelectionManager& m_rManager;
+ Reference< XInterface > m_xCreator;
+ Atom m_aSelection;
+ public:
+ X11Transferable( SelectionManager& rManager, const Reference< XInterface >& xCreator, Atom selection = None );
+ virtual ~X11Transferable();
+
+ /*
+ * 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);
+ };
+
+} // namespace
+
+#endif
diff --git a/vcl/unx/source/dtrans/bmp.cxx b/vcl/unx/source/dtrans/bmp.cxx
new file mode 100644
index 000000000000..49219bfb0e2a
--- /dev/null
+++ b/vcl/unx/source/dtrans/bmp.cxx
@@ -0,0 +1,742 @@
+/*************************************************************************
+ *
+ * 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: bmp.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 <unistd.h>
+#include <cstdio>
+#include <cstring>
+
+#include <bmp.hxx>
+
+#include <X11_selection.hxx>
+
+using namespace x11;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::script;
+using namespace com::sun::star::awt;
+using namespace rtl;
+
+/*
+ * helper functions
+ */
+
+inline void writeLE( sal_uInt16 nNumber, sal_uInt8* pBuffer )
+{
+ pBuffer[ 0 ] = (nNumber & 0xff);
+ pBuffer[ 1 ] = ((nNumber>>8)&0xff);
+}
+
+inline void writeLE( sal_uInt32 nNumber, sal_uInt8* pBuffer )
+{
+ pBuffer[ 0 ] = (nNumber & 0xff);
+ pBuffer[ 1 ] = ((nNumber>>8)&0xff);
+ pBuffer[ 2 ] = ((nNumber>>16)&0xff);
+ pBuffer[ 3 ] = ((nNumber>>24)&0xff);
+}
+
+inline sal_uInt16 readLE16( const sal_uInt8* pBuffer )
+{
+ return (((sal_uInt16)pBuffer[1]) << 8 ) | pBuffer[0];
+}
+
+inline sal_uInt16 readLE32( const sal_uInt8* pBuffer )
+{
+ return
+ (((sal_uInt32)pBuffer[3]) << 24 ) |
+ (((sal_uInt32)pBuffer[2]) << 16 ) |
+ (((sal_uInt32)pBuffer[1]) << 8 ) |
+ pBuffer[0];
+}
+
+
+/*
+ * BmpTransporter
+ */
+
+BmpTransporter::BmpTransporter( const Sequence<sal_Int8>& rBmp ) :
+ m_aBM( rBmp )
+{
+ const sal_uInt8* pData = (const sal_uInt8*)rBmp.getConstArray();
+
+ if( pData[0] == 'B' || pData[1] == 'M' )
+ {
+ pData = pData+14;
+ m_aSize.Width = readLE32( pData+4 );
+ m_aSize.Height = readLE32( pData+8 );
+ }
+ else
+ m_aSize.Width = m_aSize.Height = 0;
+}
+
+BmpTransporter::~BmpTransporter()
+{
+}
+
+com::sun::star::awt::Size SAL_CALL BmpTransporter::getSize() throw()
+{
+ return m_aSize;
+}
+
+Sequence< sal_Int8 > SAL_CALL BmpTransporter::getDIB() throw()
+{
+ return m_aBM;
+}
+
+Sequence< sal_Int8 > SAL_CALL BmpTransporter::getMaskDIB() throw()
+{
+ return Sequence< sal_Int8 >();
+}
+
+/*
+ * scanline helpers
+ */
+
+inline void X11_writeScanlinePixel( unsigned long nColor, sal_uInt8* pScanline, int depth, int x )
+{
+ switch( depth )
+ {
+ case 1:
+ pScanline[ x/8 ] &= ~(1 << (x&7));
+ pScanline[ x/8 ] |= ((nColor & 1) << (x&7));
+ break;
+ case 4:
+ pScanline[ x/2 ] &= ((x&1) ? 0x0f : 0xf0);
+ pScanline[ x/2 ] |= ((x&1) ? (nColor & 0x0f) : ((nColor & 0x0f) << 4));
+ break;
+ default:
+ case 8:
+ pScanline[ x ] = (nColor & 0xff);
+ break;
+ }
+}
+
+static sal_uInt8* X11_getPaletteBmpFromImage(
+ Display* pDisplay,
+ XImage* pImage,
+ Colormap aColormap,
+ sal_Int32& rOutSize
+ )
+{
+ sal_uInt32 nColors = 0;
+
+ rOutSize = 0;
+
+ sal_uInt8* pBuffer = 0;
+ sal_uInt32 nHeaderSize, nScanlineSize;
+ sal_uInt16 nBitCount;
+ // determine header and scanline size
+ switch( pImage->depth )
+ {
+ case 1:
+ nHeaderSize = 64;
+ nScanlineSize = (pImage->width+31)/32;
+ nBitCount = 1;
+ break;
+ case 4:
+ nHeaderSize = 72;
+ nScanlineSize = (pImage->width+1)/2;
+ nBitCount = 4;
+ break;
+ default:
+ case 8:
+ nHeaderSize = 1084;
+ nScanlineSize = pImage->width;
+ nBitCount = 8;
+ break;
+ }
+ // adjust scan lines to begin on %4 boundaries
+ if( nScanlineSize & 3 )
+ {
+ nScanlineSize &= 0xfffffffc;
+ nScanlineSize += 4;
+ }
+
+ // allocate buffer to hold header and scanlines, initialize to zero
+ rOutSize = nHeaderSize + nScanlineSize*pImage->height;
+ pBuffer = (sal_uInt8*)rtl_allocateZeroMemory( rOutSize );
+ for( int y = 0; y < pImage->height; y++ )
+ {
+ sal_uInt8* pScanline = pBuffer + nHeaderSize + (pImage->height-1-y)*nScanlineSize;
+ for( int x = 0; x < pImage->width; x++ )
+ {
+ unsigned long nPixel = XGetPixel( pImage, x, y );
+ if( nPixel >= nColors )
+ nColors = nPixel+1;
+ X11_writeScanlinePixel( nPixel, pScanline, pImage->depth, x );
+ }
+ }
+
+ // fill in header fields
+ pBuffer[ 0 ] = 'B';
+ pBuffer[ 1 ] = 'M';
+
+ writeLE( nHeaderSize, pBuffer+10 );
+ writeLE( (sal_uInt32)40, pBuffer+14 );
+ writeLE( (sal_uInt32)pImage->width, pBuffer+18 );
+ writeLE( (sal_uInt32)pImage->height, pBuffer+22 );
+ writeLE( (sal_uInt16)1, pBuffer+26 );
+ writeLE( nBitCount, pBuffer+28 );
+ writeLE( (sal_uInt32)(DisplayWidth(pDisplay,DefaultScreen(pDisplay))*1000/DisplayWidthMM(pDisplay,DefaultScreen(pDisplay))), pBuffer+38);
+ writeLE( (sal_uInt32)(DisplayHeight(pDisplay,DefaultScreen(pDisplay))*1000/DisplayHeightMM(pDisplay,DefaultScreen(pDisplay))), pBuffer+42);
+ writeLE( nColors, pBuffer+46 );
+ writeLE( nColors, pBuffer+50 );
+
+ XColor aColors[256];
+ if( nColors > (1U << nBitCount) ) // paranoia
+ nColors = (1U << nBitCount);
+ for( unsigned long nPixel = 0; nPixel < nColors; nPixel++ )
+ {
+ aColors[nPixel].flags = DoRed | DoGreen | DoBlue;
+ aColors[nPixel].pixel = nPixel;
+ }
+ XQueryColors( pDisplay, aColormap, aColors, nColors );
+ for( sal_uInt32 i = 0; i < nColors; i++ )
+ {
+ pBuffer[ 54 + i*4 ] = (sal_uInt8)(aColors[i].blue >> 8);
+ pBuffer[ 55 + i*4 ] = (sal_uInt8)(aColors[i].green >> 8);
+ pBuffer[ 56 + i*4 ] = (sal_uInt8)(aColors[i].red >> 8);
+ }
+
+ // done
+
+ return pBuffer;
+}
+
+inline unsigned long doRightShift( unsigned long nValue, int nShift )
+{
+ return (nShift > 0) ? (nValue >> nShift) : (nValue << (-nShift));
+}
+
+inline unsigned long doLeftShift( unsigned long nValue, int nShift )
+{
+ return (nShift > 0) ? (nValue << nShift) : (nValue >> (-nShift));
+}
+
+static void getShift( unsigned long nMask, int& rShift, int& rSigBits, int& rShift2 )
+{
+ unsigned long nUseMask = nMask;
+ rShift = 0;
+ while( nMask & 0xffffff00 )
+ {
+ rShift++;
+ nMask >>= 1;
+ }
+ if( rShift == 0 )
+ while( ! (nMask & 0x00000080) )
+ {
+ rShift--;
+ nMask <<= 1;
+ }
+
+ int nRotate = sizeof(unsigned long)*8 - rShift;
+ rSigBits = 0;
+ nMask = doRightShift( nUseMask, rShift) ;
+ while( nRotate-- )
+ {
+ if( nMask & 1 )
+ rSigBits++;
+ nMask >>= 1;
+ }
+
+ rShift2 = 0;
+ if( rSigBits < 8 )
+ rShift2 = 8-rSigBits;
+}
+
+static sal_uInt8* X11_getTCBmpFromImage(
+ Display* pDisplay,
+ XImage* pImage,
+ sal_Int32& rOutSize,
+ int nScreenNo
+ )
+{
+ // get masks from visual info (guesswork)
+ XVisualInfo aVInfo;
+ if( ! XMatchVisualInfo( pDisplay, nScreenNo, pImage->depth, TrueColor, &aVInfo ) )
+ return NULL;
+
+ rOutSize = 0;
+
+ sal_uInt8* pBuffer = 0;
+ sal_uInt32 nHeaderSize = 60;
+ sal_uInt32 nScanlineSize = pImage->width*3;
+
+ // adjust scan lines to begin on %4 boundaries
+ if( nScanlineSize & 3 )
+ {
+ nScanlineSize &= 0xfffffffc;
+ nScanlineSize += 4;
+ }
+ int nRedShift, nRedSig, nRedShift2 = 0;
+ getShift( aVInfo.red_mask, nRedShift, nRedSig, nRedShift2 );
+ int nGreenShift, nGreenSig, nGreenShift2 = 0;
+ getShift( aVInfo.green_mask, nGreenShift, nGreenSig, nGreenShift2 );
+ int nBlueShift, nBlueSig, nBlueShift2 = 0;
+ getShift( aVInfo.blue_mask, nBlueShift, nBlueSig, nBlueShift2 );
+
+ // allocate buffer to hold header and scanlines, initialize to zero
+ rOutSize = nHeaderSize + nScanlineSize*pImage->height;
+ pBuffer = (sal_uInt8*)rtl_allocateZeroMemory( rOutSize );
+ for( int y = 0; y < pImage->height; y++ )
+ {
+ sal_uInt8* pScanline = pBuffer + nHeaderSize + (pImage->height-1-y)*nScanlineSize;
+ for( int x = 0; x < pImage->width; x++ )
+ {
+ unsigned long nPixel = XGetPixel( pImage, x, y );
+
+ sal_uInt8 nValue = (sal_uInt8)doRightShift( nPixel&aVInfo.blue_mask, nBlueShift);
+ if( nBlueShift2 )
+ nValue |= (nValue >> nBlueShift2 );
+ *pScanline++ = nValue;
+
+ nValue = (sal_uInt8)doRightShift( nPixel&aVInfo.green_mask, nGreenShift);
+ if( nGreenShift2 )
+ nValue |= (nValue >> nGreenShift2 );
+ *pScanline++ = nValue;
+
+ nValue = (sal_uInt8)doRightShift( nPixel&aVInfo.red_mask, nRedShift);
+ if( nRedShift2 )
+ nValue |= (nValue >> nRedShift2 );
+ *pScanline++ = nValue;
+ }
+ }
+
+ // fill in header fields
+ pBuffer[ 0 ] = 'B';
+ pBuffer[ 1 ] = 'M';
+
+ writeLE( nHeaderSize, pBuffer+10 );
+ writeLE( (sal_uInt32)40, pBuffer+14 );
+ writeLE( (sal_uInt32)pImage->width, pBuffer+18 );
+ writeLE( (sal_uInt32)pImage->height, pBuffer+22 );
+ writeLE( (sal_uInt16)1, pBuffer+26 );
+ writeLE( (sal_uInt16)24, pBuffer+28 );
+ writeLE( (sal_uInt32)(DisplayWidth(pDisplay,DefaultScreen(pDisplay))*1000/DisplayWidthMM(pDisplay,DefaultScreen(pDisplay))), pBuffer+38);
+ writeLE( (sal_uInt32)(DisplayHeight(pDisplay,DefaultScreen(pDisplay))*1000/DisplayHeightMM(pDisplay,DefaultScreen(pDisplay))), pBuffer+42);
+
+ // done
+
+ return pBuffer;
+}
+
+sal_uInt8* x11::X11_getBmpFromPixmap(
+ Display* pDisplay,
+ Drawable aDrawable,
+ Colormap aColormap,
+ sal_Int32& rOutSize
+ )
+{
+ // get geometry of drawable
+ Window aRoot;
+ int x,y;
+ unsigned int w, h, bw, d;
+ XGetGeometry( pDisplay, aDrawable, &aRoot, &x, &y, &w, &h, &bw, &d );
+
+ // find which screen we are on
+ int nScreenNo = ScreenCount( pDisplay );
+ while( nScreenNo-- )
+ {
+ if( RootWindow( pDisplay, nScreenNo ) == aRoot )
+ break;
+ }
+ if( nScreenNo < 0 )
+ return NULL;
+
+ if( aColormap == None )
+ aColormap = DefaultColormap( pDisplay, nScreenNo );
+
+ // get the image
+ XImage* pImage = XGetImage( pDisplay, aDrawable, 0, 0, w, h, AllPlanes, ZPixmap );
+ if( ! pImage )
+ return NULL;
+
+ sal_uInt8* pBmp = d <= 8 ?
+ X11_getPaletteBmpFromImage( pDisplay, pImage, aColormap, rOutSize ) :
+ X11_getTCBmpFromImage( pDisplay, pImage, rOutSize, nScreenNo );
+ XDestroyImage( pImage );
+
+ return pBmp;
+}
+
+void x11::X11_freeBmp( sal_uInt8* pBmp )
+{
+ rtl_freeMemory( pBmp );
+}
+
+/*
+ * PixmapHolder
+ */
+
+PixmapHolder::PixmapHolder( Display* pDisplay ) :
+ m_pDisplay( pDisplay ),
+ m_aColormap( None ),
+ m_aPixmap( None ),
+ m_aBitmap( None )
+{
+ /* try to get a 24 bit true color visual, if that fails,
+ * revert to default visual
+ */
+ if( ! XMatchVisualInfo( m_pDisplay, DefaultScreen( m_pDisplay ), 24, TrueColor, &m_aInfo ) )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "PixmapHolder reverting to default visual\n" );
+#endif
+ Visual* pVisual = DefaultVisual( m_pDisplay, DefaultScreen( m_pDisplay ) );
+ m_aInfo.screen = DefaultScreen( m_pDisplay );
+ m_aInfo.visual = pVisual;
+ m_aInfo.visualid = pVisual->visualid;
+ m_aInfo.c_class = pVisual->c_class;
+ m_aInfo.red_mask = pVisual->red_mask;
+ m_aInfo.green_mask = pVisual->green_mask;
+ m_aInfo.blue_mask = pVisual->blue_mask;
+ m_aInfo.depth = DefaultDepth( m_pDisplay, m_aInfo.screen );
+ }
+ m_aColormap = DefaultColormap( m_pDisplay, m_aInfo.screen );
+#if OSL_DEBUG_LEVEL > 1
+ static const char* pClasses[] =
+ { "StaticGray", "GrayScale", "StaticColor", "PseudoColor", "TrueColor", "DirectColor" };
+ fprintf( stderr, "PixmapHolder visual: id = 0x%lx, class = %s (%d), depth=%d; color map = 0x%lx\n",
+ m_aInfo.visualid,
+ (m_aInfo.c_class >= 0 && unsigned(m_aInfo.c_class) < sizeof(pClasses)/sizeof(pClasses[0])) ? pClasses[m_aInfo.c_class] : "<unknown>",
+ m_aInfo.c_class,
+ m_aInfo.depth,
+ m_aColormap );
+#endif
+ if( m_aInfo.c_class == TrueColor )
+ {
+ int nRedSig, nGreenSig, nBlueSig;
+ m_nRedShift = m_nRedShift2 = 0;
+ getShift( m_aInfo.red_mask, m_nRedShift, nRedSig, m_nRedShift2 );
+ m_nGreenShift = m_nGreenShift2 = 0;
+ getShift( m_aInfo.green_mask, m_nGreenShift, nGreenSig, m_nGreenShift2 );
+ m_nBlueShift = m_nBlueShift2 = 0;
+ getShift( m_aInfo.blue_mask, m_nBlueShift, nBlueSig, m_nBlueShift2 );
+
+ m_nBlueShift2Mask = m_nBlueShift2 ? ~((unsigned long)((1<<m_nBlueShift2)-1)) : ~0L;
+ m_nGreenShift2Mask = m_nGreenShift2 ? ~((unsigned long)((1<<m_nGreenShift2)-1)) : ~0L;
+ m_nRedShift2Mask = m_nRedShift2 ? ~((unsigned long)((1<<m_nRedShift2)-1)) : ~0L;
+ }
+}
+
+PixmapHolder::~PixmapHolder()
+{
+ if( m_aPixmap != None )
+ XFreePixmap( m_pDisplay, m_aPixmap );
+ if( m_aBitmap != None )
+ XFreePixmap( m_pDisplay, m_aBitmap );
+}
+
+unsigned long PixmapHolder::getTCPixel( sal_uInt8 r, sal_uInt8 g, sal_uInt8 b ) const
+{
+ unsigned long nPixel = 0;
+ unsigned long nValue = (unsigned long)b;
+ nValue &= m_nBlueShift2Mask;
+ nPixel |= doLeftShift( nValue, m_nBlueShift );
+
+ nValue = (unsigned long)g;
+ nValue &= m_nGreenShift2Mask;
+ nPixel |= doLeftShift( nValue, m_nGreenShift );
+
+ nValue = (unsigned long)r;
+ nValue &= m_nRedShift2Mask;
+ nPixel |= doLeftShift( nValue, m_nRedShift );
+
+ return nPixel;
+}
+
+void PixmapHolder::setBitmapDataPalette( const sal_uInt8* pData, XImage* pImage )
+{
+ // setup palette
+ XColor aPalette[256];
+
+ sal_uInt32 nColors = readLE32( pData+32 );
+ sal_uInt32 nWidth = readLE32( pData+4 );
+ sal_uInt32 nHeight = readLE32( pData+8 );
+ sal_uInt16 nDepth = readLE16( pData+14 );
+
+ for( sal_uInt16 i = 0 ; i < nColors; i++ )
+ {
+ if( m_aInfo.c_class != TrueColor )
+ {
+ aPalette[i].red = ((unsigned short)pData[42 + i*4]) << 8 | ((unsigned short)pData[42 + i*4]);
+ aPalette[i].green = ((unsigned short)pData[41 + i*4]) << 8 | ((unsigned short)pData[41 + i*4]);
+ aPalette[i].blue = ((unsigned short)pData[40 + i*4]) << 8 | ((unsigned short)pData[40 + i*4]);
+ XAllocColor( m_pDisplay, m_aColormap, aPalette+i );
+ }
+ else
+ aPalette[i].pixel = getTCPixel( pData[42+i*4], pData[41+i*4], pData[40+i*4] );
+ }
+ const sal_uInt8* pBMData = pData + readLE32( pData ) + 4*nColors;
+
+ sal_uInt32 nScanlineSize = 0;
+ switch( nDepth )
+ {
+ case 1:
+ nScanlineSize = (nWidth+31)/32;
+ break;
+ case 4:
+ nScanlineSize = (nWidth+1)/2;
+ break;
+ case 8:
+ nScanlineSize = nWidth;
+ break;
+ }
+ // adjust scan lines to begin on %4 boundaries
+ if( nScanlineSize & 3 )
+ {
+ nScanlineSize &= 0xfffffffc;
+ nScanlineSize += 4;
+ }
+
+ // allocate buffer to hold header and scanlines, initialize to zero
+ for( unsigned int y = 0; y < nHeight; y++ )
+ {
+ const sal_uInt8* pScanline = pBMData + (nHeight-1-y)*nScanlineSize;
+ for( unsigned int x = 0; x < nWidth; x++ )
+ {
+ int nCol = 0;
+ switch( nDepth )
+ {
+ case 1: nCol = (pScanline[ x/8 ] & (0x80 >> (x&7))) != 0 ? 0 : 1; break;
+ case 4:
+ if( x & 1 )
+ nCol = (int)(pScanline[ x/2 ] >> 4);
+ else
+ nCol = (int)(pScanline[ x/2 ] & 0x0f);
+ break;
+ case 8: nCol = (int)pScanline[x];
+ }
+ XPutPixel( pImage, x, y, aPalette[nCol].pixel );
+ }
+ }
+}
+
+void PixmapHolder::setBitmapDataTCDither( const sal_uInt8* pData, XImage* pImage )
+{
+ XColor aPalette[216];
+
+ int nNonAllocs = 0;
+
+ for( int r = 0; r < 6; r++ )
+ {
+ for( int g = 0; g < 6; g++ )
+ {
+ for( int b = 0; b < 6; b++ )
+ {
+ int i = r*36+g*6+b;
+ aPalette[i].red = r == 5 ? 0xffff : r*10922;
+ aPalette[i].green = g == 5 ? 0xffff : g*10922;
+ aPalette[i].blue = b == 5 ? 0xffff : b*10922;
+ aPalette[i].pixel = 0;
+ if( ! XAllocColor( m_pDisplay, m_aColormap, aPalette+i ) )
+ nNonAllocs++;
+ }
+ }
+ }
+
+ if( nNonAllocs )
+ {
+ XColor aRealPalette[256];
+ int nColors = 1 << m_aInfo.depth;
+ int i;
+ for( i = 0; i < nColors; i++ )
+ aRealPalette[i].pixel = (unsigned long)i;
+ XQueryColors( m_pDisplay, m_aColormap, aRealPalette, nColors );
+ for( i = 0; i < nColors; i++ )
+ {
+ sal_uInt8 nIndex =
+ 36*(sal_uInt8)(aRealPalette[i].red/10923) +
+ 6*(sal_uInt8)(aRealPalette[i].green/10923) +
+ (sal_uInt8)(aRealPalette[i].blue/10923);
+ if( aPalette[nIndex].pixel == 0 )
+ aPalette[nIndex] = aRealPalette[i];
+ }
+ }
+
+ sal_uInt32 nWidth = readLE32( pData+4 );
+ sal_uInt32 nHeight = readLE32( pData+8 );
+
+ const sal_uInt8* pBMData = pData + readLE32( pData );
+ sal_uInt32 nScanlineSize = nWidth*3;
+ // adjust scan lines to begin on %4 boundaries
+ if( nScanlineSize & 3 )
+ {
+ nScanlineSize &= 0xfffffffc;
+ nScanlineSize += 4;
+ }
+
+ for( int y = 0; y < (int)nHeight; y++ )
+ {
+ const sal_uInt8* pScanline = pBMData + (nHeight-1-(sal_uInt32)y)*nScanlineSize;
+ for( int x = 0; x < (int)nWidth; x++ )
+ {
+ sal_uInt8 b = pScanline[3*x];
+ sal_uInt8 g = pScanline[3*x+1];
+ sal_uInt8 r = pScanline[3*x+2];
+ sal_uInt8 i = 36*(r/43) + 6*(g/43) + (b/43);
+
+ XPutPixel( pImage, x, y, aPalette[ i ].pixel );
+ }
+ }
+}
+
+void PixmapHolder::setBitmapDataTC( const sal_uInt8* pData, XImage* pImage )
+{
+ sal_uInt32 nWidth = readLE32( pData+4 );
+ sal_uInt32 nHeight = readLE32( pData+8 );
+
+ const sal_uInt8* pBMData = pData + readLE32( pData );
+ sal_uInt32 nScanlineSize = nWidth*3;
+ // adjust scan lines to begin on %4 boundaries
+ if( nScanlineSize & 3 )
+ {
+ nScanlineSize &= 0xfffffffc;
+ nScanlineSize += 4;
+ }
+
+ for( int y = 0; y < (int)nHeight; y++ )
+ {
+ const sal_uInt8* pScanline = pBMData + (nHeight-1-(sal_uInt32)y)*nScanlineSize;
+ for( int x = 0; x < (int)nWidth; x++ )
+ {
+ unsigned long nPixel = getTCPixel( pScanline[3*x+2], pScanline[3*x+1], pScanline[3*x] );
+ XPutPixel( pImage, x, y, nPixel );
+ }
+ }
+}
+
+bool PixmapHolder::needsConversion( const sal_uInt8* pData )
+{
+ if( pData[0] != 'B' || pData[1] != 'M' )
+ return true;
+
+ pData = pData+14;
+ sal_uInt32 nDepth = readLE32( pData+14 );
+ if( nDepth == 24 )
+ {
+ if( m_aInfo.c_class != TrueColor )
+ return true;
+ }
+ else if( nDepth != (sal_uInt32)m_aInfo.depth )
+ {
+ if( m_aInfo.c_class != TrueColor )
+ return true;
+ }
+
+ return false;
+}
+
+Pixmap PixmapHolder::setBitmapData( const sal_uInt8* pData )
+{
+ if( pData[0] != 'B' || pData[1] != 'M' )
+ return None;
+
+ pData = pData+14;
+
+ // reject compressed data
+ if( readLE32( pData + 16 ) != 0 )
+ return None;
+
+ sal_uInt32 nWidth = readLE32( pData+4 );
+ sal_uInt32 nHeight = readLE32( pData+8 );
+
+ if( m_aPixmap != None )
+ XFreePixmap( m_pDisplay, m_aPixmap ), m_aPixmap = None;
+ if( m_aBitmap != None )
+ XFreePixmap( m_pDisplay, m_aBitmap ), m_aBitmap = None;
+
+ m_aPixmap = XCreatePixmap( m_pDisplay,
+ RootWindow( m_pDisplay, m_aInfo.screen ),
+ nWidth, nHeight, m_aInfo.depth );
+
+ if( m_aPixmap != None )
+ {
+ XImage aImage;
+ aImage.width = (int)nWidth;
+ aImage.height = (int)nHeight;
+ aImage.xoffset = 0;
+ aImage.format = ZPixmap;
+ aImage.data = NULL;
+ aImage.byte_order = ImageByteOrder( m_pDisplay );
+ aImage.bitmap_unit = BitmapUnit( m_pDisplay );
+ aImage.bitmap_bit_order = BitmapBitOrder( m_pDisplay );
+ aImage.bitmap_pad = BitmapPad( m_pDisplay );
+ aImage.depth = m_aInfo.depth;
+ aImage.red_mask = m_aInfo.red_mask;
+ aImage.green_mask = m_aInfo.green_mask;
+ aImage.blue_mask = m_aInfo.blue_mask;
+ aImage.bytes_per_line = 0; // filled in by XInitImage
+ if( m_aInfo.depth <= 8 )
+ aImage.bits_per_pixel = m_aInfo.depth;
+ else
+ aImage.bits_per_pixel = 8*((m_aInfo.depth+7)/8);
+ aImage.obdata = NULL;
+
+ XInitImage( &aImage );
+ aImage.data = (char*)rtl_allocateMemory( nHeight*aImage.bytes_per_line );
+
+ if( readLE32( pData+14 ) == 24 )
+ {
+ if( m_aInfo.c_class == TrueColor )
+ setBitmapDataTC( pData, &aImage );
+ else
+ setBitmapDataTCDither( pData, &aImage );
+ }
+ else
+ setBitmapDataPalette( pData, &aImage );
+
+ // put the image
+ XPutImage( m_pDisplay,
+ m_aPixmap,
+ DefaultGC( m_pDisplay, m_aInfo.screen ),
+ &aImage,
+ 0, 0,
+ 0, 0,
+ nWidth, nHeight );
+
+ // clean up
+ rtl_freeMemory( aImage.data );
+
+ // prepare bitmap (mask)
+ m_aBitmap = XCreatePixmap( m_pDisplay,
+ RootWindow( m_pDisplay, m_aInfo.screen ),
+ nWidth, nHeight, 1 );
+ XGCValues aVal;
+ aVal.function = GXcopy;
+ aVal.foreground = 0xffffffff;
+ GC aGC = XCreateGC( m_pDisplay, m_aBitmap, GCFunction | GCForeground, &aVal );
+ XFillRectangle( m_pDisplay, m_aBitmap, aGC, 0, 0, nWidth, nHeight );
+ XFreeGC( m_pDisplay, aGC );
+ }
+
+ return m_aPixmap;
+}
diff --git a/vcl/unx/source/dtrans/bmp.hxx b/vcl/unx/source/dtrans/bmp.hxx
new file mode 100644
index 000000000000..baf04ac31d90
--- /dev/null
+++ b/vcl/unx/source/dtrans/bmp.hxx
@@ -0,0 +1,106 @@
+/*************************************************************************
+ *
+ * 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: bmp.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 _DTRANS_BMP_HXX_
+#define _DTRANS_BMP_HXX_
+
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <sal/types.h>
+#include <com/sun/star/awt/XBitmap.hpp>
+#include <cppuhelper/compbase1.hxx>
+
+
+
+namespace x11 {
+
+// helper methods
+sal_uInt8* X11_getBmpFromPixmap( Display* pDisplay,
+ Drawable aDrawable,
+ Colormap aColormap,
+ sal_Int32& rOutSize );
+
+void X11_freeBmp( sal_uInt8* pBmp );
+
+class PixmapHolder
+{
+ Display* m_pDisplay;
+ Colormap m_aColormap;
+ Pixmap m_aPixmap;
+ Pixmap m_aBitmap;
+ XVisualInfo m_aInfo;
+
+ int m_nRedShift, m_nRedShift2;
+ int m_nGreenShift, m_nGreenShift2;
+ int m_nBlueShift, m_nBlueShift2;
+ unsigned long m_nBlueShift2Mask, m_nRedShift2Mask, m_nGreenShift2Mask;
+
+ // these expect data pointers to bitmapinfo header
+ void setBitmapDataTC( const sal_uInt8* pData, XImage* pImage );
+ void setBitmapDataTCDither( const sal_uInt8* pData, XImage* pImage );
+ void setBitmapDataPalette( const sal_uInt8* pData, XImage* pImage );
+
+ unsigned long getTCPixel( sal_uInt8 r, sal_uInt8 g, sal_uInt8 b ) const;
+public:
+ PixmapHolder( Display* pDisplay );
+ ~PixmapHolder();
+
+ // accepts bitmap file (including bitmap file header)
+ Pixmap setBitmapData( const sal_uInt8* pData );
+ bool needsConversion( const sal_uInt8* pData );
+
+ Colormap getColormap() const { return m_aColormap; }
+ Pixmap getPixmap() const { return m_aPixmap; }
+ Pixmap getBitmap() const { return m_aBitmap; }
+ VisualID getVisualID() const { return m_aInfo.visualid; }
+ int getClass() const { return m_aInfo.c_class; }
+ int getDepth() const { return m_aInfo.depth; }
+};
+
+class BmpTransporter :
+ public cppu::WeakImplHelper1< com::sun::star::awt::XBitmap >
+{
+ com::sun::star::uno::Sequence<sal_Int8> m_aBM;
+ com::sun::star::awt::Size m_aSize;
+public:
+ BmpTransporter( const com::sun::star::uno::Sequence<sal_Int8>& rBmp );
+ virtual ~BmpTransporter();
+
+ virtual com::sun::star::awt::Size SAL_CALL getSize() throw();
+ virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getDIB() throw();
+ virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getMaskDIB() throw();
+};
+
+}
+
+#endif
diff --git a/vcl/unx/source/dtrans/config.cxx b/vcl/unx/source/dtrans/config.cxx
new file mode 100644
index 000000000000..2402fb4452c3
--- /dev/null
+++ b/vcl/unx/source/dtrans/config.cxx
@@ -0,0 +1,151 @@
+/*************************************************************************
+ *
+ * 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: config.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 <cstdio>
+#include <unotools/configitem.hxx>
+
+#include "X11_selection.hxx"
+
+#define SETTINGS_CONFIGNODE "VCL/Settings/Transfer"
+#define SELECTION_PROPERTY "SelectionTimeout"
+
+namespace x11
+{
+
+class DtransX11ConfigItem : public ::utl::ConfigItem
+{
+ sal_Int32 m_nSelectionTimeout;
+
+ virtual void Notify( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rPropertyNames );
+ virtual void Commit();
+public:
+ DtransX11ConfigItem();
+ virtual ~DtransX11ConfigItem();
+
+ sal_Int32 getSelectionTimeout() const { return m_nSelectionTimeout; }
+};
+
+}
+
+using namespace com::sun::star::lang;
+using namespace com::sun::star::uno;
+using namespace rtl;
+using namespace x11;
+
+sal_Int32 SelectionManager::getSelectionTimeout()
+{
+ if( m_nSelectionTimeout < 1 )
+ {
+ DtransX11ConfigItem aCfg;
+ m_nSelectionTimeout = aCfg.getSelectionTimeout();
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "initialized selection timeout to %ld seconds\n", m_nSelectionTimeout );
+#endif
+ }
+ return m_nSelectionTimeout;
+}
+
+/*
+ * DtransX11ConfigItem constructor
+ */
+
+DtransX11ConfigItem::DtransX11ConfigItem() :
+ ConfigItem( OUString( RTL_CONSTASCII_USTRINGPARAM( SETTINGS_CONFIGNODE ) ),
+ CONFIG_MODE_DELAYED_UPDATE ),
+ m_nSelectionTimeout( 3 )
+{
+ if( IsValidConfigMgr() )
+ {
+ Sequence< OUString > aKeys( 1 );
+ aKeys.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( SELECTION_PROPERTY ) );
+ Sequence< Any > aValues = GetProperties( aKeys );
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "found %ld properties for %s\n", aValues.getLength(), SELECTION_PROPERTY );
+#endif
+ Any* pValue = aValues.getArray();
+ for( int i = 0; i < aValues.getLength(); i++, pValue++ )
+ {
+ if( pValue->getValueTypeClass() == TypeClass_STRING )
+ {
+ const OUString* pLine = (const OUString*)pValue->getValue();
+ if( pLine->getLength() )
+ {
+ m_nSelectionTimeout = pLine->toInt32();
+ if( m_nSelectionTimeout < 1 )
+ m_nSelectionTimeout = 1;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "found SelectionTimeout \"%s\"\n",
+ OUStringToOString( *pLine, osl_getThreadTextEncoding() ).getStr() );
+#endif
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ fprintf( stderr, "found SelectionTimeout of type \"%s\"\n",
+ OUStringToOString( pValue->getValueType().getTypeName(), osl_getThreadTextEncoding() ).getStr() );
+#endif
+ }
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ fprintf( stderr, "no valid configmanager, could not read timeout setting\n" );
+#endif
+}
+
+/*
+ * DtransX11ConfigItem destructor
+ */
+
+DtransX11ConfigItem::~DtransX11ConfigItem()
+{
+}
+
+/*
+ * DtransX11ConfigItem::Commit
+ */
+
+void DtransX11ConfigItem::Commit()
+{
+ // for the clipboard service this is readonly, so
+ // there is nothing to commit
+}
+
+/*
+ * DtransX11ConfigItem::Notify
+ */
+
+void DtransX11ConfigItem::Notify( const Sequence< OUString >& /*rPropertyNames*/ )
+{
+}
+
+
diff --git a/vcl/unx/source/dtrans/copydata_curs.h b/vcl/unx/source/dtrans/copydata_curs.h
new file mode 100644
index 000000000000..21a095521939
--- /dev/null
+++ b/vcl/unx/source/dtrans/copydata_curs.h
@@ -0,0 +1,45 @@
+/*************************************************************************
+ *
+ * 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: copydata_curs.h,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.
+ *
+ ************************************************************************/
+#define copydata_curs_width 32
+#define copydata_curs_height 32
+#define copydata_curs_x_hot 1
+#define copydata_curs_y_hot 1
+static char copydata_curs_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
+ 0x7e, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00,
+ 0xfe, 0x03, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00,
+ 0x66, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
+ 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x10, 0x53, 0x00, 0x00,
+ 0x28, 0xa3, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x10, 0xf0, 0x1f, 0x00, 0x08, 0xf0, 0x1f, 0x00, 0x10, 0xf0, 0x1e, 0x00,
+ 0xa8, 0xf2, 0x1e, 0x00, 0x50, 0x35, 0x18, 0x00, 0x00, 0xf0, 0x1e, 0x00,
+ 0x00, 0xf0, 0x1e, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0xf0, 0x1f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/vcl/unx/source/dtrans/copydata_mask.h b/vcl/unx/source/dtrans/copydata_mask.h
new file mode 100644
index 000000000000..25db64d9bfee
--- /dev/null
+++ b/vcl/unx/source/dtrans/copydata_mask.h
@@ -0,0 +1,45 @@
+/*************************************************************************
+ *
+ * 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: copydata_mask.h,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.
+ *
+ ************************************************************************/
+#define copydata_mask_width 32
+#define copydata_mask_height 32
+#define copydata_mask_x_hot 1
+#define copydata_mask_y_hot 1
+static char copydata_mask_bits[] = {
+ 0x07, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+ 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
+ 0xff, 0x01, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00,
+ 0xff, 0x07, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
+ 0xff, 0x01, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0xe7, 0x03, 0x00, 0x00,
+ 0xe0, 0x03, 0x00, 0x00, 0xf8, 0xff, 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00,
+ 0xfc, 0xff, 0x01, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x3c, 0xf8, 0x3f, 0x00,
+ 0x3c, 0xf8, 0x3f, 0x00, 0x3c, 0xf8, 0x3f, 0x00, 0xfc, 0xff, 0x3f, 0x00,
+ 0xfc, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0x3f, 0x00,
+ 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00,
+ 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/vcl/unx/source/dtrans/linkdata_curs.h b/vcl/unx/source/dtrans/linkdata_curs.h
new file mode 100644
index 000000000000..01ea8678acd2
--- /dev/null
+++ b/vcl/unx/source/dtrans/linkdata_curs.h
@@ -0,0 +1,45 @@
+/*************************************************************************
+ *
+ * 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: linkdata_curs.h,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.
+ *
+ ************************************************************************/
+#define linkdata_curs_width 32
+#define linkdata_curs_height 32
+#define linkdata_curs_x_hot 1
+#define linkdata_curs_y_hot 1
+static char linkdata_curs_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
+ 0x7e, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00,
+ 0xfe, 0x03, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00,
+ 0x66, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
+ 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x10, 0x53, 0x00, 0x00,
+ 0x28, 0xa3, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x10, 0xf0, 0x1f, 0x00, 0x08, 0x70, 0x18, 0x00, 0x10, 0xf0, 0x18, 0x00,
+ 0xa8, 0x72, 0x18, 0x00, 0x50, 0x35, 0x1a, 0x00, 0x00, 0x30, 0x1f, 0x00,
+ 0x00, 0xb0, 0x1f, 0x00, 0x00, 0x70, 0x1f, 0x00, 0x00, 0xf0, 0x1f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/vcl/unx/source/dtrans/linkdata_mask.h b/vcl/unx/source/dtrans/linkdata_mask.h
new file mode 100644
index 000000000000..b4207ad40dcf
--- /dev/null
+++ b/vcl/unx/source/dtrans/linkdata_mask.h
@@ -0,0 +1,45 @@
+/*************************************************************************
+ *
+ * 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: linkdata_mask.h,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.
+ *
+ ************************************************************************/
+#define linkdata_mask_width 32
+#define linkdata_mask_height 32
+#define linkdata_mask_x_hot 1
+#define linkdata_mask_y_hot 1
+static char linkdata_mask_bits[] = {
+ 0x07, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+ 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
+ 0xff, 0x01, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00,
+ 0xff, 0x07, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
+ 0xff, 0x01, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0xe7, 0x03, 0x00, 0x00,
+ 0xe0, 0x03, 0x00, 0x00, 0xf8, 0xff, 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00,
+ 0xfc, 0xff, 0x01, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x3c, 0xf8, 0x3f, 0x00,
+ 0x3c, 0xf8, 0x3f, 0x00, 0x3c, 0xf8, 0x3f, 0x00, 0xfc, 0xff, 0x3f, 0x00,
+ 0xfc, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0x3f, 0x00,
+ 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00,
+ 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/vcl/unx/source/dtrans/makefile.mk b/vcl/unx/source/dtrans/makefile.mk
new file mode 100644
index 000000000000..6af3a7c75048
--- /dev/null
+++ b/vcl/unx/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=dtransX11
+TARGETTYPE=GUI
+
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# ------------------------------------------------------------------
+
+.IF "$(GUIBASE)"=="aqua"
+
+dummy:
+ @echo "Nothing to build for Mac OS X"
+
+.ELSE # "$(GUIBASE)"=="aqua"
+
+.IF "$(COM)$(CPU)" == "C50I" || "$(COM)$(CPU)" == "C52I"
+NOOPTFILES=\
+ $(SLO)$/X11_selection.obj
+.ENDIF
+
+SLOFILES=\
+ $(SLO)$/X11_dndcontext.obj \
+ $(SLO)$/X11_transferable.obj \
+ $(SLO)$/X11_clipboard.obj \
+ $(SLO)$/X11_selection.obj \
+ $(SLO)$/X11_droptarget.obj \
+ $(SLO)$/X11_service.obj \
+ $(SLO)$/bmp.obj \
+ $(SLO)$/config.obj
+
+.ENDIF # "$(OS)"=="MACOSX"
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/vcl/unx/source/dtrans/movedata_curs.h b/vcl/unx/source/dtrans/movedata_curs.h
new file mode 100644
index 000000000000..36845d5e9d1e
--- /dev/null
+++ b/vcl/unx/source/dtrans/movedata_curs.h
@@ -0,0 +1,45 @@
+/*************************************************************************
+ *
+ * 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: movedata_curs.h,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.
+ *
+ ************************************************************************/
+#define movedata_curs_width 32
+#define movedata_curs_height 32
+#define movedata_curs_x_hot 1
+#define movedata_curs_y_hot 1
+static char movedata_curs_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
+ 0x7e, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00,
+ 0xfe, 0x03, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00,
+ 0x66, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
+ 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x10, 0x53, 0x00, 0x00,
+ 0x28, 0xa3, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00,
+ 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00,
+ 0xa8, 0xaa, 0x00, 0x00, 0x50, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/vcl/unx/source/dtrans/movedata_mask.h b/vcl/unx/source/dtrans/movedata_mask.h
new file mode 100644
index 000000000000..facca718b8bf
--- /dev/null
+++ b/vcl/unx/source/dtrans/movedata_mask.h
@@ -0,0 +1,45 @@
+/*************************************************************************
+ *
+ * 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: movedata_mask.h,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.
+ *
+ ************************************************************************/
+#define movedata_mask_width 32
+#define movedata_mask_height 32
+#define movedata_mask_x_hot 1
+#define movedata_mask_y_hot 1
+static char movedata_mask_bits[] = {
+ 0x07, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+ 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
+ 0xff, 0x01, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00,
+ 0xff, 0x07, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
+ 0xff, 0x01, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0xe7, 0x03, 0x00, 0x00,
+ 0xe0, 0x03, 0x00, 0x00, 0xf8, 0xff, 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00,
+ 0xfc, 0xff, 0x01, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x3c, 0xe0, 0x01, 0x00,
+ 0x3c, 0xe0, 0x01, 0x00, 0x3c, 0xe0, 0x01, 0x00, 0xfc, 0xff, 0x01, 0x00,
+ 0xfc, 0xff, 0x01, 0x00, 0xfc, 0xff, 0x01, 0x00, 0xf8, 0xff, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/vcl/unx/source/dtrans/nodrop_curs.h b/vcl/unx/source/dtrans/nodrop_curs.h
new file mode 100644
index 000000000000..725b0fccf91b
--- /dev/null
+++ b/vcl/unx/source/dtrans/nodrop_curs.h
@@ -0,0 +1,45 @@
+/*************************************************************************
+ *
+ * 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: nodrop_curs.h,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.
+ *
+ ************************************************************************/
+#define nodrop_curs_width 32
+#define nodrop_curs_height 32
+#define nodrop_curs_x_hot 9
+#define nodrop_curs_y_hot 9
+static char nodrop_curs_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00,
+ 0xf8, 0x7f, 0x00, 0x00, 0x7c, 0xf8, 0x00, 0x00, 0x1c, 0xfc, 0x00, 0x00,
+ 0x1e, 0xfe, 0x01, 0x00, 0x0e, 0xdf, 0x01, 0x00, 0x8e, 0xcf, 0x01, 0x00,
+ 0xce, 0xc7, 0x01, 0x00, 0xee, 0xc3, 0x01, 0x00, 0xfe, 0xe1, 0x01, 0x00,
+ 0xfc, 0xe0, 0x00, 0x00, 0x7c, 0xf8, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00,
+ 0xf0, 0x3f, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/vcl/unx/source/dtrans/nodrop_mask.h b/vcl/unx/source/dtrans/nodrop_mask.h
new file mode 100644
index 000000000000..ef67a2bc2642
--- /dev/null
+++ b/vcl/unx/source/dtrans/nodrop_mask.h
@@ -0,0 +1,45 @@
+/*************************************************************************
+ *
+ * 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: nodrop_mask.h,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.
+ *
+ ************************************************************************/
+#define nodrop_mask_width 32
+#define nodrop_mask_height 32
+#define nodrop_mask_x_hot 9
+#define nodrop_mask_y_hot 9
+static char nodrop_mask_bits[] = {
+ 0xc0, 0x0f, 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00,
+ 0xfc, 0xff, 0x00, 0x00, 0xfe, 0xff, 0x01, 0x00, 0x7e, 0xfe, 0x01, 0x00,
+ 0x3f, 0xff, 0x03, 0x00, 0x9f, 0xff, 0x03, 0x00, 0xdf, 0xff, 0x03, 0x00,
+ 0xff, 0xef, 0x03, 0x00, 0xff, 0xe7, 0x03, 0x00, 0xff, 0xf3, 0x03, 0x00,
+ 0xfe, 0xf9, 0x01, 0x00, 0xfe, 0xff, 0x01, 0x00, 0xfc, 0xff, 0x00, 0x00,
+ 0xf8, 0x7f, 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/vcl/unx/source/gdi/cdeint.cxx b/vcl/unx/source/gdi/cdeint.cxx
index 4d2a6dba78ca..3794737b293e 100644
--- a/vcl/unx/source/gdi/cdeint.cxx
+++ b/vcl/unx/source/gdi/cdeint.cxx
@@ -216,6 +216,7 @@ void CDEIntegrator::GetSystemLook( AllSettings& rSettings )
aStyleSettings.SetDialogTextColor( aDeactive );
aStyleSettings.SetMenuTextColor( aDeactive );
+ aStyleSettings.SetMenuBarTextColor( aDeactive );
aStyleSettings.SetButtonTextColor( aDeactive );
aStyleSettings.SetRadioCheckTextColor( aDeactive );
aStyleSettings.SetGroupTextColor( aDeactive );
diff --git a/vcl/unx/source/gdi/salgdi.cxx b/vcl/unx/source/gdi/salgdi.cxx
index 4d3e40840a7b..34f2dfd4b935 100644
--- a/vcl/unx/source/gdi/salgdi.cxx
+++ b/vcl/unx/source/gdi/salgdi.cxx
@@ -1176,11 +1176,11 @@ typedef std::multiset< int, TrapezoidYCompare > VerticalTrapSet;
} // end of anonymous namespace
// draw a poly-polygon
-bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly, double fTransparency)
+bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPolyPoly, double fTransparency)
{
// nothing to do for empty polypolygons
- const int nPolygonCount = rPolyPoly.count();
- if( nPolygonCount <= 0 )
+ const int nOrigPolyCount = rOrigPolyPoly.count();
+ if( nOrigPolyCount <= 0 )
return TRUE;
// nothing to do if everything is transparent
@@ -1209,28 +1209,22 @@ bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly
// don't bother with polygons outside of visible area
const basegfx::B2DRange aViewRange( 0, 0, GetGraphicsWidth(), GetGraphicsHeight() );
- const basegfx::B2DRange aPolyRange = basegfx::tools::getRange( rPolyPoly );
+ const basegfx::B2DRange aPolyRange = basegfx::tools::getRange( rOrigPolyPoly );
const bool bNeedViewClip = !aPolyRange.isInside( aViewRange );
if( !aPolyRange.overlaps( aViewRange ) )
return true;
// convert the polypolygon to trapezoids
- // first convert the B2DPolyPolygon to HalfTrapezoids
- // #i100922# try to prevent priority-queue reallocations by reservering enough
+ // prepare the polypolygon for the algorithm below:
+ // - clip it against the view range
+ // - make sure it contains no self-intersections
+ // while we are at it guess the number of involved polygon points
int nHTQueueReserve = 0;
- for( int nOuterPolyIdx = 0; nOuterPolyIdx < nPolygonCount; ++nOuterPolyIdx )
- {
- const ::basegfx::B2DPolygon aOuterPolygon = rPolyPoly.getB2DPolygon( nOuterPolyIdx );
- const int nPointCount = aOuterPolygon.count();
- nHTQueueReserve += aOuterPolygon.areControlPointsUsed() ? 8 * nPointCount : nPointCount;
- }
- nHTQueueReserve = ((4*nHTQueueReserve) | 0x1FFF) + 1;
- HTQueue aHTQueue;
- aHTQueue.reserve( nHTQueueReserve );
- for( int nOuterPolyIdx = 0; nOuterPolyIdx < nPolygonCount; ++nOuterPolyIdx )
+ basegfx::B2DPolyPolygon aGoodPolyPoly;
+ for( int nOrigPolyIdx = 0; nOrigPolyIdx < nOrigPolyCount; ++nOrigPolyIdx )
{
- const ::basegfx::B2DPolygon aOuterPolygon = rPolyPoly.getB2DPolygon( nOuterPolyIdx );
+ const ::basegfx::B2DPolygon aOuterPolygon = rOrigPolyPoly.getB2DPolygon( nOrigPolyIdx );
// render-trapezoids should be inside the view => clip polygon against view range
basegfx::B2DPolyPolygon aClippedPolygon( aOuterPolygon );
@@ -1238,33 +1232,55 @@ bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly
{
aClippedPolygon = basegfx::tools::clipPolygonOnRange( aOuterPolygon, aViewRange, true, false );
DBG_ASSERT( aClippedPolygon.count(), "polygon confirmed to overlap with view should not get here" );
- if( !aClippedPolygon.count() )
- continue;
}
+ const int nClippedPolyCount = aClippedPolygon.count();
+ if( !nClippedPolyCount )
+ continue;
- // render-trapezoids have linear edges => get rid of bezier segments
- if( aClippedPolygon.areControlPointsUsed() )
- aClippedPolygon = ::basegfx::tools::adaptiveSubdivideByDistance( aClippedPolygon, 0.125 );
-
- // test and remove self intersections
- // TODO: make code intersection save, then remove this test
- basegfx::B2DPolyPolygon aInnerPolyPoly(basegfx::tools::solveCrossovers( aClippedPolygon));
- const int nInnerPolyCount = aInnerPolyPoly.count();
- for( int nInnerPolyIdx = 0; nInnerPolyIdx < nInnerPolyCount; ++nInnerPolyIdx )
+ // #i103259# polypoly.solveCrossover() fails to remove self-intersections
+ // but polygon.solveCrossover() works. Use it to build the intersection-free polypolygon
+ // TODO: if the self-intersection prevention is too expensive make the trap-algorithm tolerate intersections
+ for( int nClippedPolyIdx = 0; nClippedPolyIdx < nClippedPolyCount; ++nClippedPolyIdx )
{
- ::basegfx::B2DPolygon aInnerPolygon = aInnerPolyPoly.getB2DPolygon( nInnerPolyIdx );
- const int nPointCount = aInnerPolygon.count();
- if( !nPointCount )
- continue;
+ ::basegfx::B2DPolygon aUnsolvedPolygon = aClippedPolygon.getB2DPolygon( nClippedPolyIdx );
+ basegfx::B2DPolyPolygon aSolvedPolyPoly( basegfx::tools::solveCrossovers( aUnsolvedPolygon) );
+ const int nSolvedPolyCount = aSolvedPolyPoly.count();
+ for( int nSolvedPolyIdx = 0; nSolvedPolyIdx < nSolvedPolyCount; ++nSolvedPolyIdx )
+ {
+ // build the intersection-free polypolygon one by one
+ const ::basegfx::B2DPolygon aSolvedPolygon = aSolvedPolyPoly.getB2DPolygon( nSolvedPolyIdx );
+ aGoodPolyPoly.append( aSolvedPolygon );
+ // and while we are at it use the conviently available point count to guess the number of needed half-traps
+ const int nPointCount = aSolvedPolygon.count();
+ nHTQueueReserve += aSolvedPolygon.areControlPointsUsed() ? 8 * nPointCount : nPointCount;
+ }
+ }
+ }
+ // #i100922# try to prevent priority-queue reallocations by reservering enough
+ nHTQueueReserve = ((4*nHTQueueReserve) | 0x1FFF) + 1;
+ HTQueue aHTQueue;
+ aHTQueue.reserve( nHTQueueReserve );
- aHTQueue.reserve( aHTQueue.size() + 8 * nPointCount );
+ // first convert the B2DPolyPolygon to HalfTrapezoids
+ const int nGoodPolyCount = aGoodPolyPoly.count();
+ for( int nGoodPolyIdx = 0; nGoodPolyIdx < nGoodPolyCount; ++nGoodPolyIdx )
+ {
+ ::basegfx::B2DPolygon aInnerPolygon = aGoodPolyPoly.getB2DPolygon( nGoodPolyIdx );
+
+ // render-trapezoids have linear edges => get rid of bezier segments
+ if( aInnerPolygon.areControlPointsUsed() )
+ aInnerPolygon = ::basegfx::tools::adaptiveSubdivideByDistance( aInnerPolygon, 0.125 );
+ const int nPointCount = aInnerPolygon.count();
+ if( nPointCount >= 3 )
+ {
// convert polygon point pairs to HalfTrapezoids
// connect the polygon point with the first one if needed
XPointFixed aOldXPF = { 0, 0 };
XPointFixed aNewXPF;
for( int nPointIdx = 0; nPointIdx <= nPointCount; ++nPointIdx, aOldXPF = aNewXPF )
{
+ // auto-close the polygon if needed
const int k = (nPointIdx < nPointCount) ? nPointIdx : 0;
const ::basegfx::B2DPoint& aPoint = aInnerPolygon.getB2DPoint( k );
@@ -1551,3 +1567,4 @@ bool X11SalGraphics::drawPolyLine(const ::basegfx::B2DPolygon& rPolygon, const :
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
diff --git a/vcl/unx/source/plugadapt/salplug.cxx b/vcl/unx/source/plugadapt/salplug.cxx
index 8a1ed05b8e25..14de25b13e4d 100644
--- a/vcl/unx/source/plugadapt/salplug.cxx
+++ b/vcl/unx/source/plugadapt/salplug.cxx
@@ -6,9 +6,6 @@
*
* OpenOffice.org - a multi-platform office productivity suite
*
- * $RCSfile: salplug.cxx,v $
- * $Revision: 1.30 $
- *
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
@@ -31,18 +28,14 @@
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"
-#include <osl/module.h>
-#include <osl/process.h>
+#include "osl/module.h"
+#include "osl/process.h"
-#include <rtl/ustrbuf.hxx>
+#include "rtl/ustrbuf.hxx"
-#include <svunx.h>
-#include <tools/prex.h>
-#include <X11/Xatom.h>
-#include <tools/postx.h>
-#include <vcl/salinst.hxx>
-#include <saldata.hxx>
+#include "vcl/salinst.hxx"
+#include "saldata.hxx"
#include <cstdio>
#include <unistd.h>
@@ -130,292 +123,45 @@ static SalInstance* tryInstance( const OUString& rModuleBase )
return pInst;
}
-static bool is_gnome_desktop( Display* pDisplay )
+static const rtl::OUString& get_desktop_environment()
{
- bool ret = false;
-
- // warning: these checks are coincidental, GNOME does not
- // explicitly advertise itself
-
- if ( NULL != getenv( "GNOME_DESKTOP_SESSION_ID" ) )
- ret = true;
-
- if( ! ret )
- {
- Atom nAtom1 = XInternAtom( pDisplay, "GNOME_SM_PROXY", True );
- Atom nAtom2 = XInternAtom( pDisplay, "NAUTILUS_DESKTOP_WINDOW_ID", True );
- if( nAtom1 || nAtom2 )
- {
- int nProperties = 0;
- Atom* pProperties = XListProperties( pDisplay, DefaultRootWindow( pDisplay ), &nProperties );
- if( pProperties && nProperties )
- {
- for( int i = 0; i < nProperties; i++ )
- if( pProperties[ i ] == nAtom1 ||
- pProperties[ i ] == nAtom2 )
- {
- ret = true;
- }
- XFree( pProperties );
- }
- }
- }
-
- if( ! ret )
+ static rtl::OUString aRet;
+ if( ! aRet.getLength() )
{
- Atom nUTFAtom = XInternAtom( pDisplay, "UTF8_STRING", True );
- Atom nNetWMNameAtom = XInternAtom( pDisplay, "_NET_WM_NAME", True );
- if( nUTFAtom && nNetWMNameAtom )
- {
- // another, more expensive check: search for a gnome-panel
- XLIB_Window aRoot, aParent, *pChildren = NULL;
- unsigned int nChildren = 0;
- XQueryTree( pDisplay, DefaultRootWindow( pDisplay ),
- &aRoot, &aParent, &pChildren, &nChildren );
- if( pChildren && nChildren )
- {
- for( unsigned int i = 0; i < nChildren && ! ret; i++ )
- {
- Atom nType = None;
- int nFormat = 0;
- unsigned long nItems = 0, nBytes = 0;
- unsigned char* pProp = NULL;
- XGetWindowProperty( pDisplay,
- pChildren[i],
- nNetWMNameAtom,
- 0, 8,
- False,
- nUTFAtom,
- &nType,
- &nFormat,
- &nItems,
- &nBytes,
- &pProp );
- if( pProp && nType == nUTFAtom )
- {
- OString aWMName( (sal_Char*)pProp );
- if( aWMName.equalsIgnoreAsciiCase( "gnome-panel" ) )
- ret = true;
- }
- if( pProp )
- XFree( pProp );
- }
- XFree( pChildren );
- }
- }
- }
-
- return ret;
-}
-
-static bool bWasXError = false;
-
-static inline bool WasXError()
-{
- bool bRet = bWasXError;
- bWasXError = false;
- return bRet;
-}
-
-extern "C"
-{
- static int autodect_error_handler( Display*, XErrorEvent* )
- {
- bWasXError = true;
- return 0;
- }
-
- typedef int(* XErrorHandler)(Display*,XErrorEvent*);
-}
-
-static int KDEVersion( Display* pDisplay )
-{
- int nRet = 0;
-
- Atom nFullSession = XInternAtom( pDisplay, "KDE_FULL_SESSION", True );
- Atom nKDEVersion = XInternAtom( pDisplay, "KDE_SESSION_VERSION", True );
-
- if( nFullSession )
- {
- if( !nKDEVersion )
- return 3;
-
- Atom aRealType = None;
- int nFormat = 8;
- unsigned long nItems = 0;
- unsigned long nBytesLeft = 0;
- unsigned char* pProperty = NULL;
- XGetWindowProperty( pDisplay,
- DefaultRootWindow( pDisplay ),
- nKDEVersion,
- 0, 1,
- False,
- AnyPropertyType,
- &aRealType,
- &nFormat,
- &nItems,
- &nBytesLeft,
- &pProperty );
- if( !WasXError() && nItems != 0 && pProperty )
- {
- nRet = *reinterpret_cast< sal_Int32* >( pProperty );
- }
- if( pProperty )
- {
- XFree( pProperty );
- pProperty = NULL;
- }
- }
- return nRet;
-}
-
-static bool is_kde_desktop( Display* pDisplay )
-{
- if ( NULL != getenv( "KDE_FULL_SESSION" ) )
- {
- const char *pVer = getenv( "KDE_SESSION_VERSION" );
- if ( !pVer || pVer[0] == '0' )
- {
- return true; // does not exist => KDE3
- }
-
- rtl::OUString aVer( RTL_CONSTASCII_USTRINGPARAM( "3" ) );
- if ( aVer.equalsIgnoreAsciiCaseAscii( pVer ) )
+ OUStringBuffer aModName( 128 );
+ aModName.appendAscii( SAL_DLLPREFIX"desktop_detector" );
+ aModName.appendAscii( SAL_DLLPOSTFIX );
+ aModName.appendAscii( SAL_DLLEXTENSION );
+ OUString aModule = aModName.makeStringAndClear();
+
+ oslModule aMod = osl_loadModuleRelative(
+ reinterpret_cast< oslGenericFunction >( &tryInstance ), aModule.pData,
+ SAL_LOADMODULE_DEFAULT );
+ if( aMod )
{
- return true;
+ rtl::OUString (*pSym)() = (rtl::OUString(*)())
+ osl_getAsciiFunctionSymbol( aMod, "get_desktop_environment" );
+ if( pSym )
+ aRet = pSym();
}
+ osl_unloadModule( aMod );
}
-
- if ( KDEVersion( pDisplay ) == 3 )
- return true;
-
- return false;
-}
-
-static bool is_kde4_desktop( Display* pDisplay )
-{
- if ( NULL != getenv( "KDE_FULL_SESSION" ) )
- {
- rtl::OUString aVer( RTL_CONSTASCII_USTRINGPARAM( "4" ) );
-
- const char *pVer = getenv( "KDE_SESSION_VERSION" );
- if ( pVer && aVer.equalsIgnoreAsciiCaseAscii( pVer ) )
- return true;
- }
-
- if ( KDEVersion( pDisplay ) == 4 )
- return true;
-
- return false;
-}
-
-static bool is_cde_desktop( Display* pDisplay )
-{
- void* pLibrary = NULL;
-
- Atom nDtAtom = XInternAtom( pDisplay, "_DT_WM_READY", True );
- OUString aPathName( RTL_CONSTASCII_USTRINGPARAM( "file:///usr/dt/lib/libDtSvc.so" ) );
- if( nDtAtom && ( pLibrary = osl_loadModule( aPathName.pData, SAL_LOADMODULE_DEFAULT ) ) )
- {
- osl_unloadModule( (oslModule)pLibrary );
- return true;
- }
-
- return false;
-}
-
-
-static const char * get_desktop_environment()
-{
- static const char *pRet = NULL;
- static const char *pOverride = getenv( "OOO_FORCE_DESKTOP" );
-
- if ( pOverride && *pOverride )
- {
- OString aOver( pOverride );
-
- if ( aOver.equalsIgnoreAsciiCase( "cde" ) )
- pRet = desktop_strings[DESKTOP_CDE];
- if ( aOver.equalsIgnoreAsciiCase( "kde" ) )
- pRet = desktop_strings[DESKTOP_KDE];
- if ( aOver.equalsIgnoreAsciiCase( "kde4" ) )
- pRet = desktop_strings[DESKTOP_KDE4];
- if ( aOver.equalsIgnoreAsciiCase( "gnome" ) )
- pRet = desktop_strings[DESKTOP_GNOME];
- if ( aOver.equalsIgnoreAsciiCase( "none" ) )
- pRet = desktop_strings[DESKTOP_UNKNOWN];
- }
-
- if ( NULL == pRet )
- {
- // get display to connect to
- const char* pDisplayStr = getenv( "DISPLAY" );
- int nParams = osl_getCommandArgCount();
- OUString aParam;
- OString aBParm;
- for( int i = 0; i < nParams; i++ )
- {
- osl_getCommandArg( i, &aParam.pData );
- if( aParam.equalsAscii( "-headless" ) )
- {
- pDisplayStr = NULL;
- break;
- }
- if( i < nParams-1 && (aParam.equalsAscii( "-display" ) || aParam.equalsAscii( "--display" )) )
- {
- osl_getCommandArg( i+1, &aParam.pData );
- aBParm = OUStringToOString( aParam, osl_getThreadTextEncoding() );
- pDisplayStr = aBParm.getStr();
- break;
- }
- }
-
- // no server at all
- if( ! pDisplayStr || !*pDisplayStr )
- pRet = desktop_strings[DESKTOP_NONE];
- else
- {
- Display* pDisplay = XOpenDisplay( pDisplayStr );
- if( pDisplay )
- {
- XErrorHandler pOldHdl = XSetErrorHandler( autodect_error_handler );
-
- if ( is_kde4_desktop( pDisplay ) )
- pRet = desktop_strings[DESKTOP_KDE4];
- else if ( is_kde_desktop( pDisplay ) )
- pRet = desktop_strings[DESKTOP_KDE];
- else if ( is_gnome_desktop( pDisplay ) )
- pRet = desktop_strings[DESKTOP_GNOME];
- else if ( is_cde_desktop( pDisplay ) )
- pRet = desktop_strings[DESKTOP_CDE];
- else
- pRet = desktop_strings[DESKTOP_UNKNOWN];
-
- // set the default handler again
- XSetErrorHandler( pOldHdl );
-
- XCloseDisplay( pDisplay );
- }
- }
- }
-
- return pRet;
+ return aRet;
}
-
static const char* autodetect_plugin()
{
- const char * desktop = get_desktop_environment();
+ const rtl::OUString& desktop( get_desktop_environment() );
const char * pRet = "gen";
// no server at all: dummy plugin
- if ( desktop == desktop_strings[DESKTOP_NONE] )
+ if ( desktop.equalsAscii( desktop_strings[DESKTOP_NONE] ) )
pRet = "svp";
- else if ( desktop == desktop_strings[DESKTOP_GNOME] )
+ else if ( desktop.equalsAscii( desktop_strings[DESKTOP_GNOME] ) )
pRet = "gtk";
- else if( desktop == desktop_strings[DESKTOP_KDE] )
+ else if( desktop.equalsAscii( desktop_strings[DESKTOP_KDE] ) )
pRet = "kde";
- else if( desktop == desktop_strings[DESKTOP_KDE4] )
+ else if( desktop.equalsAscii( desktop_strings[DESKTOP_KDE4] ) )
pRet = "kde4";
else
{
@@ -455,19 +201,6 @@ SalInstance *CreateSalInstance()
if( !(pUsePlugin && *pUsePlugin) )
pInst = check_headless_plugin();
- if( ! pInst )
- {
- /* #i92121# workaround deadlocks in the X11 implementation
- */
- static const char* pNoXInitThreads = getenv( "SAL_NO_XINITTHREADS" );
- /* #i90094#
- from now on we know that an X connection will be
- established, so protect X against itself
- */
- if( ! ( pNoXInitThreads && *pNoXInitThreads ) )
- XInitThreads();
- }
-
if( ! pInst && !(pUsePlugin && *pUsePlugin) )
pUsePlugin = autodetect_plugin();
@@ -527,8 +260,7 @@ void SalAbort( const XubString& rErrorText )
const OUString& SalGetDesktopEnvironment()
{
- static OUString aRet = OStringToOUString(OString(get_desktop_environment()), RTL_TEXTENCODING_ASCII_US);
- return aRet;
+ return get_desktop_environment();
}
SalData::SalData() :
diff --git a/vcl/unx/source/printer/ppdparser.cxx b/vcl/unx/source/printer/ppdparser.cxx
index 1caf64ef7e2c..95bc7bca41ca 100644
--- a/vcl/unx/source/printer/ppdparser.cxx
+++ b/vcl/unx/source/printer/ppdparser.cxx
@@ -293,8 +293,14 @@ void PPDParser::initPPDFiles()
}
}
-void PPDParser::getKnownPPDDrivers( std::list< rtl::OUString >& o_rDrivers )
+void PPDParser::getKnownPPDDrivers( std::list< rtl::OUString >& o_rDrivers, bool bRefresh )
{
+ if( bRefresh )
+ {
+ delete pAllPPDFiles;
+ pAllPPDFiles = NULL;
+ }
+
initPPDFiles();
o_rDrivers.clear();
diff --git a/vcl/unx/source/window/salframe.cxx b/vcl/unx/source/window/salframe.cxx
index 04eb9cd32771..6219b50d6ec3 100644
--- a/vcl/unx/source/window/salframe.cxx
+++ b/vcl/unx/source/window/salframe.cxx
@@ -1212,7 +1212,12 @@ void X11SalFrame::Show( BOOL bVisible, BOOL bNoActivate )
XLIB_Time nUserTime = 0;
if( ! bNoActivate && (nStyle_ & (SAL_FRAME_STYLE_OWNERDRAWDECORATION|SAL_FRAME_STYLE_TOOLWINDOW)) == 0 )
- nUserTime = pDisplay_->GetLastUserEventTime();
+ {
+ if( GetDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii("Metacity") )
+ nUserTime = pDisplay_->GetLastUserEventTime( true );
+ else
+ nUserTime = pDisplay_->GetLastUserEventTime();
+ }
GetDisplay()->getWMAdaptor()->setUserTime( this, nUserTime );
// actually map the window
diff --git a/vcl/util/makefile.mk b/vcl/util/makefile.mk
index 5bb18f25ecd3..32620d9e966a 100644
--- a/vcl/util/makefile.mk
+++ b/vcl/util/makefile.mk
@@ -158,6 +158,9 @@ LIB1FILES+= \
$(SLB)$/salwin.lib \
$(SLB)$/salgdi.lib \
$(SLB)$/salapp.lib
+.IF "$(GUIBASE)" == "aqua"
+LIB1FILES+= $(SLB)$/dtransaqua.lib
+.ENDIF
.ENDIF
SHL1TARGET= vcl$(DLLPOSTFIX)
@@ -195,7 +198,8 @@ SHL1USE_EXPORTS=name
.IF "$(GUIBASE)"=="aqua"
SHL1STDLIBS+= \
$(BASEBMPLIB) \
- -lAppleRemote$(DLLPOSTFIX)
+ -lAppleRemote$(DLLPOSTFIX) \
+ -framework QuickTime
LIB1FILES+= \
$(SLB)$/sala11y.lib
@@ -268,9 +272,20 @@ STDSHL1 += ft2lib.lib
# UNX sal plugins
.IF "$(GUI)" == "UNX" && "$(GUIBASE)" != "aqua"
+# desktop detector
+LIB7TARGET=$(SLB)$/idet
+LIB7FILES=$(SLB)$/dtdetect.lib
+SHL7TARGET=desktop_detector$(DLLPOSTFIX)
+SHL7STDLIBS=\
+ $(SALLIB) \
+ $(X11LINK_DYNAMIC)
+SHL7IMPLIB=idet
+SHL7LIBS=$(LIB7TARGET)
+
# basic pure X11 plugin
LIB2TARGET=$(SLB)$/ipure_x
LIB2FILES= \
+ $(SLB)$/dtransX11.lib \
$(SLB)$/printergfx.lib \
$(SLB)$/salwin.lib \
$(SLB)$/salgdi.lib \
@@ -287,6 +302,9 @@ SHL2STDLIBS=\
$(TOOLSLIB) \
$(VOSLIB) \
$(BASEGFXLIB) \
+ $(UNOTOOLSLIB) \
+ $(CPPUHELPERLIB) \
+ $(CPPULIB) \
$(SALLIB)
# prepare linking of Xinerama
@@ -362,7 +380,8 @@ SHL4STDLIBS+=\
$(CPPUHELPERLIB) \
$(CPPULIB) \
$(VOSLIB) \
- $(SALLIB)
+ $(SALLIB) \
+ $(X11LINK_DYNAMIC)
.IF "$(ENABLE_RANDR)" != ""
.IF "$(XRANDR_DLOPEN)" == "FALSE"
@@ -390,7 +409,8 @@ SHL5STDLIBS+=\
$(VCLLIB) \
$(TOOLSLIB) \
$(VOSLIB) \
- $(SALLIB)
+ $(SALLIB) \
+ $(X11LINK_DYNAMIC)
.IF "$(ENABLE_RANDR)" != ""
.IF "$(XRANDR_DLOPEN)" == "FALSE"
@@ -419,7 +439,8 @@ SHL6STDLIBS+=\
$(PSPLIB) \
$(TOOLSLIB) \
$(VOSLIB) \
- $(SALLIB)
+ $(SALLIB) \
+ $(X11LINK_DYNAMIC)
.IF "$(ENABLE_RANDR)" != ""
.IF "$(XRANDR_DLOPEN)" == "FALSE"
diff --git a/vcl/util/makefile2.pmk b/vcl/util/makefile2.pmk
index 0e57d7aeb80b..63b2889bc15d 100644
--- a/vcl/util/makefile2.pmk
+++ b/vcl/util/makefile2.pmk
@@ -34,6 +34,5 @@ CDEFS += -DVCL_DLLIMPLEMENTATION
VISIBILITY_HIDDEN=TRUE
.IF "$(GUIBASE)"=="aqua"
-OBJCXXFLAGS=-x objective-c++ -fobjc-exceptions
CFLAGSCXX+=$(OBJCXXFLAGS)
.ENDIF # "$(GUIBASE)"=="aqua"
diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index 2d335808e4c1..1b80bf578530 100755
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -1920,7 +1920,7 @@ int UniscribeLayout::GetNextGlyphs( int nLen, sal_GlyphId* pGlyphs, Point& rPos,
// calculate the absolute position of the first result glyph in pixel units
const GOFFSET aGOffset = mpGlyphOffsets[ nStart ];
- Point aRelativePos( nXOffset + aGOffset.du, aGOffset.dv );
+ Point aRelativePos( nXOffset + aGOffset.du, -aGOffset.dv );
rPos = GetDrawPosition( aRelativePos );
// fill the result arrays
diff --git a/vcl/win/source/window/salframe.cxx b/vcl/win/source/window/salframe.cxx
index 3ffc358bd76d..4a49d83918da 100644
--- a/vcl/win/source/window/salframe.cxx
+++ b/vcl/win/source/window/salframe.cxx
@@ -440,11 +440,11 @@ SalFrame* ImplSalCreateFrame( WinSalInstance* pInst,
nExSysStyle |= WS_EX_TOOLWINDOW;
pFrame->mbFloatWin = TRUE;
- if ( pEnvTransparentFloats && bLayeredAPI == 1 /*&& !(nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE) */)
+ if ( (bLayeredAPI == 1) && (pEnvTransparentFloats /* does not work remote! || (nSalFrameStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE) */ ) )
nExSysStyle |= WS_EX_LAYERED;
}
- if( nSalFrameStyle & SAL_FRAME_STYLE_TOOLTIP )
+ if( (nSalFrameStyle & SAL_FRAME_STYLE_TOOLTIP) || (nSalFrameStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE) )
nExSysStyle |= WS_EX_TOPMOST;
// init frame data
@@ -2930,6 +2930,7 @@ void WinSalFrame::UpdateSettings( AllSettings& rSettings )
aStyleSettings.SetUseFlatBorders( FALSE );
aStyleSettings.SetUseFlatMenues( FALSE );
aStyleSettings.SetMenuTextColor( ImplWinColorToSal( GetSysColor( COLOR_MENUTEXT ) ) );
+ aStyleSettings.SetMenuBarTextColor( ImplWinColorToSal( GetSysColor( COLOR_MENUTEXT ) ) );
aStyleSettings.SetActiveColor( ImplWinColorToSal( GetSysColor( COLOR_ACTIVECAPTION ) ) );
aStyleSettings.SetActiveTextColor( ImplWinColorToSal( GetSysColor( COLOR_CAPTIONTEXT ) ) );
aStyleSettings.SetDeactiveColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVECAPTION ) ) );
diff --git a/vcl/workben/makefile.mk b/vcl/workben/makefile.mk
index 34316356a1a6..0b89f031651d 100644
--- a/vcl/workben/makefile.mk
+++ b/vcl/workben/makefile.mk
@@ -140,6 +140,7 @@ APP5STDLIBS+=-lsocket
.ENDIF
.INCLUDE : target.mk
+.IF "$(L10N_framework)"==""
ALLTAR : $(BIN)$/applicat.rdb
@@ -151,4 +152,4 @@ $(BIN)$/applicat.rdb : makefile.mk $(UNOUCRRDB)
$(REGCOMP) -register -r applicat.rdb \
-c i18nsearch.uno$(DLLPOST) \
-c i18npool.uno$(DLLPOST)
-
+.ENDIF