summaryrefslogtreecommitdiff
path: root/vcl/aqua/source/app
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/aqua/source/app')
-rw-r--r--vcl/aqua/source/app/makefile.mk63
-rw-r--r--vcl/aqua/source/app/saldata.cxx293
-rw-r--r--vcl/aqua/source/app/salinst.cxx1323
-rwxr-xr-xvcl/aqua/source/app/salnstimer.mm56
-rw-r--r--vcl/aqua/source/app/salsys.cxx220
-rw-r--r--vcl/aqua/source/app/saltimer.cxx135
-rwxr-xr-xvcl/aqua/source/app/vclnsapp.mm518
7 files changed, 2608 insertions, 0 deletions
diff --git a/vcl/aqua/source/app/makefile.mk b/vcl/aqua/source/app/makefile.mk
new file mode 100644
index 000000000000..a0ddcbc02226
--- /dev/null
+++ b/vcl/aqua/source/app/makefile.mk
@@ -0,0 +1,63 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=vcl
+TARGET=salapp
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile2.pmk
+
+# --- Files --------------------------------------------------------
+
+.IF "$(GUIBASE)"!="aqua"
+
+dummy:
+ @echo "Nothing to build for GUIBASE $(GUIBASE)"
+
+.ELSE # "$(GUIBASE)"!="aqua"
+
+SLOFILES= $(SLO)$/salinst.obj \
+ $(SLO)$/saldata.obj \
+ $(SLO)$/vclnsapp.obj \
+ $(SLO)$/saltimer.obj \
+ $(SLO)$/salnstimer.obj \
+ $(SLO)$/salsys.obj
+
+.ENDIF # "$(GUIBASE)"!="aqua"
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+.INCLUDE : $(PRJ)$/util$/target.pmk
+
diff --git a/vcl/aqua/source/app/saldata.cxx b/vcl/aqua/source/app/saldata.cxx
new file mode 100644
index 000000000000..3cb878636ad3
--- /dev/null
+++ b/vcl/aqua/source/app/saldata.cxx
@@ -0,0 +1,293 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include "saldata.hxx"
+#include "salnsmenu.h"
+#include "salinst.h"
+#import "apple_remote/RemoteMainController.h"
+
+oslThreadKey SalData::s_aAutoReleaseKey = 0;
+
+static void SAL_CALL releasePool( void* pPool )
+{
+ if( pPool )
+ [(NSAutoreleasePool*)pPool release];
+}
+
+SalData::SalData()
+:
+ mpTimerProc( NULL ),
+ mpFirstInstance( NULL ),
+ mpFirstObject( NULL ),
+ mpFirstVD( NULL ),
+ mpFirstPrinter( NULL ),
+ mpFontList( NULL ),
+ mpStatusItem( nil ),
+ mxRGBSpace( CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB) ),
+ mxGraySpace( CGColorSpaceCreateWithName(kCGColorSpaceGenericGray) ),
+ mxP50Space( NULL ),
+ mxP50Pattern( NULL ),
+ maCursors( POINTER_COUNT, INVALID_CURSOR_PTR ),
+ mbIsScrollbarDoubleMax( false ),
+ mnSystemVersion( VER_TIGER ),
+ mpMainController( NULL ),
+ mpDockIconClickHandler( nil ),
+ mnDPIX( 0 ),
+ mnDPIY( 0 )
+{
+ if( s_aAutoReleaseKey == 0 )
+ s_aAutoReleaseKey = osl_createThreadKey( releasePool );
+}
+
+SalData::~SalData()
+{
+ CGPatternRelease( mxP50Pattern );
+ CGColorSpaceRelease( mxP50Space );
+ CGColorSpaceRelease( mxRGBSpace );
+ CGColorSpaceRelease( mxGraySpace );
+ for( unsigned int i = 0; i < maCursors.size(); i++ )
+ {
+ NSCursor* pCurs = maCursors[i];
+ if( pCurs && pCurs != INVALID_CURSOR_PTR )
+ [pCurs release];
+ }
+ if( s_aAutoReleaseKey )
+ {
+ // release the last pool
+ NSAutoreleasePool* pPool = nil;
+ pPool = reinterpret_cast<NSAutoreleasePool*>( osl_getThreadKeyData( s_aAutoReleaseKey ) );
+ if( pPool )
+ {
+ osl_setThreadKeyData( s_aAutoReleaseKey, NULL );
+ [pPool release];
+ }
+
+ osl_destroyThreadKey( s_aAutoReleaseKey );
+ s_aAutoReleaseKey = 0;
+ }
+ if ( mpMainController )
+ [mpMainController release];
+}
+
+void SalData::ensureThreadAutoreleasePool()
+{
+ NSAutoreleasePool* pPool = nil;
+ if( s_aAutoReleaseKey )
+ {
+ pPool = reinterpret_cast<NSAutoreleasePool*>( osl_getThreadKeyData( s_aAutoReleaseKey ) );
+ if( ! pPool )
+ {
+ pPool = [[NSAutoreleasePool alloc] init];
+ osl_setThreadKeyData( s_aAutoReleaseKey, pPool );
+ }
+ }
+ else
+ {
+ DBG_ERROR( "no autorelease key" );
+ }
+}
+
+void SalData::drainThreadAutoreleasePool()
+{
+ NSAutoreleasePool* pPool = nil;
+ if( s_aAutoReleaseKey )
+ {
+ pPool = reinterpret_cast<NSAutoreleasePool*>( osl_getThreadKeyData( s_aAutoReleaseKey ) );
+ if( pPool )
+ {
+ // osl_setThreadKeyData( s_aAutoReleaseKey, NULL );
+ // [pPool release];
+ [pPool drain];
+ }
+ else
+ {
+ pPool = [[NSAutoreleasePool alloc] init];
+ osl_setThreadKeyData( s_aAutoReleaseKey, pPool );
+ }
+ }
+ else
+ {
+ DBG_ERROR( "no autorelease key" );
+ }
+}
+
+
+struct curs_ent
+{
+ const char* pBaseName;
+ const NSPoint aHotSpot;
+}
+const aCursorTab[ POINTER_COUNT ] =
+{
+{ NULL, { 0, 0 } }, //POINTER_ARROW
+{ "nullptr", { 16, 16 } }, //POINTER_NULL
+{ "hourglass", { 15, 15 } }, //POINTER_WAIT
+{ NULL, { 0, 0 } }, //POINTER_TEXT
+{ "help", { 0, 0 } }, //POINTER_HELP
+{ NULL, { 0, 0 } }, //POINTER_CROSS
+{ NULL, { 0, 0 } }, //POINTER_MOVE
+{ NULL, { 0, 0 } }, //POINTER_NSIZE
+{ NULL, { 0, 0 } }, //POINTER_SSIZE
+{ NULL, { 0, 0 } }, //POINTER_WSIZE
+{ NULL, { 0, 0 } }, //POINTER_ESIZE
+{ "nwsesize", { 15, 15 } }, //POINTER_NWSIZE
+{ "neswsize", { 15, 15 } }, //POINTER_NESIZE
+{ "neswsize", { 15, 15 } }, //POINTER_SWSIZE
+{ "nwsesize", { 15, 15 } }, //POINTER_SESIZE
+{ NULL, { 0, 0 } }, //POINTER_WINDOW_NSIZE
+{ NULL, { 0, 0 } }, //POINTER_WINDOW_SSIZE
+{ NULL, { 0, 0 } }, //POINTER_WINDOW_WSIZE
+{ NULL, { 0, 0 } }, //POINTER_WINDOW_ESIZE
+{ "nwsesize", { 15, 15 } }, //POINTER_WINDOW_NWSIZE
+{ "neswsize", { 15, 15 } }, //POINTER_WINDOW_NESIZE
+{ "neswsize", { 15, 15 } }, //POINTER_WINDOW_SWSIZE
+{ "nwsesize", { 15, 15 } }, //POINTER_WINDOW_SESIZE
+{ NULL, { 0, 0 } }, //POINTER_HSPLIT
+{ NULL, { 0, 0 } }, //POINTER_VSPLIT
+{ NULL, { 0, 0 } }, //POINTER_HSIZEBAR
+{ NULL, { 0, 0 } }, //POINTER_VSIZEBAR
+{ NULL, { 0, 0 } }, //POINTER_HAND
+{ NULL, { 0, 0 } }, //POINTER_REFHAND
+{ "pen", { 3, 27 } }, //POINTER_PEN
+{ "magnify", { 12, 13 } }, //POINTER_MAGNIFY
+{ "fill", { 10, 22 } }, //POINTER_FILL
+{ "rotate", { 15, 15 } }, //POINTER_ROTATE
+{ "hshear", { 15, 15 } }, //POINTER_HSHEAR
+{ "vshear", { 15, 15 } }, //POINTER_VSHEAR
+{ "mirror", { 14, 12 } }, //POINTER_MIRROR
+{ "crook", { 15, 14 } }, //POINTER_CROOK
+{ "crop", { 9, 9 } }, //POINTER_CROP
+{ "movept", { 0, 0 } }, //POINTER_MOVEPOINT
+{ "movebw", { 0, 0 } }, //POINTER_MOVEBEZIERWEIGHT
+{ "movedata", { 0, 0 } }, //POINTER_MOVEDATA
+{ "copydata", { 0, 0 } }, //POINTER_COPYDATA
+{ "linkdata", { 0, 0 } }, //POINTER_LINKDATA
+{ "movedlnk", { 0, 0 } }, //POINTER_MOVEDATALINK
+{ "copydlnk", { 0, 0 } }, //POINTER_COPYDATALINK
+{ "movef", { 8, 8 } }, //POINTER_MOVEFILE
+{ "copyf", { 8, 8 } }, //POINTER_COPYFILE
+{ "linkf", { 8, 8 } }, //POINTER_LINKFILE
+{ "moveflnk", { 8, 8 } }, //POINTER_MOVEFILELINK
+{ "copyflnk", { 8, 8 } }, //POINTER_COPYFILELINK
+{ "movef2", { 7, 8 } }, //POINTER_MOVEFILES
+{ "copyf2", { 7, 8 } }, //POINTER_COPYFILES
+{ "notallow", { 15, 15 } }, //POINTER_NOTALLOWED
+{ "dline", { 8, 8 } }, //POINTER_DRAW_LINE
+{ "drect", { 8, 8 } }, //POINTER_DRAW_RECT
+{ "dpolygon", { 8, 8 } }, //POINTER_DRAW_POLYGON
+{ "dbezier", { 8, 8 } }, //POINTER_DRAW_BEZIER
+{ "darc", { 8, 8 } }, //POINTER_DRAW_ARC
+{ "dpie", { 8, 8 } }, //POINTER_DRAW_PIE
+{ "dcirccut", { 8, 8 } }, //POINTER_DRAW_CIRCLECUT
+{ "dellipse", { 8, 8 } }, //POINTER_DRAW_ELLIPSE
+{ "dfree", { 8, 8 } }, //POINTER_DRAW_FREEHAND
+{ "dconnect", { 8, 8 } }, //POINTER_DRAW_CONNECT
+{ "dtext", { 8, 8 } }, //POINTER_DRAW_TEXT
+{ "dcapt", { 8, 8 } }, //POINTER_DRAW_CAPTION
+{ "chart", { 15, 16 } }, //POINTER_CHART
+{ "detectiv", { 12, 13 } }, //POINTER_DETECTIVE
+{ "pivotcol", { 7, 5 } }, //POINTER_PIVOT_COL
+{ "pivotrow", { 8, 7 } }, //POINTER_PIVOT_ROW
+{ "pivotfld", { 8, 7 } }, //POINTER_PIVOT_FIELD
+{ "chain", { 0, 2 } }, //POINTER_CHAIN
+{ "chainnot", { 2, 2 } }, //POINTER_CHAIN_NOTALLOWED
+{ "timemove", { 16, 16 } }, //POINTER_TIMEEVENT_MOVE
+{ "timesize", { 16, 17 } }, //POINTER_TIMEEVENT_SIZE
+{ "asn", { 16, 12 } }, //POINTER_AUTOSCROLL_N
+{ "ass", { 15, 19 } }, //POINTER_AUTOSCROLL_S
+{ "asw", { 12, 15 } }, //POINTER_AUTOSCROLL_W
+{ "ase", { 19, 16 } }, //POINTER_AUTOSCROLL_E
+{ "asnw", { 10, 10 } }, //POINTER_AUTOSCROLL_NW
+{ "asne", { 21, 10 } }, //POINTER_AUTOSCROLL_NE
+{ "assw", { 21, 21 } }, //POINTER_AUTOSCROLL_SW
+{ "asse", { 21, 21 } }, //POINTER_AUTOSCROLL_SE
+{ "asns", { 15, 15 } }, //POINTER_AUTOSCROLL_NS
+{ "aswe", { 15, 15 } }, //POINTER_AUTOSCROLL_WE
+{ "asnswe", { 15, 15 } }, //POINTER_AUTOSCROLL_NSWE
+{ "airbrush", { 5, 22 } }, //POINTER_AIRBRUSH
+{ "vtext", { 15, 15 } }, //POINTER_TEXT_VERTICAL
+{ "pivotdel", { 18, 15 } }, //POINTER_PIVOT_DELETE
+{ "tblsels", { 15, 30 } }, //POINTER_TAB_SELECT_S
+{ "tblsele", { 30, 16 } }, //POINTER_TAB_SELECT_E
+{ "tblselse", { 30, 30 } }, //POINTER_TAB_SELECT_SE
+{ "tblselw", { 1, 16 } }, //POINTER_TAB_SELECT_W
+{ "tblselsw", { 1, 30 } }, //POINTER_TAB_SELECT_SW
+{ "pntbrsh", { 9, 16 } } //POINTER_PAINTBRUSH
+};
+
+NSCursor* SalData::getCursor( PointerStyle i_eStyle )
+{
+ if( i_eStyle >= POINTER_COUNT )
+ return nil;
+
+ NSCursor* pCurs = maCursors[ i_eStyle ];
+ if( pCurs == INVALID_CURSOR_PTR )
+ {
+ pCurs = nil;
+ if( aCursorTab[ i_eStyle ].pBaseName )
+ {
+ NSPoint aHotSpot = aCursorTab[ i_eStyle ].aHotSpot;
+ CFStringRef pCursorName =
+ CFStringCreateWithCStringNoCopy(
+ kCFAllocatorDefault,
+ aCursorTab[ i_eStyle ].pBaseName,
+ kCFStringEncodingASCII,
+ kCFAllocatorNull );
+ CFBundleRef hMain = CFBundleGetMainBundle();
+ CFURLRef hURL = CFBundleCopyResourceURL( hMain, pCursorName, CFSTR("png"), CFSTR("cursors") );
+ if( hURL )
+ {
+ pCurs = [[NSCursor alloc] initWithImage: [[NSImage alloc] initWithContentsOfURL: (NSURL*)hURL] hotSpot: aHotSpot];
+ CFRelease( hURL );
+ }
+ CFRelease( pCursorName );
+ }
+ maCursors[ i_eStyle ] = pCurs;
+ }
+ return pCurs;
+}
+
+NSStatusItem* SalData::getStatusItem()
+{
+ SalData* pData = GetSalData();
+ if( ! pData->mpStatusItem )
+ {
+ NSStatusBar* pStatBar =[NSStatusBar systemStatusBar];
+ if( pStatBar )
+ {
+ pData->mpStatusItem = [pStatBar statusItemWithLength: NSVariableStatusItemLength];
+ [pData->mpStatusItem retain];
+ OOStatusItemView* pView = [[OOStatusItemView alloc] init];
+ [pData->mpStatusItem setView: pView ];
+ [pView display];
+ }
+ }
+ return pData->mpStatusItem;
+}
diff --git a/vcl/aqua/source/app/salinst.cxx b/vcl/aqua/source/app/salinst.cxx
new file mode 100644
index 000000000000..cce018ac6229
--- /dev/null
+++ b/vcl/aqua/source/app/salinst.cxx
@@ -0,0 +1,1323 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include <stdio.h>
+
+#include "tools/fsys.hxx"
+#include "tools/getprocessworkingdir.hxx"
+#include "osl/process.h"
+#include "rtl/ustrbuf.hxx"
+#include "vcl/svapp.hxx"
+#include "vcl/print.h"
+#include "vcl/salimestatus.hxx"
+#include "vcl/window.hxx"
+#include "vcl/timer.hxx"
+#include "vcl/impbmp.hxx"
+
+#include "saldata.hxx"
+#include "salinst.h"
+#include "salframe.h"
+#include "salobj.h"
+#include "salsys.h"
+#include "salvd.h"
+#include "salbmp.h"
+#include "salprn.h"
+#include "saltimer.h"
+#include "vclnsapp.h"
+
+#include <comphelper/processfactory.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/uri/XExternalUriReferenceTranslator.hpp>
+#include <com/sun/star/uri/ExternalUriReferenceTranslator.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include "premac.h"
+#include <Foundation/Foundation.h>
+#include <ApplicationServices/ApplicationServices.h>
+#import "apple_remote/RemoteMainController.h"
+#include "apple_remote/RemoteControl.h"
+#include "postmac.h"
+#include <tools/solarmutex.hxx>
+
+using namespace std;
+using namespace ::com::sun::star;
+
+extern BOOL ImplSVMain();
+
+static BOOL* gpbInit = 0;
+static NSMenu* pDockMenu = nil;
+static bool bNoSVMain = true;
+static bool bLeftMain = false;
+// -----------------------------------------------------------------------
+
+class AquaDelayedSettingsChanged : public Timer
+{
+ bool mbInvalidate;
+ public:
+ AquaDelayedSettingsChanged( bool bInvalidate ) :
+ mbInvalidate( bInvalidate )
+ {
+ }
+
+ virtual void Timeout()
+ {
+ SalData* pSalData = GetSalData();
+ if( ! pSalData->maFrames.empty() )
+ pSalData->maFrames.front()->CallCallback( SALEVENT_SETTINGSCHANGED, NULL );
+
+ if( mbInvalidate )
+ {
+ for( std::list< AquaSalFrame* >::iterator it = pSalData->maFrames.begin();
+ it != pSalData->maFrames.end(); ++it )
+ {
+ if( (*it)->mbShown )
+ (*it)->SendPaintEvent( NULL );
+ }
+ }
+ Stop();
+ delete this;
+ }
+};
+
+void AquaSalInstance::delayedSettingsChanged( bool bInvalidate )
+{
+ vos::OGuard aGuard( *mpSalYieldMutex );
+ AquaDelayedSettingsChanged* pTimer = new AquaDelayedSettingsChanged( bInvalidate );
+ pTimer->SetTimeout( 50 );
+ pTimer->Start();
+}
+
+
+// the AppEventList must be available before any SalData/SalInst/etc. objects are ready
+typedef std::list<const ApplicationEvent*> AppEventList;
+AppEventList AquaSalInstance::aAppEventList;
+
+NSMenu* AquaSalInstance::GetDynamicDockMenu()
+{
+ if( ! pDockMenu && ! bLeftMain )
+ pDockMenu = [[NSMenu alloc] initWithTitle: @""];
+ return pDockMenu;
+}
+
+bool AquaSalInstance::isOnCommandLine( const rtl::OUString& rArg )
+{
+ sal_uInt32 nArgs = osl_getCommandArgCount();
+ for( sal_uInt32 i = 0; i < nArgs; i++ )
+ {
+ rtl::OUString aArg;
+ osl_getCommandArg( i, &aArg.pData );
+ if( aArg.equals( rArg ) )
+ return true;
+ }
+ return false;
+}
+
+
+// initialize the cocoa VCL_NSApplication object
+// returns an NSAutoreleasePool that must be released when the event loop begins
+static void initNSApp()
+{
+ // create our cocoa NSApplication
+ [VCL_NSApplication sharedApplication];
+
+ SalData::ensureThreadAutoreleasePool();
+
+ // put cocoa into multithreaded mode
+ [NSThread detachNewThreadSelector:@selector(enableCocoaThreads:) toTarget:[[CocoaThreadEnabler alloc] init] withObject:nil];
+
+ // activate our delegate methods
+ [NSApp setDelegate: NSApp];
+
+ [[NSNotificationCenter defaultCenter] addObserver: NSApp
+ selector: @selector(systemColorsChanged:)
+ name: NSSystemColorsDidChangeNotification
+ object: nil ];
+ [[NSNotificationCenter defaultCenter] addObserver: NSApp
+ selector: @selector(screenParametersChanged:)
+ name: NSApplicationDidChangeScreenParametersNotification
+ object: nil ];
+ // add observers for some settings changes that affect vcl's settings
+ // scrollbar variant
+ [[NSDistributedNotificationCenter defaultCenter] addObserver: NSApp
+ selector: @selector(scrollbarVariantChanged:)
+ name: @"AppleAquaScrollBarVariantChanged"
+ object: nil ];
+ // scrollbar page behavior ("jump to here" or not)
+ [[NSDistributedNotificationCenter defaultCenter] addObserver: NSApp
+ selector: @selector(scrollbarSettingsChanged:)
+ name: @"AppleNoRedisplayAppearancePreferenceChanged"
+ object: nil ];
+
+ // get System Version and store the value in GetSalData()->mnSystemVersion
+ OSErr err = noErr;
+ SInt32 systemVersion = VER_TIGER; // Initialize with minimal requirement
+ if( (err = Gestalt(gestaltSystemVersion, &systemVersion)) == noErr )
+ {
+ GetSalData()->mnSystemVersion = systemVersion;
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "System Version %x\n", (unsigned int)systemVersion);
+#endif
+ }
+ else
+ NSLog(@"Unable to obtain system version: %ld", (long)err);
+
+ // Initialize Apple Remote
+ GetSalData()->mpMainController = [[MainController alloc] init];
+
+ [[NSDistributedNotificationCenter defaultCenter] addObserver: NSApp
+ selector: @selector(applicationWillBecomeActive:)
+ name: @"AppleRemoteWillBecomeActive"
+ object: nil ];
+
+ [[NSDistributedNotificationCenter defaultCenter] addObserver: NSApp
+ selector: @selector(applicationWillResignActive:)
+ name: @"AppleRemoteWillResignActive"
+ object: nil ];
+
+ if( ImplGetSVData()->mbIsTestTool )
+ [NSApp activateIgnoringOtherApps: YES];
+}
+
+BOOL ImplSVMainHook( BOOL * pbInit )
+{
+ gpbInit = pbInit;
+
+ bNoSVMain = false;
+ initNSApp();
+
+ NSPoint aPt = { 0, 0 };
+ NSEvent* pEvent = [NSEvent otherEventWithType: NSApplicationDefined
+ location: aPt
+ modifierFlags: 0
+ timestamp: 0
+ windowNumber: 0
+ context: nil
+ subtype: AquaSalInstance::AppExecuteSVMain
+ data1: 0
+ data2: 0 ];
+ if( pEvent )
+ {
+ [NSApp postEvent: pEvent atStart: NO];
+
+ rtl::OUString aExeURL, aExe;
+ osl_getExecutableFile( &aExeURL.pData );
+ osl_getSystemPathFromFileURL( aExeURL.pData, &aExe.pData );
+ rtl::OString aByteExe( rtl::OUStringToOString( aExe, osl_getThreadTextEncoding() ) );
+
+#ifdef DEBUG
+ aByteExe += OString ( " NSAccessibilityDebugLogLevel 1" );
+ const char* pArgv[] = { aByteExe.getStr(), NULL };
+ NSApplicationMain( 3, pArgv );
+#else
+ const char* pArgv[] = { aByteExe.getStr(), NULL };
+ NSApplicationMain( 1, pArgv );
+#endif
+ }
+ else
+ {
+ DBG_ERROR( "NSApplication initialization could not be done" );
+ }
+
+ return TRUE; // indicate that ImplSVMainHook is implemented
+}
+
+// =======================================================================
+
+void SalAbort( const XubString& rErrorText )
+{
+ if( !rErrorText.Len() )
+ fprintf( stderr, "Application Error " );
+ else
+ fprintf( stderr, "%s ",
+ ByteString( rErrorText, gsl_getSystemTextEncoding() ).GetBuffer() );
+ abort();
+}
+
+// -----------------------------------------------------------------------
+
+void InitSalData()
+{
+ SalData *pSalData = new SalData;
+ SetSalData( pSalData );
+}
+
+// -----------------------------------------------------------------------
+
+const ::rtl::OUString& SalGetDesktopEnvironment()
+{
+ static OUString aDesktopEnvironment(RTL_CONSTASCII_USTRINGPARAM( "MacOSX" ));
+ return aDesktopEnvironment;
+}
+
+// -----------------------------------------------------------------------
+
+void DeInitSalData()
+{
+ SalData *pSalData = GetSalData();
+ if( pSalData->mpStatusItem )
+ {
+ [pSalData->mpStatusItem release];
+ pSalData->mpStatusItem = nil;
+ }
+ delete pSalData;
+ SetSalData( NULL );
+}
+
+// -----------------------------------------------------------------------
+
+extern "C" {
+#include <crt_externs.h>
+}
+
+// -----------------------------------------------------------------------
+
+void InitSalMain()
+{
+ rtl::OUString urlWorkDir;
+ rtl_uString *sysWorkDir = NULL;
+ if (tools::getProcessWorkingDir(&urlWorkDir))
+ {
+ oslFileError err2 = osl_getSystemPathFromFileURL(urlWorkDir.pData, &sysWorkDir);
+ if (err2 == osl_File_E_None)
+ {
+ ByteString aPath( getenv( "PATH" ) );
+ ByteString aResPath( getenv( "STAR_RESOURCEPATH" ) );
+ ByteString aLibPath( getenv( "DYLD_LIBRARY_PATH" ) );
+ ByteString aCmdPath( OUStringToOString(OUString(sysWorkDir), RTL_TEXTENCODING_UTF8).getStr() );
+ ByteString aTmpPath;
+ // Get absolute path of command's directory
+ if ( aCmdPath.Len() ) {
+ DirEntry aCmdDirEntry( aCmdPath );
+ aCmdDirEntry.ToAbs();
+ aCmdPath = ByteString( aCmdDirEntry.GetPath().GetFull(), RTL_TEXTENCODING_ASCII_US );
+ }
+ // Assign to PATH environment variable
+ if ( aCmdPath.Len() )
+ {
+ aTmpPath = ByteString( "PATH=" );
+ aTmpPath += aCmdPath;
+ if ( aPath.Len() )
+ aTmpPath += ByteString( DirEntry::GetSearchDelimiter(), RTL_TEXTENCODING_ASCII_US );
+ aTmpPath += aPath;
+ putenv( (char*)aTmpPath.GetBuffer() );
+ }
+ // Assign to STAR_RESOURCEPATH environment variable
+ if ( aCmdPath.Len() )
+ {
+ aTmpPath = ByteString( "STAR_RESOURCEPATH=" );
+ aTmpPath += aCmdPath;
+ if ( aResPath.Len() )
+ aTmpPath += ByteString( DirEntry::GetSearchDelimiter(), RTL_TEXTENCODING_ASCII_US );
+ aTmpPath += aResPath;
+ putenv( (char*)aTmpPath.GetBuffer() );
+ }
+ // Assign to DYLD_LIBRARY_PATH environment variable
+ if ( aCmdPath.Len() )
+ {
+ aTmpPath = ByteString( "DYLD_LIBRARY_PATH=" );
+ aTmpPath += aCmdPath;
+ if ( aLibPath.Len() )
+ aTmpPath += ByteString( DirEntry::GetSearchDelimiter(), RTL_TEXTENCODING_ASCII_US );
+ aTmpPath += aLibPath;
+ putenv( (char*)aTmpPath.GetBuffer() );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DeInitSalMain()
+{
+}
+
+// =======================================================================
+
+SalYieldMutex::SalYieldMutex()
+{
+ mnCount = 0;
+ mnThreadId = 0;
+}
+
+void SalYieldMutex::acquire()
+{
+ OMutex::acquire();
+ mnThreadId = vos::OThread::getCurrentIdentifier();
+ mnCount++;
+}
+
+void SalYieldMutex::release()
+{
+ if ( mnThreadId == vos::OThread::getCurrentIdentifier() )
+ {
+ if ( mnCount == 1 )
+ mnThreadId = 0;
+ mnCount--;
+ }
+ OMutex::release();
+}
+
+sal_Bool SalYieldMutex::tryToAcquire()
+{
+ if ( OMutex::tryToAcquire() )
+ {
+ mnThreadId = vos::OThread::getCurrentIdentifier();
+ mnCount++;
+ return sal_True;
+ }
+ else
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+// some convenience functions regarding the yield mutex, aka solar mutex
+
+BOOL ImplSalYieldMutexTryToAcquire()
+{
+ AquaSalInstance* pInst = (AquaSalInstance*) GetSalData()->mpFirstInstance;
+ if ( pInst )
+ return pInst->mpSalYieldMutex->tryToAcquire();
+ else
+ return FALSE;
+}
+
+void ImplSalYieldMutexAcquire()
+{
+ AquaSalInstance* pInst = (AquaSalInstance*) GetSalData()->mpFirstInstance;
+ if ( pInst )
+ pInst->mpSalYieldMutex->acquire();
+}
+
+void ImplSalYieldMutexRelease()
+{
+ AquaSalInstance* pInst = (AquaSalInstance*) GetSalData()->mpFirstInstance;
+ if ( pInst )
+ pInst->mpSalYieldMutex->release();
+}
+
+// =======================================================================
+
+SalInstance* CreateSalInstance()
+{
+ // this is the case for not using SVMain
+ // not so good
+ if( bNoSVMain )
+ initNSApp();
+
+ SalData* pSalData = GetSalData();
+ DBG_ASSERT( pSalData->mpFirstInstance == NULL, "more than one instance created" );
+ AquaSalInstance* pInst = new AquaSalInstance;
+
+ // init instance (only one instance in this version !!!)
+ pSalData->mpFirstInstance = pInst;
+ // this one is for outside AquaSalInstance::Yield
+ SalData::ensureThreadAutoreleasePool();
+ // no focus rects on NWF aqua
+ ImplGetSVData()->maNWFData.mbNoFocusRects = true;
+ ImplGetSVData()->maNWFData.mbNoBoldTabFocus = true;
+ ImplGetSVData()->maNWFData.mbNoActiveTabTextRaise = true;
+ ImplGetSVData()->maNWFData.mbCenteredTabs = true;
+ ImplGetSVData()->maNWFData.mbProgressNeedsErase = true;
+ ImplGetSVData()->maNWFData.mbCheckBoxNeedsErase = true;
+ ImplGetSVData()->maNWFData.mnStatusBarLowerRightOffset = 10;
+ ImplGetSVData()->maGDIData.mbPrinterPullModel = true;
+ ImplGetSVData()->maGDIData.mbNoXORClipping = true;
+ ImplGetSVData()->maWinData.mbNoSaveBackground = true;
+
+ return pInst;
+}
+
+// -----------------------------------------------------------------------
+
+void DestroySalInstance( SalInstance* pInst )
+{
+ delete pInst;
+}
+
+// -----------------------------------------------------------------------
+
+AquaSalInstance::AquaSalInstance()
+{
+ mpSalYieldMutex = new SalYieldMutex;
+ mpSalYieldMutex->acquire();
+ ::tools::SolarMutex::SetSolarMutex( mpSalYieldMutex );
+ maMainThread = vos::OThread::getCurrentIdentifier();
+ mbWaitingYield = false;
+ maUserEventListMutex = osl_createMutex();
+ mnActivePrintJobs = 0;
+ maWaitingYieldCond = osl_createCondition();
+}
+
+// -----------------------------------------------------------------------
+
+AquaSalInstance::~AquaSalInstance()
+{
+ ::tools::SolarMutex::SetSolarMutex( 0 );
+ mpSalYieldMutex->release();
+ delete mpSalYieldMutex;
+ osl_destroyMutex( maUserEventListMutex );
+ osl_destroyCondition( maWaitingYieldCond );
+}
+
+// -----------------------------------------------------------------------
+
+void AquaSalInstance::wakeupYield()
+{
+ // wakeup :Yield
+ if( mbWaitingYield )
+ {
+ SalData::ensureThreadAutoreleasePool();
+ NSPoint aPt = { 0, 0 };
+ NSEvent* pEvent = [NSEvent otherEventWithType: NSApplicationDefined
+ location: aPt
+ modifierFlags: 0
+ timestamp: 0
+ windowNumber: 0
+ context: nil
+ subtype: AquaSalInstance::YieldWakeupEvent
+ data1: 0
+ data2: 0 ];
+ if( pEvent )
+ [NSApp postEvent: pEvent atStart: NO];
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void AquaSalInstance::PostUserEvent( AquaSalFrame* pFrame, USHORT nType, void* pData )
+{
+ osl_acquireMutex( maUserEventListMutex );
+ maUserEvents.push_back( SalUserEvent( pFrame, pData, nType ) );
+ osl_releaseMutex( maUserEventListMutex );
+
+ // notify main loop that an event has arrived
+ wakeupYield();
+}
+
+// -----------------------------------------------------------------------
+
+vos::IMutex* AquaSalInstance::GetYieldMutex()
+{
+ return mpSalYieldMutex;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG AquaSalInstance::ReleaseYieldMutex()
+{
+ SalYieldMutex* pYieldMutex = mpSalYieldMutex;
+ if ( pYieldMutex->GetThreadId() ==
+ vos::OThread::getCurrentIdentifier() )
+ {
+ ULONG nCount = pYieldMutex->GetAcquireCount();
+ ULONG n = nCount;
+ while ( n )
+ {
+ pYieldMutex->release();
+ n--;
+ }
+
+ return nCount;
+ }
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void AquaSalInstance::AcquireYieldMutex( ULONG nCount )
+{
+ SalYieldMutex* pYieldMutex = mpSalYieldMutex;
+ while ( nCount )
+ {
+ pYieldMutex->acquire();
+ nCount--;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+bool AquaSalInstance::isNSAppThread() const
+{
+ return vos::OThread::getCurrentIdentifier() == maMainThread;
+}
+
+// -----------------------------------------------------------------------
+
+void AquaSalInstance::handleAppDefinedEvent( NSEvent* pEvent )
+{
+ switch( [pEvent subtype] )
+ {
+ case AppStartTimerEvent:
+ AquaSalTimer::handleStartTimerEvent( pEvent );
+ break;
+ case AppEndLoopEvent:
+ [NSApp stop: NSApp];
+ break;
+ case AppExecuteSVMain:
+ {
+ BOOL bResult = ImplSVMain();
+ if( gpbInit )
+ *gpbInit = bResult;
+ [NSApp stop: NSApp];
+ bLeftMain = true;
+ if( pDockMenu )
+ {
+ [pDockMenu release];
+ pDockMenu = nil;
+ }
+ }
+ break;
+ case AppleRemoteEvent:
+ {
+ sal_Int16 nCommand = 0;
+ SalData* pSalData = GetSalData();
+ bool bIsFullScreenMode = false;
+
+ std::list<AquaSalFrame*>::iterator it = pSalData->maFrames.begin();
+ while( (*it) && ( (it != pSalData->maFrames.end() ) || ( (*it)->mbFullScreen == false ) ) )
+ {
+ if ( ((*it)->mbFullScreen == true) )
+ bIsFullScreenMode = true;
+ it++;
+ }
+
+ switch ([pEvent data1])
+ {
+ case kRemoteButtonPlay:
+ nCommand = ( bIsFullScreenMode == true ) ? MEDIA_COMMAND_PLAY_PAUSE : MEDIA_COMMAND_PLAY;
+ break;
+
+ // kept for experimentation purpose (scheduled for future implementation)
+ // case kRemoteButtonMenu: nCommand = MEDIA_COMMAND_MENU; break;
+
+ case kRemoteButtonPlus: nCommand = MEDIA_COMMAND_VOLUME_UP; break;
+
+ case kRemoteButtonMinus: nCommand = MEDIA_COMMAND_VOLUME_DOWN; break;
+
+ case kRemoteButtonRight: nCommand = MEDIA_COMMAND_NEXTTRACK; break;
+
+ case kRemoteButtonRight_Hold: nCommand = MEDIA_COMMAND_NEXTTRACK_HOLD; break;
+
+ case kRemoteButtonLeft: nCommand = MEDIA_COMMAND_PREVIOUSTRACK; break;
+
+ case kRemoteButtonLeft_Hold: nCommand = MEDIA_COMMAND_REWIND; break;
+
+ case kRemoteButtonPlay_Hold: nCommand = MEDIA_COMMAND_PLAY_HOLD; break;
+
+ case kRemoteButtonMenu_Hold: nCommand = MEDIA_COMMAND_STOP; break;
+
+ // FIXME : not detected
+ case kRemoteButtonPlus_Hold:
+ case kRemoteButtonMinus_Hold:
+ break;
+
+ default:
+ break;
+ }
+ AquaSalFrame* pFrame = pSalData->maFrames.front();
+ Window * pWindow = pFrame->GetWindow() ? pSalData->maFrames.front()->GetWindow() : NULL;
+
+ if( pWindow )
+ {
+ const Point aPoint;
+ CommandEvent aCEvt( aPoint, COMMAND_MEDIA, FALSE, &nCommand );
+ NotifyEvent aNCmdEvt( EVENT_COMMAND, pWindow, &aCEvt );
+
+ if ( !ImplCallPreNotify( aNCmdEvt ) )
+ pWindow->Command( aCEvt );
+ }
+
+ }
+ break;
+
+ case YieldWakeupEvent:
+ // do nothing, fall out of Yield
+ break;
+
+ default:
+ DBG_ERROR( "unhandled NSApplicationDefined event" );
+ break;
+ };
+}
+
+// -----------------------------------------------------------------------
+
+class ReleasePoolHolder
+{
+ NSAutoreleasePool* mpPool;
+ public:
+ ReleasePoolHolder() : mpPool( [[NSAutoreleasePool alloc] init] ) {}
+ ~ReleasePoolHolder() { [mpPool release]; }
+};
+
+void AquaSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
+{
+ // ensure that the per thread autorelease pool is top level and
+ // will therefore not be destroyed by cocoa implicitly
+ SalData::ensureThreadAutoreleasePool();
+
+ // NSAutoreleasePool documentation suggests we should have
+ // an own pool for each yield level
+ ReleasePoolHolder aReleasePool;
+
+ // Release all locks so that we don't deadlock when we pull pending
+ // events from the event queue
+ bool bDispatchUser = true;
+ while( bDispatchUser )
+ {
+ ULONG nCount = ReleaseYieldMutex();
+
+ // get one user event
+ osl_acquireMutex( maUserEventListMutex );
+ SalUserEvent aEvent( NULL, NULL, 0 );
+ if( ! maUserEvents.empty() )
+ {
+ aEvent = maUserEvents.front();
+ maUserEvents.pop_front();
+ }
+ else
+ bDispatchUser = false;
+ osl_releaseMutex( maUserEventListMutex );
+
+ AcquireYieldMutex( nCount );
+
+ // dispatch it
+ if( aEvent.mpFrame && AquaSalFrame::isAlive( aEvent.mpFrame ) )
+ {
+ aEvent.mpFrame->CallCallback( aEvent.mnType, aEvent.mpData );
+ osl_setCondition( maWaitingYieldCond );
+ // return if only one event is asked for
+ if( ! bHandleAllCurrentEvents )
+ return;
+ }
+ }
+
+ // handle cocoa event queue
+ // cocoa events mye be only handled in the thread the NSApp was created
+ if( isNSAppThread() && mnActivePrintJobs == 0 )
+ {
+ // we need to be woken up by a cocoa-event
+ // if a user event should be posted by the event handling below
+ bool bOldWaitingYield = mbWaitingYield;
+ mbWaitingYield = bWait;
+
+ // handle available events
+ NSEvent* pEvent = nil;
+ bool bHadEvent = false;
+ do
+ {
+ ULONG nCount = ReleaseYieldMutex();
+
+ pEvent = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: nil
+ inMode: NSDefaultRunLoopMode dequeue: YES];
+ if( pEvent )
+ {
+ [NSApp sendEvent: pEvent];
+ bHadEvent = true;
+ }
+ [NSApp updateWindows];
+
+ AcquireYieldMutex( nCount );
+ } while( bHandleAllCurrentEvents && pEvent );
+
+ // if we had no event yet, wait for one if requested
+ if( bWait && ! bHadEvent )
+ {
+ ULONG nCount = ReleaseYieldMutex();
+
+ NSDate* pDt = AquaSalTimer::pRunningTimer ? [AquaSalTimer::pRunningTimer fireDate] : [NSDate distantFuture];
+ pEvent = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: pDt
+ inMode: NSDefaultRunLoopMode dequeue: YES];
+ if( pEvent )
+ [NSApp sendEvent: pEvent];
+ [NSApp updateWindows];
+
+ AcquireYieldMutex( nCount );
+
+ // #i86581#
+ // FIXME: sometimes the NSTimer will never fire. Firing it by hand then
+ // fixes the problem even seems to set the correct next firing date
+ // Why oh why ?
+ if( ! pEvent && AquaSalTimer::pRunningTimer )
+ {
+ // this cause crashes on MacOSX 10.4
+ // [AquaSalTimer::pRunningTimer fire];
+ ImplGetSVData()->mpSalTimer->CallCallback();
+ }
+ }
+
+ mbWaitingYield = bOldWaitingYield;
+
+ // collect update rectangles
+ const std::list< AquaSalFrame* > rFrames( GetSalData()->maFrames );
+ for( std::list< AquaSalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
+ {
+ if( (*it)->mbShown && ! (*it)->maInvalidRect.IsEmpty() )
+ {
+ (*it)->Flush( (*it)->maInvalidRect );
+ (*it)->maInvalidRect.SetEmpty();
+ }
+ }
+ osl_setCondition( maWaitingYieldCond );
+ }
+ else if( bWait )
+ {
+ // #i103162#
+ // wait until any thread (most likely the main thread)
+ // has dispatched an event, cop out at 200 ms
+ osl_resetCondition( maWaitingYieldCond );
+ TimeValue aVal = { 0, 200000000 };
+ ULONG nCount = ReleaseYieldMutex();
+ osl_waitCondition( maWaitingYieldCond, &aVal );
+ AcquireYieldMutex( nCount );
+ }
+
+ // we get some apple events way too early
+ // before the application is ready to handle them,
+ // so their corresponding application events need to be delayed
+ // now is a good time to handle at least one of them
+ if( bWait && !aAppEventList.empty() && ImplGetSVData()->maAppData.mbInAppExecute )
+ {
+ // make sure that only one application event is active at a time
+ static bool bInAppEvent = false;
+ if( !bInAppEvent )
+ {
+ bInAppEvent = true;
+ // get the next delayed application event
+ const ApplicationEvent* pAppEvent = aAppEventList.front();
+ aAppEventList.pop_front();
+ // handle one application event (no recursion)
+ const ImplSVData* pSVData = ImplGetSVData();
+ pSVData->mpApp->AppEvent( *pAppEvent );
+ delete pAppEvent;
+ // allow the next delayed application event
+ bInAppEvent = false;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+bool AquaSalInstance::AnyInput( USHORT nType )
+{
+ if( nType & INPUT_APPEVENT )
+ {
+ if( ! aAppEventList.empty() )
+ return true;
+ if( nType == INPUT_APPEVENT )
+ 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 |=
+ NSLeftMouseDownMask | NSRightMouseDownMask | NSOtherMouseDownMask |
+ NSLeftMouseUpMask | NSRightMouseUpMask | NSOtherMouseUpMask |
+ NSLeftMouseDraggedMask | NSRightMouseDraggedMask | NSOtherMouseDraggedMask |
+ NSScrollWheelMask |
+ // NSMouseMovedMask |
+ NSMouseEnteredMask | NSMouseExitedMask;
+ if( nType & INPUT_KEYBOARD)
+ nEventMask |= NSKeyDownMask | NSKeyUpMask | NSFlagsChangedMask;
+ if( nType & INPUT_OTHER)
+ nEventMask |= NSTabletPoint;
+ // TODO: INPUT_PAINT / more INPUT_OTHER
+ if( !nType)
+ return false;
+
+ NSEvent* pEvent = [NSApp nextEventMatchingMask: nEventMask untilDate: nil
+ inMode: NSDefaultRunLoopMode dequeue: NO];
+ return (pEvent != NULL);
+}
+
+// -----------------------------------------------------------------------
+
+SalFrame* AquaSalInstance::CreateChildFrame( SystemParentData* pSystemParentData, ULONG nSalFrameStyle )
+{
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+SalFrame* AquaSalInstance::CreateFrame( SalFrame* pParent, ULONG nSalFrameStyle )
+{
+ SalData::ensureThreadAutoreleasePool();
+
+ SalFrame* pFrame = new AquaSalFrame( pParent, nSalFrameStyle );
+ return pFrame;
+}
+
+// -----------------------------------------------------------------------
+
+void AquaSalInstance::DestroyFrame( SalFrame* pFrame )
+{
+ delete pFrame;
+}
+
+// -----------------------------------------------------------------------
+
+SalObject* AquaSalInstance::CreateObject( SalFrame* pParent, SystemWindowData* /* pWindowData */, BOOL /* bShow */ )
+{
+ // SystemWindowData is meaningless on Mac OS X
+ AquaSalObject *pObject = NULL;
+
+ if ( pParent )
+ pObject = new AquaSalObject( static_cast<AquaSalFrame*>(pParent) );
+
+ return pObject;
+}
+
+// -----------------------------------------------------------------------
+
+void AquaSalInstance::DestroyObject( SalObject* pObject )
+{
+ delete ( pObject );
+}
+
+// -----------------------------------------------------------------------
+
+SalPrinter* AquaSalInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter )
+{
+ return new AquaSalPrinter( dynamic_cast<AquaSalInfoPrinter*>(pInfoPrinter) );
+}
+
+// -----------------------------------------------------------------------
+
+void AquaSalInstance::DestroyPrinter( SalPrinter* pPrinter )
+{
+ delete pPrinter;
+}
+
+// -----------------------------------------------------------------------
+
+void AquaSalInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList )
+{
+ NSArray* pNames = [NSPrinter printerNames];
+ NSArray* pTypes = [NSPrinter printerTypes];
+ unsigned int nNameCount = pNames ? [pNames count] : 0;
+ unsigned int nTypeCount = pTypes ? [pTypes count] : 0;
+ DBG_ASSERT( nTypeCount == nNameCount, "type count not equal to printer count" );
+ for( unsigned int i = 0; i < nNameCount; i++ )
+ {
+ NSString* pName = [pNames objectAtIndex: i];
+ NSString* pType = i < nTypeCount ? [pTypes objectAtIndex: i] : nil;
+ if( pName )
+ {
+ SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
+ pInfo->maPrinterName = GetOUString( pName );
+ if( pType )
+ pInfo->maDriver = GetOUString( pType );
+ pInfo->mnStatus = 0;
+ pInfo->mnJobs = 0;
+ pInfo->mpSysData = NULL;
+
+ pList->Add( pInfo );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void AquaSalInstance::GetPrinterQueueState( SalPrinterQueueInfo* pInfo )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void AquaSalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo )
+{
+ delete pInfo;
+}
+
+// -----------------------------------------------------------------------
+
+XubString AquaSalInstance::GetDefaultPrinter()
+{
+ // #i113170# may not be the main thread if called from UNO API
+ SalData::ensureThreadAutoreleasePool();
+
+ if( ! maDefaultPrinter.getLength() )
+ {
+ NSPrintInfo* pPI = [NSPrintInfo sharedPrintInfo];
+ DBG_ASSERT( pPI, "no print info" );
+ if( pPI )
+ {
+ NSPrinter* pPr = [pPI printer];
+ DBG_ASSERT( pPr, "no printer in default info" );
+ if( pPr )
+ {
+ NSString* pDefName = [pPr name];
+ DBG_ASSERT( pDefName, "printer has no name" );
+ maDefaultPrinter = GetOUString( pDefName );
+ }
+ }
+ }
+ return maDefaultPrinter;
+}
+
+// -----------------------------------------------------------------------
+
+SalInfoPrinter* AquaSalInstance::CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo,
+ ImplJobSetup* pSetupData )
+{
+ // #i113170# may not be the main thread if called from UNO API
+ SalData::ensureThreadAutoreleasePool();
+
+ SalInfoPrinter* pNewInfoPrinter = NULL;
+ if( pQueueInfo )
+ {
+ pNewInfoPrinter = new AquaSalInfoPrinter( *pQueueInfo );
+ if( pSetupData )
+ pNewInfoPrinter->SetPrinterData( pSetupData );
+ }
+
+ return pNewInfoPrinter;
+}
+
+// -----------------------------------------------------------------------
+
+void AquaSalInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter )
+{
+ // #i113170# may not be the main thread if called from UNO API
+ SalData::ensureThreadAutoreleasePool();
+
+ delete pPrinter;
+}
+
+// -----------------------------------------------------------------------
+
+SalSystem* AquaSalInstance::CreateSystem()
+{
+ return new AquaSalSystem();
+}
+
+// -----------------------------------------------------------------------
+
+void AquaSalInstance::DestroySystem( SalSystem* pSystem )
+{
+ delete pSystem;
+}
+
+// -----------------------------------------------------------------------
+
+void AquaSalInstance::SetEventCallback( void* pInstance, bool(*pCallback)(void*,void*,int) )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void AquaSalInstance::SetErrorEventCallback( void* pInstance, bool(*pCallback)(void*,void*,int) )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void* AquaSalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes )
+{
+ rReturnedBytes = 1;
+ rReturnedType = AsciiCString;
+ return (void*)"";
+}
+
+// We need to re-encode file urls because osl_getFileURLFromSystemPath converts
+// to UTF-8 before encoding non ascii characters, which is not what other apps expect.
+static rtl::OUString translateToExternalUrl(const rtl::OUString& internalUrl)
+{
+ rtl::OUString extUrl;
+
+ uno::Reference< lang::XMultiServiceFactory > sm = comphelper::getProcessServiceFactory();
+ if (sm.is())
+ {
+ uno::Reference< beans::XPropertySet > pset;
+ sm->queryInterface( getCppuType( &pset )) >>= pset;
+ if (pset.is())
+ {
+ uno::Reference< uno::XComponentContext > context;
+ static const rtl::OUString DEFAULT_CONTEXT( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) );
+ pset->getPropertyValue(DEFAULT_CONTEXT) >>= context;
+ if (context.is())
+ extUrl = uri::ExternalUriReferenceTranslator::create(context)->translateToExternal(internalUrl);
+ }
+ }
+ return extUrl;
+}
+
+// #i104525# many versions of OSX have problems with some URLs:
+// when an app requests OSX to add one of these URLs to the "Recent Items" list
+// then this app gets killed (TextEdit, Preview, etc. and also OOo)
+static bool isDangerousUrl( const rtl::OUString& rUrl )
+{
+ // use a heuristic that detects all known cases since there is no official comment
+ // on the exact impact and root cause of the OSX bug
+ const int nLen = rUrl.getLength();
+ const sal_Unicode* p = rUrl.getStr();
+ for( int i = 0; i < nLen-3; ++i, ++p ) {
+ if( p[0] != '%' )
+ continue;
+ // escaped percent?
+ if( (p[1] == '2') && (p[2] == '5') )
+ return true;
+ // escapes are considered to be UTF-8 encoded
+ // => check for invalid UTF-8 leading byte
+ if( (p[1] != 'f') && (p[1] != 'F') )
+ continue;
+ int cLowNibble = p[2];
+ if( (cLowNibble >= '0' ) && (cLowNibble <= '9'))
+ return false;
+ if( cLowNibble >= 'a' )
+ cLowNibble -= 'a' - 'A';
+ if( (cLowNibble < 'A') || (cLowNibble >= 'C'))
+ return true;
+ }
+
+ return false;
+}
+
+void AquaSalInstance::AddToRecentDocumentList(const rtl::OUString& rFileUrl, const rtl::OUString& /*rMimeType*/)
+{
+ // Convert file URL for external use (see above)
+ rtl::OUString externalUrl = translateToExternalUrl(rFileUrl);
+ if( 0 == externalUrl.getLength() )
+ externalUrl = rFileUrl;
+
+ if( externalUrl.getLength() && !isDangerousUrl( externalUrl ) )
+ {
+ NSString* pString = CreateNSString( externalUrl );
+ NSURL* pURL = [NSURL URLWithString: pString];
+
+ if( pURL )
+ {
+ NSDocumentController* pCtrl = [NSDocumentController sharedDocumentController];
+ [pCtrl noteNewRecentDocumentURL: pURL];
+ }
+ if( pString )
+ [pString release];
+ }
+}
+
+
+// -----------------------------------------------------------------------
+
+SalTimer* AquaSalInstance::CreateSalTimer()
+{
+ return new AquaSalTimer();
+}
+
+// -----------------------------------------------------------------------
+
+SalSystem* AquaSalInstance::CreateSalSystem()
+{
+ return new AquaSalSystem();
+}
+
+// -----------------------------------------------------------------------
+
+SalBitmap* AquaSalInstance::CreateSalBitmap()
+{
+ return new AquaSalBitmap();
+}
+
+// -----------------------------------------------------------------------
+
+SalSession* AquaSalInstance::CreateSalSession()
+{
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+class MacImeStatus : public SalI18NImeStatus
+{
+public:
+ MacImeStatus() {}
+ virtual ~MacImeStatus() {}
+
+ // asks whether there is a status window available
+ // to toggle into menubar
+ virtual bool canToggle() { return false; }
+ virtual void toggle() {}
+};
+
+// -----------------------------------------------------------------------
+
+SalI18NImeStatus* AquaSalInstance::CreateI18NImeStatus()
+{
+ return new MacImeStatus();
+}
+
+// YieldMutexReleaser
+YieldMutexReleaser::YieldMutexReleaser() : mnCount( 0 )
+{
+ SalData* pSalData = GetSalData();
+ if( ! pSalData->mpFirstInstance->isNSAppThread() )
+ {
+ SalData::ensureThreadAutoreleasePool();
+ mnCount = pSalData->mpFirstInstance->ReleaseYieldMutex();
+ }
+}
+
+YieldMutexReleaser::~YieldMutexReleaser()
+{
+ if( mnCount != 0 )
+ GetSalData()->mpFirstInstance->AcquireYieldMutex( mnCount );
+}
+
+//////////////////////////////////////////////////////////////
+rtl::OUString GetOUString( CFStringRef rStr )
+{
+ if( rStr == 0 )
+ return rtl::OUString();
+ CFIndex nLength = CFStringGetLength( rStr );
+ if( nLength == 0 )
+ return rtl::OUString();
+ const UniChar* pConstStr = CFStringGetCharactersPtr( rStr );
+ if( pConstStr )
+ return rtl::OUString( pConstStr, nLength );
+ UniChar* pStr = reinterpret_cast<UniChar*>( rtl_allocateMemory( sizeof(UniChar)*nLength ) );
+ CFRange aRange = { 0, nLength };
+ CFStringGetCharacters( rStr, aRange, pStr );
+ rtl::OUString aRet( pStr, nLength );
+ rtl_freeMemory( pStr );
+ return aRet;
+}
+
+rtl::OUString GetOUString( NSString* pStr )
+{
+ if( ! pStr )
+ return rtl::OUString();
+ int nLen = [pStr length];
+ if( nLen == 0 )
+ return rtl::OUString();
+
+ rtl::OUStringBuffer aBuf( nLen+1 );
+ aBuf.setLength( nLen );
+ [pStr getCharacters: const_cast<sal_Unicode*>(aBuf.getStr())];
+ return aBuf.makeStringAndClear();
+}
+
+CFStringRef CreateCFString( const rtl::OUString& rStr )
+{
+ return CFStringCreateWithCharacters(kCFAllocatorDefault, rStr.getStr(), rStr.getLength() );
+}
+
+NSString* CreateNSString( const rtl::OUString& rStr )
+{
+ return [[NSString alloc] initWithCharacters: rStr.getStr() length: rStr.getLength()];
+}
+
+CGImageRef CreateCGImage( const Image& rImage )
+{
+ BitmapEx aBmpEx( rImage.GetBitmapEx() );
+ Bitmap aBmp( aBmpEx.GetBitmap() );
+
+ if( ! aBmp || ! aBmp.ImplGetImpBitmap() )
+ return NULL;
+
+ // simple case, no transparency
+ AquaSalBitmap* pSalBmp = static_cast<AquaSalBitmap*>(aBmp.ImplGetImpBitmap()->ImplGetSalBitmap());
+
+ if( ! pSalBmp )
+ return NULL;
+
+ CGImageRef xImage = NULL;
+ if( ! (aBmpEx.IsAlpha() || aBmpEx.IsTransparent() ) )
+ xImage = pSalBmp->CreateCroppedImage( 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight );
+ else if( aBmpEx.IsAlpha() )
+ {
+ AlphaMask aAlphaMask( aBmpEx.GetAlpha() );
+ Bitmap aMask( aAlphaMask.GetBitmap() );
+ AquaSalBitmap* pMaskBmp = static_cast<AquaSalBitmap*>(aMask.ImplGetImpBitmap()->ImplGetSalBitmap());
+ if( pMaskBmp )
+ xImage = pSalBmp->CreateWithMask( *pMaskBmp, 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight );
+ else
+ xImage = pSalBmp->CreateCroppedImage( 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight );
+ }
+ else if( aBmpEx.GetTransparentType() == TRANSPARENT_BITMAP )
+ {
+ Bitmap aMask( aBmpEx.GetMask() );
+ AquaSalBitmap* pMaskBmp = static_cast<AquaSalBitmap*>(aMask.ImplGetImpBitmap()->ImplGetSalBitmap());
+ if( pMaskBmp )
+ xImage = pSalBmp->CreateWithMask( *pMaskBmp, 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight );
+ else
+ xImage = pSalBmp->CreateCroppedImage( 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight );
+ }
+ else if( aBmpEx.GetTransparentType() == TRANSPARENT_COLOR )
+ {
+ Color aTransColor( aBmpEx.GetTransparentColor() );
+ SalColor nTransColor = MAKE_SALCOLOR( aTransColor.GetRed(), aTransColor.GetGreen(), aTransColor.GetBlue() );
+ xImage = pSalBmp->CreateColorMask( 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight, nTransColor );
+ }
+
+ return xImage;
+}
+
+NSImage* CreateNSImage( const Image& rImage )
+{
+ CGImageRef xImage = CreateCGImage( rImage );
+
+ if( ! xImage )
+ return nil;
+
+ Size aSize( rImage.GetSizePixel() );
+ NSImage* pImage = [[NSImage alloc] initWithSize: NSMakeSize( aSize.Width(), aSize.Height() )];
+ if( pImage )
+ {
+ [pImage setFlipped: YES];
+ [pImage lockFocus];
+
+ NSGraphicsContext* pContext = [NSGraphicsContext currentContext];
+ CGContextRef rCGContext = reinterpret_cast<CGContextRef>([pContext graphicsPort]);
+
+ const CGRect aDstRect = { {0, 0}, { aSize.Width(), aSize.Height() } };
+ CGContextDrawImage( rCGContext, aDstRect, xImage );
+
+ [pImage unlockFocus];
+ }
+
+ CGImageRelease( xImage );
+
+ return pImage;
+}
diff --git a/vcl/aqua/source/app/salnstimer.mm b/vcl/aqua/source/app/salnstimer.mm
new file mode 100755
index 000000000000..73e49fd99c61
--- /dev/null
+++ b/vcl/aqua/source/app/salnstimer.mm
@@ -0,0 +1,56 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include "saltimer.h"
+#include "salnstimer.h"
+#include "salinst.h"
+#include "saldata.hxx"
+
+#include "vcl/svdata.hxx"
+
+@implementation TimerCallbackCaller
+-(void)timerElapsed:(NSTimer*)pTimer
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if( AquaSalTimer::bDispatchTimer )
+ {
+ if( pSVData->mpSalTimer )
+ {
+ YIELD_GUARD;
+ pSVData->mpSalTimer->CallCallback();
+
+ // NSTimer does not end nextEventMatchingMask of NSApplication
+ // so we need to wakeup a waiting Yield to inform it something happened
+ GetSalData()->mpFirstInstance->wakeupYield();
+ }
+ }
+}
+@end
+
diff --git a/vcl/aqua/source/app/salsys.cxx b/vcl/aqua/source/app/salsys.cxx
new file mode 100644
index 000000000000..cf5cf00b7fe4
--- /dev/null
+++ b/vcl/aqua/source/app/salsys.cxx
@@ -0,0 +1,220 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include "tools/rc.hxx"
+#include "vcl/svids.hrc"
+#include "vcl/button.hxx"
+
+#include "salsys.h"
+#include "saldata.hxx"
+#include "salinst.h"
+#include "rtl/ustrbuf.hxx"
+
+using namespace rtl;
+
+// =======================================================================
+
+AquaSalSystem::~AquaSalSystem()
+{
+}
+
+unsigned int AquaSalSystem::GetDisplayScreenCount()
+{
+ NSArray* pScreens = [NSScreen screens];
+ return pScreens ? [pScreens count] : 1;
+}
+
+bool AquaSalSystem::IsMultiDisplay()
+{
+ return false;
+}
+
+unsigned int AquaSalSystem::GetDefaultDisplayNumber()
+{
+ return 0;
+}
+
+Rectangle AquaSalSystem::GetDisplayScreenPosSizePixel( unsigned int nScreen )
+{
+ NSArray* pScreens = [NSScreen screens];
+ Rectangle aRet;
+ NSScreen* pScreen = nil;
+ if( pScreens && nScreen < [pScreens count] )
+ pScreen = [pScreens objectAtIndex: nScreen];
+ else
+ pScreen = [NSScreen mainScreen];
+
+ if( pScreen )
+ {
+ NSRect aFrame = [pScreen frame];
+ aRet = Rectangle( Point( static_cast<long int>(aFrame.origin.x), static_cast<long int>(aFrame.origin.y) ),
+ Size( static_cast<long int>(aFrame.size.width), static_cast<long int>(aFrame.size.height) ) );
+ }
+ return aRet;
+}
+
+Rectangle AquaSalSystem::GetDisplayWorkAreaPosSizePixel( unsigned int nScreen )
+{
+ NSArray* pScreens = [NSScreen screens];
+ Rectangle aRet;
+ NSScreen* pScreen = nil;
+ if( pScreens && nScreen < [pScreens count] )
+ pScreen = [pScreens objectAtIndex: nScreen];
+ else
+ pScreen = [NSScreen mainScreen];
+
+ if( pScreen )
+ {
+ NSRect aFrame = [pScreen visibleFrame];
+ aRet = Rectangle( Point( static_cast<long int>(aFrame.origin.x), static_cast<long int>(aFrame.origin.y) ),
+ Size( static_cast<long int>(aFrame.size.width), static_cast<long int>(aFrame.size.height) ) );
+ }
+ return aRet;
+}
+
+rtl::OUString AquaSalSystem::GetScreenName( unsigned int nScreen )
+{
+ NSArray* pScreens = [NSScreen screens];
+ OUString aRet;
+ if( nScreen < [pScreens count] )
+ {
+ ResMgr* pMgr = ImplGetResMgr();
+ if( pMgr )
+ {
+ String aScreenName( ResId( SV_MAC_SCREENNNAME, *pMgr ) );
+ aScreenName.SearchAndReplaceAllAscii( "%d", String::CreateFromInt32( nScreen ) );
+ aRet = aScreenName;
+ }
+ }
+ return aRet;
+}
+
+static NSString* getStandardString( int nButtonId )
+{
+ rtl::OUString aText( Button::GetStandardText( nButtonId ) );
+ if( ! aText.getLength() ) // this is for bad cases, we might be missing the vcl resource
+ {
+ switch( nButtonId )
+ {
+ case BUTTON_OK: aText = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OK" ) );break;
+ case BUTTON_ABORT: aText = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Abort" ) );break;
+ case BUTTON_CANCEL: aText = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Cancel" ) );break;
+ case BUTTON_RETRY: aText = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Retry" ) );break;
+ case BUTTON_YES: aText = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Yes" ) );break;
+ case BUTTON_NO : aText = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No" ) );break;
+ }
+ }
+ return aText.getLength() ? CreateNSString( aText) : nil;
+}
+
+int AquaSalSystem::ShowNativeMessageBox( const String& rTitle,
+ const String& rMessage,
+ int nButtonCombination,
+ int nDefaultButton)
+{
+ NSString* pTitle = CreateNSString( rTitle );
+ NSString* pMessage = CreateNSString( rMessage );
+
+ struct id_entry
+ {
+ int nCombination;
+ int nDefaultButton;
+ int nTextIds[3];
+ } aButtonIds[] =
+ {
+ { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK, { BUTTON_OK, -1, -1 } },
+ { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK, { BUTTON_OK, BUTTON_CANCEL, -1 } },
+ { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL, { BUTTON_CANCEL, BUTTON_OK, -1 } },
+ { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_ABORT_RETRY_IGNORE, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_ABORT, { BUTTON_ABORT, BUTTON_IGNORE, BUTTON_RETRY } },
+ { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_ABORT_RETRY_IGNORE, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_RETRY, { BUTTON_RETRY, BUTTON_IGNORE, BUTTON_ABORT } },
+ { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_ABORT_RETRY_IGNORE, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_IGNORE, { BUTTON_IGNORE, BUTTON_IGNORE, BUTTON_ABORT } },
+ { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_YES_NO_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_YES, { BUTTON_YES, BUTTON_NO, BUTTON_CANCEL } },
+ { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_YES_NO_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO, { BUTTON_NO, BUTTON_YES, BUTTON_CANCEL } },
+ { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_YES_NO_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL, { BUTTON_CANCEL, BUTTON_YES, BUTTON_NO } },
+ { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_YES_NO, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_YES, { BUTTON_YES, BUTTON_NO, -1 } },
+ { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_YES_NO, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO, { BUTTON_NO, BUTTON_YES, -1 } },
+ { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_RETRY, { BUTTON_RETRY, BUTTON_CANCEL, -1 } },
+ { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL, { BUTTON_CANCEL, BUTTON_RETRY, -1 } }
+ };
+
+ NSString* pDefText = nil;
+ NSString* pAltText = nil;
+ NSString* pOthText = nil;
+
+ unsigned int nC;
+ for( nC = 0; nC < sizeof(aButtonIds)/sizeof(aButtonIds[0]); nC++ )
+ {
+ if( aButtonIds[nC].nCombination == nButtonCombination )
+ {
+ if( aButtonIds[nC].nDefaultButton == nDefaultButton )
+ {
+ if( aButtonIds[nC].nTextIds[0] != -1 )
+ pDefText = getStandardString( aButtonIds[nC].nTextIds[0] );
+ if( aButtonIds[nC].nTextIds[1] != -1 )
+ pAltText = getStandardString( aButtonIds[nC].nTextIds[1] );
+ if( aButtonIds[nC].nTextIds[2] != -1 )
+ pOthText = getStandardString( aButtonIds[nC].nTextIds[2] );
+ break;
+ }
+ }
+ }
+
+
+ int nResult = NSRunAlertPanel( pTitle, pMessage, pDefText, pAltText, pOthText );
+
+ if( pTitle )
+ [pTitle release];
+ if( pMessage )
+ [pMessage release];
+ if( pDefText )
+ [pDefText release];
+ if( pAltText )
+ [pAltText release];
+ if( pOthText )
+ [pOthText release];
+
+ int nRet = 0;
+ if( nC < sizeof(aButtonIds)/sizeof(aButtonIds[0]) && nResult >= 1 && nResult <= 3 )
+ {
+ int nPressed = aButtonIds[nC].nTextIds[nResult-1];
+ switch( nPressed )
+ {
+ case BUTTON_NO: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO; break;
+ case BUTTON_YES: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_YES; break;
+ case BUTTON_OK: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK; break;
+ case BUTTON_CANCEL: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL; break;
+ case BUTTON_ABORT: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_ABORT; break;
+ case BUTTON_RETRY: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_RETRY; break;
+ case BUTTON_IGNORE: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_IGNORE; break;
+ }
+ }
+
+ return nRet;
+}
diff --git a/vcl/aqua/source/app/saltimer.cxx b/vcl/aqua/source/app/saltimer.cxx
new file mode 100644
index 000000000000..724857e92a0c
--- /dev/null
+++ b/vcl/aqua/source/app/saltimer.cxx
@@ -0,0 +1,135 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include "saltimer.h"
+#include "salnstimer.h"
+#include "saldata.hxx"
+#include "salframe.h"
+#include "salinst.h"
+
+// =======================================================================
+
+NSTimer* AquaSalTimer::pRunningTimer = nil;
+bool AquaSalTimer::bDispatchTimer = false;
+
+
+void ImplSalStartTimer( ULONG nMS )
+{
+ SalData* pSalData = GetSalData();
+ if( pSalData->mpFirstInstance->isNSAppThread() )
+ {
+ AquaSalTimer::bDispatchTimer = true;
+ NSTimeInterval aTI = double(nMS)/1000.0;
+ if( AquaSalTimer::pRunningTimer != nil )
+ {
+ if( [AquaSalTimer::pRunningTimer timeInterval] == aTI )
+ // set new fire date
+ [AquaSalTimer::pRunningTimer setFireDate: [NSDate dateWithTimeIntervalSinceNow: aTI]];
+ else
+ {
+ [AquaSalTimer::pRunningTimer invalidate];
+ AquaSalTimer::pRunningTimer = nil;
+ }
+ }
+ if( AquaSalTimer::pRunningTimer == nil )
+ {
+ AquaSalTimer::pRunningTimer = [NSTimer scheduledTimerWithTimeInterval: aTI
+ target: [[[TimerCallbackCaller alloc] init] autorelease]
+ selector: @selector(timerElapsed:)
+ userInfo: nil
+ repeats: YES];
+ /* #i84055# add timer to tracking run loop mode,
+ so they also elapse while e.g. life resize
+ */
+ [[NSRunLoop currentRunLoop] addTimer: AquaSalTimer::pRunningTimer forMode: NSEventTrackingRunLoopMode];
+ }
+ }
+ else
+ {
+ SalData::ensureThreadAutoreleasePool();
+ // post an event so we can get into the main thread
+ NSPoint aPt = { 0, 0 };
+ NSEvent* pEvent = [NSEvent otherEventWithType: NSApplicationDefined
+ location: aPt
+ modifierFlags: 0
+ timestamp: [NSDate timeIntervalSinceReferenceDate]
+ windowNumber: 0
+ context: nil
+ subtype: AquaSalInstance::AppStartTimerEvent
+ data1: (int)nMS
+ data2: 0 ];
+ if( pEvent )
+ [NSApp postEvent: pEvent atStart: YES];
+ }
+}
+
+void ImplSalStopTimer()
+{
+ AquaSalTimer::bDispatchTimer = false;
+}
+
+void AquaSalTimer::handleStartTimerEvent( NSEvent* pEvent )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if( pSVData->mpSalTimer )
+ {
+ NSTimeInterval posted = [pEvent timestamp] + NSTimeInterval([pEvent data1])/1000.0;
+ NSTimeInterval current = [NSDate timeIntervalSinceReferenceDate];
+ if( (posted - current) <= 0.0 )
+ {
+ YIELD_GUARD;
+ // timer already elapsed since event posted
+ pSVData->mpSalTimer->CallCallback();
+ }
+ ImplSalStartTimer( ULONG( [pEvent data1] ) );
+ }
+
+}
+
+AquaSalTimer::AquaSalTimer( )
+{
+}
+
+AquaSalTimer::~AquaSalTimer()
+{
+ ImplSalStopTimer();
+}
+
+void AquaSalTimer::Start( ULONG nMS )
+{
+ ImplSalStartTimer( nMS );
+}
+
+void AquaSalTimer::Stop()
+{
+ ImplSalStopTimer();
+}
+
+
diff --git a/vcl/aqua/source/app/vclnsapp.mm b/vcl/aqua/source/app/vclnsapp.mm
new file mode 100755
index 000000000000..f33599fa086e
--- /dev/null
+++ b/vcl/aqua/source/app/vclnsapp.mm
@@ -0,0 +1,518 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+ // MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include "vclnsapp.h"
+#include "salinst.h"
+#include "saldata.hxx"
+#include "salframe.h"
+#include "salframeview.h"
+
+#include "vcl/window.hxx"
+#include "vcl/svapp.hxx"
+#include "vcl/cmdevt.hxx"
+#include "rtl/ustrbuf.hxx"
+
+#include "premac.h"
+#import "Carbon/Carbon.h"
+#import "apple_remote/RemoteControl.h"
+#include "postmac.h"
+
+
+@implementation CocoaThreadEnabler
+-(void)enableCocoaThreads:(id)param
+{
+ // do nothing, this is just to start an NSThread and therefore put
+ // Cocoa into multithread mode
+}
+@end
+
+@implementation VCL_NSApplication
+-(void)sendEvent:(NSEvent*)pEvent
+{
+ NSEventType eType = [pEvent type];
+ if( eType == NSApplicationDefined )
+ GetSalData()->mpFirstInstance->handleAppDefinedEvent( pEvent );
+ else if( eType == NSKeyDown && ([pEvent modifierFlags] & NSCommandKeyMask) != 0 )
+ {
+ NSWindow* pKeyWin = [NSApp keyWindow];
+ if( pKeyWin && [pKeyWin isKindOfClass: [SalFrameWindow class]] )
+ {
+ AquaSalFrame* pFrame = [(SalFrameWindow*)pKeyWin getSalFrame];
+ // handle Cmd-W
+ // FIXME: the correct solution would be to handle this in framework
+ // in the menu code
+ // however that is currently being revised, so let's use a preliminary solution here
+ // this hack is based on assumption
+ // a) Cmd-W is the same in all languages in OOo's menu conig
+ // b) Cmd-W is the same in all languages in on MacOS
+ // for now this seems to be true
+ unsigned int nModMask = ([pEvent modifierFlags] & (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask|NSCommandKeyMask));
+ if( (pFrame->mnStyleMask & NSClosableWindowMask) != 0 )
+ {
+ if( nModMask == NSCommandKeyMask
+ && [[pEvent charactersIgnoringModifiers] isEqualToString: @"w"] )
+ {
+ [pFrame->getWindow() windowShouldClose: nil];
+ return;
+ }
+ }
+
+ /*
+ * #i98949# - Cmd-M miniaturize window, Cmd-Option-M miniaturize all windows
+ */
+ if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"m"] )
+ {
+ if ( nModMask == NSCommandKeyMask && ([pFrame->getWindow() styleMask] & NSMiniaturizableWindowMask) )
+ {
+ [pFrame->getWindow() performMiniaturize: nil];
+ return;
+ }
+
+ if ( nModMask == ( NSCommandKeyMask | NSAlternateKeyMask ) )
+ {
+ [NSApp miniaturizeAll: nil];
+ 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;
+ bool bHandled = false;
+
+ // dispatch to view directly to avoid the key event being consumed by the menubar
+ // popup windows do not get the focus, so they don't get these either
+ // simplest would be dispatch this to the key window always if it is without parent
+ // however e.g. in document we want the menu shortcut if e.g. the stylist has focus
+ if( pFrame->mpParent && (pFrame->mnStyle & SAL_FRAME_STYLE_FLOAT) == 0 )
+ {
+ [[pKeyWin contentView] keyDown: pEvent];
+ bHandled = GetSalData()->maKeyEventAnswer[ pEvent ];
+ }
+
+ // see whether the main menu consumes this event
+ // if not, we want to dispatch it ourselves. Unless we do this "trick"
+ // the main menu just beeps for an unknown or disabled key equivalent
+ // and swallows the event wholesale
+ NSMenu* pMainMenu = [NSApp mainMenu];
+ if( ! bHandled && (pMainMenu == 0 || ! [pMainMenu performKeyEquivalent: pEvent]) )
+ {
+ [[pKeyWin contentView] keyDown: pEvent];
+ bHandled = GetSalData()->maKeyEventAnswer[ pEvent ];
+ }
+ else
+ bHandled = true; // event handled already or main menu just handled it
+
+ GetSalData()->maKeyEventAnswer.erase( pEvent );
+ if( bHandled )
+ return;
+ }
+ else if( pKeyWin )
+ {
+ // #i94601# a window not of vcl's making has the focus.
+ // Since our menus do not invoke the usual commands
+ // try to play nice with native windows like the file dialog
+ // and emulate them
+ // precondition: this ONLY works because CMD-V (paste), CMD-C (copy) and CMD-X (cut) are
+ // NOT localized, that is the same in all locales. Should this be
+ // different in any locale, this hack will fail.
+ unsigned int nModMask = ([pEvent modifierFlags] & (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask|NSCommandKeyMask));
+ if( nModMask == NSCommandKeyMask )
+ {
+
+ if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"v"] )
+ {
+ if( [NSApp sendAction: @selector(paste:) to: nil from: nil] )
+ return;
+ }
+ else if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"c"] )
+ {
+ if( [NSApp sendAction: @selector(copy:) to: nil from: nil] )
+ return;
+ }
+ else if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"x"] )
+ {
+ if( [NSApp sendAction: @selector(cut:) to: nil from: nil] )
+ return;
+ }
+ }
+ }
+ }
+ else if( eType == NSScrollWheel && ( GetSalData()->mnSystemVersion < VER_LEOPARD /* fixed in Leopard and above */ ) )
+ {
+
+ NSWindow* pWin = [pEvent window];
+ // on Tiger wheel events do not reach non key windows
+ // which probably should be considered a bug
+ if( [pWin isKindOfClass: [SalFrameWindow class]] && [pWin canBecomeKeyWindow] == NO )
+ {
+ [[pWin contentView] scrollWheel: pEvent];
+ return;
+ }
+ }
+ [super sendEvent: pEvent];
+}
+
+-(void)sendSuperEvent:(NSEvent*)pEvent
+{
+ [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
+{
+ return AquaSalInstance::GetDynamicDockMenu();
+}
+
+-(MacOSBOOL)application: (NSApplication*)app openFile: (NSString*)pFile
+{
+ const rtl::OUString aFile( GetOUString( pFile ) );
+ if( ! AquaSalInstance::isOnCommandLine( aFile ) )
+ {
+ const ApplicationEvent* pAppEvent = new ApplicationEvent( String(), ApplicationAddress(),
+ APPEVENT_OPEN_STRING, aFile );
+ AquaSalInstance::aAppEventList.push_back( pAppEvent );
+ }
+ return YES;
+}
+
+-(void)application: (NSApplication*) app openFiles: (NSArray*)files
+{
+ rtl::OUStringBuffer aFileList( 256 );
+
+ NSEnumerator* it = [files objectEnumerator];
+ NSString* pFile = nil;
+
+ while( (pFile = [it nextObject]) != nil )
+ {
+ const rtl::OUString aFile( GetOUString( pFile ) );
+ if( ! AquaSalInstance::isOnCommandLine( aFile ) )
+ {
+ if( aFileList.getLength() > 0 )
+ aFileList.append( sal_Unicode( APPEVENT_PARAM_DELIMITER ) );
+ aFileList.append( aFile );
+ }
+ }
+
+ if( aFileList.getLength() )
+ {
+ // we have no back channel here, we have to assume success, in which case
+ // replyToOpenOrPrint does not need to be called according to documentation
+ // [app replyToOpenOrPrint: NSApplicationDelegateReplySuccess];
+ const ApplicationEvent* pAppEvent = new ApplicationEvent( String(), ApplicationAddress(),
+ APPEVENT_OPEN_STRING, aFileList.makeStringAndClear() );
+ AquaSalInstance::aAppEventList.push_back( pAppEvent );
+ }
+}
+
+-(MacOSBOOL)application: (NSApplication*)app printFile: (NSString*)pFile
+{
+ const rtl::OUString aFile( GetOUString( pFile ) );
+ const ApplicationEvent* pAppEvent = new ApplicationEvent( String(), ApplicationAddress(),
+ APPEVENT_PRINT_STRING, aFile );
+ AquaSalInstance::aAppEventList.push_back( pAppEvent );
+ return YES;
+}
+-(NSApplicationPrintReply)application: (NSApplication *) app printFiles:(NSArray *)files withSettings: (NSDictionary *)printSettings showPrintPanels:(MacOSBOOL)bShowPrintPanels
+{
+ // currently ignores print settings an bShowPrintPanels
+ rtl::OUStringBuffer aFileList( 256 );
+
+ NSEnumerator* it = [files objectEnumerator];
+ NSString* pFile = nil;
+
+ while( (pFile = [it nextObject]) != nil )
+ {
+ if( aFileList.getLength() > 0 )
+ aFileList.append( sal_Unicode( APPEVENT_PARAM_DELIMITER ) );
+ aFileList.append( GetOUString( pFile ) );
+ }
+ const ApplicationEvent* pAppEvent = new ApplicationEvent( String(), ApplicationAddress(),
+ APPEVENT_PRINT_STRING, aFileList.makeStringAndClear() );
+ AquaSalInstance::aAppEventList.push_back( pAppEvent );
+ // we have no back channel here, we have to assume success
+ // correct handling would be NSPrintingReplyLater and then send [app replyToOpenOrPrint]
+ return NSPrintingSuccess;
+}
+
+-(NSApplicationTerminateReply)applicationShouldTerminate: (NSApplication *) app
+{
+ SalData* pSalData = GetSalData();
+ #if 1 // currently do some really bad hack
+ if( ! pSalData->maFrames.empty() )
+ {
+ /* #i92766# something really weird is going on with the retain count of
+ our windows; sometimes we get a duplicate free before exit on one of our
+ NSWindows. The reason is unclear; to avoid this currently we retain them once more
+
+ FIXME: this is a really bad hack, relying on the system to catch the leaked
+ resources. Find out what really goes on here and fix it !
+ */
+ std::vector< NSWindow* > aHackRetainedWindows;
+ for( std::list< AquaSalFrame* >::iterator it = pSalData->maFrames.begin();
+ it != pSalData->maFrames.end(); ++it )
+ {
+ #if OSL_DEBUG_LEVEL > 1
+ Window* pWin = (*it)->GetWindow();
+ String aTitle = pWin->GetText();
+ Window* pClient = pWin->ImplGetClientWindow();
+ fprintf( stderr, "retaining %p (old count %d) windowtype=%s clienttyp=%s title=%s\n",
+ (*it)->mpWindow, [(*it)->mpWindow retainCount],
+ typeid(*pWin).name(), pClient ? typeid(*pClient).name() : "<nil>",
+ rtl::OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ).getStr()
+ );
+ #endif
+ [(*it)->mpWindow retain];
+ aHackRetainedWindows.push_back( (*it)->mpWindow );
+ }
+ if( pSalData->maFrames.front()->CallCallback( SALEVENT_SHUTDOWN, NULL ) )
+ {
+ for( std::vector< NSWindow* >::iterator it = aHackRetainedWindows.begin();
+ it != aHackRetainedWindows.end(); ++it )
+ {
+ // clean up the retaing count again from the shutdown workaround
+ #if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "releasing %p\n", (*it) );
+ #endif
+ [(*it) release];
+ }
+ return NSTerminateCancel;
+ }
+ #if OSL_DEBUG_LEVEL > 1
+ for( std::list< AquaSalFrame* >::iterator it = pSalData->maFrames.begin();
+ it != pSalData->maFrames.end(); ++it )
+ {
+ Window* pWin = (*it)->GetWindow();
+ String aTitle = pWin->GetText();
+ Window* pClient = pWin->ImplGetClientWindow();
+ fprintf( stderr, "frame still alive: NSWindow %p windowtype=%s clienttyp=%s title=%s\n",
+ (*it)->mpWindow, typeid(*pWin).name(), pClient ? typeid(*pClient).name() : "<nil>",
+ rtl::OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ).getStr()
+ );
+ }
+ #endif
+ }
+ #else // the clean version follows
+ return pSalData->maFrames.front()->CallCallback( SALEVENT_SHUTDOWN, NULL ) ? NSTerminateCancel : NSTerminateNow;
+ #endif
+ return NSTerminateNow;
+}
+
+-(void)systemColorsChanged: (NSNotification*) pNotification
+{
+ const SalData* pSalData = GetSalData();
+ if( !pSalData->maFrames.empty() )
+ pSalData->maFrames.front()->CallCallback( SALEVENT_SETTINGSCHANGED, NULL );
+}
+
+-(void)screenParametersChanged: (NSNotification*) pNotification
+{
+ SalData* pSalData = GetSalData();
+ std::list< AquaSalFrame* >::iterator it;
+ for( it = pSalData->maFrames.begin(); it != pSalData->maFrames.end(); ++it )
+ {
+ (*it)->screenParametersChanged();
+ }
+}
+
+-(void)scrollbarVariantChanged: (NSNotification*) pNotification
+{
+ GetSalData()->mpFirstInstance->delayedSettingsChanged( true );
+}
+
+-(void)scrollbarSettingsChanged: (NSNotification*) pNotification
+{
+ GetSalData()->mpFirstInstance->delayedSettingsChanged( false );
+}
+
+-(void)addFallbackMenuItem: (NSMenuItem*)pNewItem
+{
+ AquaSalMenu::addFallbackMenuItem( pNewItem );
+}
+
+-(void)removeFallbackMenuItem: (NSMenuItem*)pItem
+{
+ AquaSalMenu::removeFallbackMenuItem( pItem );
+}
+
+-(void)addDockMenuItem: (NSMenuItem*)pNewItem
+{
+ NSMenu* pDock = AquaSalInstance::GetDynamicDockMenu();
+ [pDock insertItem: pNewItem atIndex: [pDock numberOfItems]];
+}
+
+// for Apple Remote implementation
+
+#pragma mark -
+#pragma mark NSApplication Delegates
+- (void)applicationWillBecomeActive:(NSNotification *)aNotification {
+ if (GetSalData()->mpMainController->remoteControl) {
+
+ // [remoteControl startListening: self];
+ // does crash because the right thing to do is
+ // [GetSalData()->mpMainController->remoteControl startListening: self];
+ // but the instance variable 'remoteControl' is declared protected
+ // workaround : declare remoteControl instance variable as public in RemoteMainController.m
+
+ [GetSalData()->mpMainController->remoteControl startListening: self];
+#ifdef DEBUG
+ NSLog(@"Apple Remote will become active - Using remote controls");
+#endif
+ }
+}
+
+- (void)applicationWillResignActive:(NSNotification *)aNotification {
+ if (GetSalData()->mpMainController->remoteControl) {
+
+ // [remoteControl stopListening: self];
+ // does crash because the right thing to do is
+ // [GetSalData()->mpMainController->remoteControl stopListening: self];
+ // but the instance variable 'remoteControl' is declared protected
+ // workaround : declare remoteControl instance variable as public in RemoteMainController.m
+
+ [GetSalData()->mpMainController->remoteControl stopListening: self];
+#ifdef DEBUG
+ NSLog(@"Apple Remote will resign active - Releasing remote controls");
+#endif
+ }
+}
+
+- (MacOSBOOL)applicationShouldHandleReopen: (NSApplication*)pApp hasVisibleWindows: (MacOSBOOL) bWinVisible
+{
+ NSObject* pHdl = GetSalData()->mpDockIconClickHandler;
+ if( pHdl && [pHdl respondsToSelector: @selector(dockIconClicked:)] )
+ {
+ [pHdl performSelector:@selector(dockIconClicked:) withObject: self];
+ }
+ return YES;
+}
+
+-(void)setDockIconClickHandler: (NSObject*)pHandler
+{
+ GetSalData()->mpDockIconClickHandler = pHandler;
+}
+
+
+@end
+