1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salinst.cxx,v $
10 * $Revision: 1.53.22.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
36 #include "tools/fsys.hxx"
37 #include "tools/getprocessworkingdir.hxx"
38 #include "osl/process.h"
39 #include "rtl/ustrbuf.hxx"
40 #include "vcl/svapp.hxx"
41 #include "vcl/print.h"
42 #include "vcl/salimestatus.hxx"
43 #include "vcl/window.hxx"
44 #include "vcl/timer.hxx"
45 #include "vcl/impbmp.hxx"
47 #include "saldata.hxx"
59 #include <Foundation/Foundation.h>
60 #include <ApplicationServices/ApplicationServices.h>
61 #import "apple_remote/RemoteMainController.h"
62 #include "apple_remote/RemoteControl.h"
68 extern BOOL
ImplSVMain();
70 static BOOL
* gpbInit
= 0;
71 static NSMenu
* pDockMenu
= nil
;
72 static bool bNoSVMain
= true;
73 static bool bLeftMain
= false;
74 // -----------------------------------------------------------------------
76 class AquaDelayedSettingsChanged
: public Timer
80 AquaDelayedSettingsChanged( bool bInvalidate
) :
81 mbInvalidate( bInvalidate
)
85 virtual void Timeout()
87 SalData
* pSalData
= GetSalData();
88 if( ! pSalData
->maFrames
.empty() )
89 pSalData
->maFrames
.front()->CallCallback( SALEVENT_SETTINGSCHANGED
, NULL
);
93 for( std::list
< AquaSalFrame
* >::iterator it
= pSalData
->maFrames
.begin();
94 it
!= pSalData
->maFrames
.end(); ++it
)
97 (*it
)->SendPaintEvent( NULL
);
105 void AquaSalInstance::delayedSettingsChanged( bool bInvalidate
)
107 vos::OGuard
aGuard( *mpSalYieldMutex
);
108 AquaDelayedSettingsChanged
* pTimer
= new AquaDelayedSettingsChanged( bInvalidate
);
109 pTimer
->SetTimeout( 50 );
114 // the AppEventList must be available before any SalData/SalInst/etc. objects are ready
115 typedef std::list
<const ApplicationEvent
*> AppEventList
;
116 AppEventList
AquaSalInstance::aAppEventList
;
118 NSMenu
* AquaSalInstance::GetDynamicDockMenu()
120 if( ! pDockMenu
&& ! bLeftMain
)
121 pDockMenu
= [[NSMenu alloc
] initWithTitle
: @
""];
125 bool AquaSalInstance::isOnCommandLine( const rtl::OUString
& rArg
)
127 sal_uInt32 nArgs
= osl_getCommandArgCount();
128 for( sal_uInt32 i
= 0; i
< nArgs
; i
++ )
131 osl_getCommandArg( i
, &aArg
.pData
);
132 if( aArg
.equals( rArg
) )
139 // initialize the cocoa VCL_NSApplication object
140 // returns an NSAutoreleasePool that must be released when the event loop begins
141 static void initNSApp()
143 // create our cocoa NSApplication
144 [VCL_NSApplication sharedApplication
];
146 SalData::ensureThreadAutoreleasePool();
148 // put cocoa into multithreaded mode
149 [NSThread detachNewThreadSelector
:@
selector(enableCocoaThreads
:) toTarget
:[[CocoaThreadEnabler alloc
] init
] withObject
:nil
];
151 // activate our delegate methods
152 [NSApp setDelegate
: NSApp
];
154 [[NSNotificationCenter defaultCenter
] addObserver
: NSApp
155 selector
: @
selector(systemColorsChanged
:)
156 name
: NSSystemColorsDidChangeNotification
158 [[NSNotificationCenter defaultCenter
] addObserver
: NSApp
159 selector
: @
selector(screenParametersChanged
:)
160 name
: NSApplicationDidChangeScreenParametersNotification
162 // add observers for some settings changes that affect vcl's settings
164 [[NSDistributedNotificationCenter defaultCenter
] addObserver
: NSApp
165 selector
: @
selector(scrollbarVariantChanged
:)
166 name
: @
"AppleAquaScrollBarVariantChanged"
168 // scrollbar page behavior ("jump to here" or not)
169 [[NSDistributedNotificationCenter defaultCenter
] addObserver
: NSApp
170 selector
: @
selector(scrollbarSettingsChanged
:)
171 name
: @
"AppleNoRedisplayAppearancePreferenceChanged"
174 // get System Version and store the value in GetSalData()->mnSystemVersion
176 SInt32 systemVersion
= VER_TIGER
; // Initialize with minimal requirement
177 if( (err
= Gestalt(gestaltSystemVersion
, &systemVersion
)) == noErr
)
179 GetSalData()->mnSystemVersion
= systemVersion
;
180 #if OSL_DEBUG_LEVEL > 1
181 fprintf( stderr
, "System Version %x\n", (unsigned int)systemVersion
);
185 NSLog(@
"Unable to obtain system version: %ld", (long)err
);
187 // Initialize Apple Remote
188 GetSalData()->mpMainController
= [[MainController alloc
] init
];
190 [[NSDistributedNotificationCenter defaultCenter
] addObserver
: NSApp
191 selector
: @
selector(applicationWillBecomeActive
:)
192 name
: @
"AppleRemoteWillBecomeActive"
195 [[NSDistributedNotificationCenter defaultCenter
] addObserver
: NSApp
196 selector
: @
selector(applicationWillResignActive
:)
197 name
: @
"AppleRemoteWillResignActive"
200 if( ImplGetSVData()->mbIsTestTool
)
201 [NSApp activateIgnoringOtherApps
: YES
];
204 BOOL
ImplSVMainHook( BOOL
* pbInit
)
211 NSPoint aPt
= { 0, 0 };
212 NSEvent
* pEvent
= [NSEvent otherEventWithType
: NSApplicationDefined
218 subtype
: AquaSalInstance::AppExecuteSVMain
223 [NSApp postEvent
: pEvent atStart
: NO
];
225 rtl::OUString aExeURL
, aExe
;
226 osl_getExecutableFile( &aExeURL
.pData
);
227 osl_getSystemPathFromFileURL( aExeURL
.pData
, &aExe
.pData
);
228 rtl::OString
aByteExe( rtl::OUStringToOString( aExe
, osl_getThreadTextEncoding() ) );
231 aByteExe
+= OString ( " NSAccessibilityDebugLogLevel 1" );
232 const char* pArgv
[] = { aByteExe
.getStr(), NULL
};
233 NSApplicationMain( 3, pArgv
);
235 const char* pArgv
[] = { aByteExe
.getStr(), NULL
};
236 NSApplicationMain( 1, pArgv
);
241 DBG_ERROR( "NSApplication initialization could not be done" );
244 return TRUE
; // indicate that ImplSVMainHook is implemented
247 // =======================================================================
249 void SalAbort( const XubString
& rErrorText
)
251 if( !rErrorText
.Len() )
252 fprintf( stderr
, "Application Error " );
254 fprintf( stderr
, "%s ",
255 ByteString( rErrorText
, gsl_getSystemTextEncoding() ).GetBuffer() );
259 // -----------------------------------------------------------------------
263 SalData
*pSalData
= new SalData
;
264 SetSalData( pSalData
);
267 // -----------------------------------------------------------------------
269 const ::rtl::OUString
& SalGetDesktopEnvironment()
271 static OUString
aDesktopEnvironment(RTL_CONSTASCII_USTRINGPARAM( "MacOSX" ));
272 return aDesktopEnvironment
;
275 // -----------------------------------------------------------------------
279 SalData
*pSalData
= GetSalData();
280 if( pSalData
->mpStatusItem
)
282 [pSalData
->mpStatusItem release
];
283 pSalData
->mpStatusItem
= nil
;
289 // -----------------------------------------------------------------------
292 #include <crt_externs.h>
295 // -----------------------------------------------------------------------
299 rtl::OUString urlWorkDir
;
300 rtl_uString
*sysWorkDir
= NULL
;
301 if (tools::getProcessWorkingDir(&urlWorkDir
))
303 oslFileError err2
= osl_getSystemPathFromFileURL(urlWorkDir
.pData
, &sysWorkDir
);
304 if (err2
== osl_File_E_None
)
306 ByteString
aPath( getenv( "PATH" ) );
307 ByteString
aResPath( getenv( "STAR_RESOURCEPATH" ) );
308 ByteString
aLibPath( getenv( "DYLD_LIBRARY_PATH" ) );
309 ByteString
aCmdPath( OUStringToOString(OUString(sysWorkDir
), RTL_TEXTENCODING_UTF8
).getStr() );
311 // Get absolute path of command's directory
312 if ( aCmdPath
.Len() ) {
313 DirEntry
aCmdDirEntry( aCmdPath
);
314 aCmdDirEntry
.ToAbs();
315 aCmdPath
= ByteString( aCmdDirEntry
.GetPath().GetFull(), RTL_TEXTENCODING_ASCII_US
);
317 // Assign to PATH environment variable
318 if ( aCmdPath
.Len() )
320 aTmpPath
= ByteString( "PATH=" );
321 aTmpPath
+= aCmdPath
;
323 aTmpPath
+= ByteString( DirEntry::GetSearchDelimiter(), RTL_TEXTENCODING_ASCII_US
);
325 putenv( (char*)aTmpPath
.GetBuffer() );
327 // Assign to STAR_RESOURCEPATH environment variable
328 if ( aCmdPath
.Len() )
330 aTmpPath
= ByteString( "STAR_RESOURCEPATH=" );
331 aTmpPath
+= aCmdPath
;
332 if ( aResPath
.Len() )
333 aTmpPath
+= ByteString( DirEntry::GetSearchDelimiter(), RTL_TEXTENCODING_ASCII_US
);
334 aTmpPath
+= aResPath
;
335 putenv( (char*)aTmpPath
.GetBuffer() );
337 // Assign to DYLD_LIBRARY_PATH environment variable
338 if ( aCmdPath
.Len() )
340 aTmpPath
= ByteString( "DYLD_LIBRARY_PATH=" );
341 aTmpPath
+= aCmdPath
;
342 if ( aLibPath
.Len() )
343 aTmpPath
+= ByteString( DirEntry::GetSearchDelimiter(), RTL_TEXTENCODING_ASCII_US
);
344 aTmpPath
+= aLibPath
;
345 putenv( (char*)aTmpPath
.GetBuffer() );
351 // -----------------------------------------------------------------------
357 // =======================================================================
359 SalYieldMutex::SalYieldMutex()
365 void SalYieldMutex::acquire()
368 mnThreadId
= NAMESPACE_VOS(OThread
)::getCurrentIdentifier();
372 void SalYieldMutex::release()
374 if ( mnThreadId
== NAMESPACE_VOS(OThread
)::getCurrentIdentifier() )
383 sal_Bool
SalYieldMutex::tryToAcquire()
385 if ( OMutex::tryToAcquire() )
387 mnThreadId
= NAMESPACE_VOS(OThread
)::getCurrentIdentifier();
395 // -----------------------------------------------------------------------
397 // some convenience functions regarding the yield mutex, aka solar mutex
399 BOOL
ImplSalYieldMutexTryToAcquire()
401 AquaSalInstance
* pInst
= (AquaSalInstance
*) GetSalData()->mpFirstInstance
;
403 return pInst
->mpSalYieldMutex
->tryToAcquire();
408 void ImplSalYieldMutexAcquire()
410 AquaSalInstance
* pInst
= (AquaSalInstance
*) GetSalData()->mpFirstInstance
;
412 pInst
->mpSalYieldMutex
->acquire();
415 void ImplSalYieldMutexRelease()
417 AquaSalInstance
* pInst
= (AquaSalInstance
*) GetSalData()->mpFirstInstance
;
419 pInst
->mpSalYieldMutex
->release();
422 // =======================================================================
424 SalInstance
* CreateSalInstance()
426 // this is the case for not using SVMain
431 SalData
* pSalData
= GetSalData();
432 DBG_ASSERT( pSalData
->mpFirstInstance
== NULL
, "more than one instance created" );
433 AquaSalInstance
* pInst
= new AquaSalInstance
;
435 // init instance (only one instance in this version !!!)
436 pSalData
->mpFirstInstance
= pInst
;
437 // this one is for outside AquaSalInstance::Yield
438 SalData::ensureThreadAutoreleasePool();
439 // no focus rects on NWF aqua
440 ImplGetSVData()->maNWFData
.mbNoFocusRects
= true;
441 ImplGetSVData()->maNWFData
.mbNoBoldTabFocus
= true;
442 ImplGetSVData()->maNWFData
.mbNoActiveTabTextRaise
= true;
443 ImplGetSVData()->maNWFData
.mbCenteredTabs
= true;
444 ImplGetSVData()->maNWFData
.mbProgressNeedsErase
= true;
445 ImplGetSVData()->maNWFData
.mbCheckBoxNeedsErase
= true;
446 ImplGetSVData()->maGDIData
.mbPrinterPullModel
= true;
447 ImplGetSVData()->maGDIData
.mbNoXORClipping
= true;
448 ImplGetSVData()->maWinData
.mbNoSaveBackground
= true;
453 // -----------------------------------------------------------------------
455 void DestroySalInstance( SalInstance
* pInst
)
460 // -----------------------------------------------------------------------
462 AquaSalInstance::AquaSalInstance()
464 mpSalYieldMutex
= new SalYieldMutex
;
465 mpSalYieldMutex
->acquire();
466 maMainThread
= vos::OThread::getCurrentIdentifier();
467 mbWaitingYield
= false;
468 maUserEventListMutex
= osl_createMutex();
469 mnActivePrintJobs
= 0;
472 // -----------------------------------------------------------------------
474 AquaSalInstance::~AquaSalInstance()
476 mpSalYieldMutex
->release();
477 delete mpSalYieldMutex
;
478 osl_destroyMutex( maUserEventListMutex
);
481 // -----------------------------------------------------------------------
483 void AquaSalInstance::wakeupYield()
488 SalData::ensureThreadAutoreleasePool();
489 NSPoint aPt
= { 0, 0 };
490 NSEvent
* pEvent
= [NSEvent otherEventWithType
: NSApplicationDefined
496 subtype
: AquaSalInstance::YieldWakeupEvent
500 [NSApp postEvent
: pEvent atStart
: NO
];
504 // -----------------------------------------------------------------------
506 void AquaSalInstance::PostUserEvent( AquaSalFrame
* pFrame
, USHORT nType
, void* pData
)
508 osl_acquireMutex( maUserEventListMutex
);
509 maUserEvents
.push_back( SalUserEvent( pFrame
, pData
, nType
) );
510 osl_releaseMutex( maUserEventListMutex
);
512 // notify main loop that an event has arrived
516 // -----------------------------------------------------------------------
518 vos::IMutex
* AquaSalInstance::GetYieldMutex()
520 return mpSalYieldMutex
;
523 // -----------------------------------------------------------------------
525 ULONG
AquaSalInstance::ReleaseYieldMutex()
527 SalYieldMutex
* pYieldMutex
= mpSalYieldMutex
;
528 if ( pYieldMutex
->GetThreadId() ==
529 NAMESPACE_VOS(OThread
)::getCurrentIdentifier() )
531 ULONG nCount
= pYieldMutex
->GetAcquireCount();
535 pYieldMutex
->release();
545 // -----------------------------------------------------------------------
547 void AquaSalInstance::AcquireYieldMutex( ULONG nCount
)
549 SalYieldMutex
* pYieldMutex
= mpSalYieldMutex
;
552 pYieldMutex
->acquire();
557 // -----------------------------------------------------------------------
559 bool AquaSalInstance::isNSAppThread() const
561 return vos::OThread::getCurrentIdentifier() == maMainThread
;
564 // -----------------------------------------------------------------------
566 void AquaSalInstance::handleAppDefinedEvent( NSEvent
* pEvent
)
568 switch( [pEvent subtype
] )
570 case AppStartTimerEvent
:
571 AquaSalTimer::handleStartTimerEvent( pEvent
);
573 case AppEndLoopEvent
:
576 case AppExecuteSVMain
:
578 BOOL bResult
= ImplSVMain();
590 case AppleRemoteEvent
:
592 sal_Int16 nCommand
= 0;
593 SalData
* pSalData
= GetSalData();
594 bool bIsFullScreenMode
= false;
596 std::list
<AquaSalFrame
*>::iterator it
= pSalData
->maFrames
.begin();
597 while( (*it
) && ( (it
!= pSalData
->maFrames
.end() ) || ( (*it
)->mbFullScreen
== false ) ) )
599 if ( ((*it
)->mbFullScreen
== true) )
600 bIsFullScreenMode
= true;
604 switch ([pEvent data1
])
606 case kRemoteButtonPlay
:
607 nCommand
= ( bIsFullScreenMode
== true ) ? MEDIA_COMMAND_PLAY_PAUSE
: MEDIA_COMMAND_PLAY
;
610 // kept for experimentation purpose (scheduled for future implementation)
611 // case kRemoteButtonMenu: nCommand = MEDIA_COMMAND_MENU; break;
613 case kRemoteButtonPlus
: nCommand
= MEDIA_COMMAND_VOLUME_UP
; break;
615 case kRemoteButtonMinus
: nCommand
= MEDIA_COMMAND_VOLUME_DOWN
; break;
617 case kRemoteButtonRight
: nCommand
= MEDIA_COMMAND_NEXTTRACK
; break;
619 case kRemoteButtonRight_Hold
: nCommand
= MEDIA_COMMAND_NEXTTRACK_HOLD
; break;
621 case kRemoteButtonLeft
: nCommand
= MEDIA_COMMAND_PREVIOUSTRACK
; break;
623 case kRemoteButtonLeft_Hold
: nCommand
= MEDIA_COMMAND_REWIND
; break;
625 case kRemoteButtonPlay_Hold
: nCommand
= MEDIA_COMMAND_PLAY_HOLD
; break;
627 case kRemoteButtonMenu_Hold
: nCommand
= MEDIA_COMMAND_STOP
; break;
629 // FIXME : not detected
630 case kRemoteButtonPlus_Hold
:
631 case kRemoteButtonMinus_Hold
:
637 AquaSalFrame
* pFrame
= pSalData
->maFrames
.front();
638 Window
* pWindow
= pFrame
->GetWindow() ? pSalData
->maFrames
.front()->GetWindow() : NULL
;
643 CommandEvent
aCEvt( aPoint
, COMMAND_MEDIA
, FALSE
, &nCommand
);
644 NotifyEvent
aNCmdEvt( EVENT_COMMAND
, pWindow
, &aCEvt
);
646 if ( !ImplCallPreNotify( aNCmdEvt
) )
647 pWindow
->Command( aCEvt
);
653 case YieldWakeupEvent
:
654 // do nothing, fall out of Yield
658 DBG_ERROR( "unhandled NSApplicationDefined event" );
663 // -----------------------------------------------------------------------
665 class ReleasePoolHolder
667 NSAutoreleasePool
* mpPool
;
669 ReleasePoolHolder() : mpPool( [[NSAutoreleasePool alloc
] init
] ) {}
670 ~ReleasePoolHolder() { [mpPool release
]; }
673 void AquaSalInstance::Yield( bool bWait
, bool bHandleAllCurrentEvents
)
675 // ensure that the per thread autorelease pool is top level and
676 // will therefore not be destroyed by cocoa implicitly
677 SalData::ensureThreadAutoreleasePool();
679 // NSAutoreleasePool documentation suggests we should have
680 // an own pool for each yield level
681 ReleasePoolHolder aReleasePool
;
683 // Release all locks so that we don't deadlock when we pull pending
684 // events from the event queue
685 bool bDispatchUser
= true;
686 while( bDispatchUser
)
688 ULONG nCount
= ReleaseYieldMutex();
690 // get one user event
691 osl_acquireMutex( maUserEventListMutex
);
692 SalUserEvent
aEvent( NULL
, NULL
, 0 );
693 if( ! maUserEvents
.empty() )
695 aEvent
= maUserEvents
.front();
696 maUserEvents
.pop_front();
699 bDispatchUser
= false;
700 osl_releaseMutex( maUserEventListMutex
);
702 AcquireYieldMutex( nCount
);
705 if( aEvent
.mpFrame
&& AquaSalFrame::isAlive( aEvent
.mpFrame
) )
707 aEvent
.mpFrame
->CallCallback( aEvent
.mnType
, aEvent
.mpData
);
708 // return if only one event is asked for
709 if( ! bHandleAllCurrentEvents
)
714 // handle cocoa event queue
715 // cocoa events mye be only handled in the thread the NSApp was created
716 if( isNSAppThread() && mnActivePrintJobs
== 0 )
718 // we need to be woken up by a cocoa-event
719 // if a user event should be posted by the event handling below
720 bool bOldWaitingYield
= mbWaitingYield
;
721 mbWaitingYield
= bWait
;
723 // handle available events
724 NSEvent
* pEvent
= nil
;
725 bool bHadEvent
= false;
728 ULONG nCount
= ReleaseYieldMutex();
730 pEvent
= [NSApp nextEventMatchingMask
: NSAnyEventMask untilDate
: nil
731 inMode
: NSDefaultRunLoopMode dequeue
: YES
];
734 [NSApp sendEvent
: pEvent
];
737 [NSApp updateWindows
];
739 AcquireYieldMutex( nCount
);
740 } while( bHandleAllCurrentEvents
&& pEvent
);
742 // if we had no event yet, wait for one if requested
743 if( bWait
&& ! bHadEvent
)
745 ULONG nCount
= ReleaseYieldMutex();
747 NSDate
* pDt
= AquaSalTimer::pRunningTimer
? [AquaSalTimer::pRunningTimer fireDate
] : [NSDate distantFuture
];
748 pEvent
= [NSApp nextEventMatchingMask
: NSAnyEventMask untilDate
: pDt
749 inMode
: NSDefaultRunLoopMode dequeue
: YES
];
751 [NSApp sendEvent
: pEvent
];
752 [NSApp updateWindows
];
754 AcquireYieldMutex( nCount
);
757 // FIXME: sometimes the NSTimer will never fire. Firing it by hand then
758 // fixes the problem even seems to set the correct next firing date
760 if( ! pEvent
&& AquaSalTimer::pRunningTimer
)
762 // this cause crashes on MacOSX 10.4
763 // [AquaSalTimer::pRunningTimer fire];
764 ImplGetSVData()->mpSalTimer
->CallCallback();
768 mbWaitingYield
= bOldWaitingYield
;
770 // collect update rectangles
771 const std::list
< AquaSalFrame
* > rFrames( GetSalData()->maFrames
);
772 for( std::list
< AquaSalFrame
* >::const_iterator it
= rFrames
.begin(); it
!= rFrames
.end(); ++it
)
774 if( (*it
)->mbShown
&& ! (*it
)->maInvalidRect
.IsEmpty() )
776 (*it
)->Flush( (*it
)->maInvalidRect
);
777 (*it
)->maInvalidRect
.SetEmpty();
782 // we get some apple events way too early
783 // before the application is ready to handle them,
784 // so their corresponding application events need to be delayed
785 // now is a good time to handle at least one of them
786 if( bWait
&& !aAppEventList
.empty() && ImplGetSVData()->maAppData
.mbInAppExecute
)
788 // make sure that only one application event is active at a time
789 static bool bInAppEvent
= false;
793 // get the next delayed application event
794 const ApplicationEvent
* pAppEvent
= aAppEventList
.front();
795 aAppEventList
.pop_front();
796 // handle one application event (no recursion)
797 const ImplSVData
* pSVData
= ImplGetSVData();
798 pSVData
->mpApp
->AppEvent( *pAppEvent
);
800 // allow the next delayed application event
806 // -----------------------------------------------------------------------
808 bool AquaSalInstance::AnyInput( USHORT nType
)
810 if( nType
& INPUT_APPEVENT
)
812 if( ! aAppEventList
.empty() )
814 if( nType
== INPUT_APPEVENT
)
818 if( nType
& INPUT_TIMER
)
820 if( AquaSalTimer::pRunningTimer
)
822 NSDate
* pDt
= [AquaSalTimer::pRunningTimer fireDate
];
823 if( pDt
&& [pDt timeIntervalSinceNow
] < 0 )
830 unsigned/*NSUInteger*/ nEventMask
= 0;
831 if( nType
& INPUT_MOUSE
)
833 NSLeftMouseDownMask
| NSRightMouseDownMask
| NSOtherMouseDownMask
|
834 NSLeftMouseUpMask
| NSRightMouseUpMask
| NSOtherMouseUpMask
|
835 NSLeftMouseDraggedMask
| NSRightMouseDraggedMask
| NSOtherMouseDraggedMask
|
837 // NSMouseMovedMask |
838 NSMouseEnteredMask
| NSMouseExitedMask
;
839 if( nType
& INPUT_KEYBOARD
)
840 nEventMask
|= NSKeyDownMask
| NSKeyUpMask
| NSFlagsChangedMask
;
841 if( nType
& INPUT_OTHER
)
842 nEventMask
|= NSTabletPoint
;
843 // TODO: INPUT_PAINT / more INPUT_OTHER
847 NSEvent
* pEvent
= [NSApp nextEventMatchingMask
: nEventMask untilDate
: nil
848 inMode
: NSDefaultRunLoopMode dequeue
: NO
];
849 return (pEvent
!= NULL
);
852 // -----------------------------------------------------------------------
854 SalFrame
* AquaSalInstance::CreateChildFrame( SystemParentData
* pSystemParentData
, ULONG nSalFrameStyle
)
859 // -----------------------------------------------------------------------
861 SalFrame
* AquaSalInstance::CreateFrame( SalFrame
* pParent
, ULONG nSalFrameStyle
)
863 SalData::ensureThreadAutoreleasePool();
865 SalFrame
* pFrame
= new AquaSalFrame( pParent
, nSalFrameStyle
);
869 // -----------------------------------------------------------------------
871 void AquaSalInstance::DestroyFrame( SalFrame
* pFrame
)
876 // -----------------------------------------------------------------------
878 SalObject
* AquaSalInstance::CreateObject( SalFrame
* pParent
, SystemWindowData
* /* pWindowData */, BOOL
/* bShow */ )
880 // SystemWindowData is meaningless on Mac OS X
881 AquaSalObject
*pObject
= NULL
;
884 pObject
= new AquaSalObject( static_cast<AquaSalFrame
*>(pParent
) );
889 // -----------------------------------------------------------------------
891 void AquaSalInstance::DestroyObject( SalObject
* pObject
)
896 // -----------------------------------------------------------------------
898 SalPrinter
* AquaSalInstance::CreatePrinter( SalInfoPrinter
* pInfoPrinter
)
900 return new AquaSalPrinter( dynamic_cast<AquaSalInfoPrinter
*>(pInfoPrinter
) );
903 // -----------------------------------------------------------------------
905 void AquaSalInstance::DestroyPrinter( SalPrinter
* pPrinter
)
910 // -----------------------------------------------------------------------
912 void AquaSalInstance::GetPrinterQueueInfo( ImplPrnQueueList
* pList
)
914 NSArray
* pNames
= [NSPrinter printerNames
];
915 NSArray
* pTypes
= [NSPrinter printerTypes
];
916 unsigned int nNameCount
= pNames
? [pNames count
] : 0;
917 unsigned int nTypeCount
= pTypes
? [pTypes count
] : 0;
918 DBG_ASSERT( nTypeCount
== nNameCount
, "type count not equal to printer count" );
919 for( unsigned int i
= 0; i
< nNameCount
; i
++ )
921 NSString
* pName
= [pNames objectAtIndex
: i
];
922 NSString
* pType
= i
< nTypeCount
? [pTypes objectAtIndex
: i
] : nil
;
925 SalPrinterQueueInfo
* pInfo
= new SalPrinterQueueInfo
;
926 pInfo
->maPrinterName
= GetOUString( pName
);
928 pInfo
->maDriver
= GetOUString( pType
);
931 pInfo
->mpSysData
= NULL
;
938 // -----------------------------------------------------------------------
940 void AquaSalInstance::GetPrinterQueueState( SalPrinterQueueInfo
* pInfo
)
944 // -----------------------------------------------------------------------
946 void AquaSalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo
* pInfo
)
951 // -----------------------------------------------------------------------
953 XubString
AquaSalInstance::GetDefaultPrinter()
955 if( ! maDefaultPrinter
.getLength() )
957 NSPrintInfo
* pPI
= [NSPrintInfo sharedPrintInfo
];
958 DBG_ASSERT( pPI
, "no print info" );
961 NSPrinter
* pPr
= [pPI printer
];
962 DBG_ASSERT( pPr
, "no printer in default info" );
965 NSString
* pDefName
= [pPr name
];
966 DBG_ASSERT( pDefName
, "printer has no name" );
967 maDefaultPrinter
= GetOUString( pDefName
);
971 return maDefaultPrinter
;
974 // -----------------------------------------------------------------------
976 SalInfoPrinter
* AquaSalInstance::CreateInfoPrinter( SalPrinterQueueInfo
* pQueueInfo
,
977 ImplJobSetup
* pSetupData
)
979 SalInfoPrinter
* pNewInfoPrinter
= NULL
;
982 pNewInfoPrinter
= new AquaSalInfoPrinter( *pQueueInfo
);
984 pNewInfoPrinter
->SetPrinterData( pSetupData
);
987 return pNewInfoPrinter
;
990 // -----------------------------------------------------------------------
992 void AquaSalInstance::DestroyInfoPrinter( SalInfoPrinter
* pPrinter
)
997 // -----------------------------------------------------------------------
999 SalSystem
* AquaSalInstance::CreateSystem()
1001 return new AquaSalSystem();
1004 // -----------------------------------------------------------------------
1006 void AquaSalInstance::DestroySystem( SalSystem
* pSystem
)
1011 // -----------------------------------------------------------------------
1013 void AquaSalInstance::SetEventCallback( void* pInstance
, bool(*pCallback
)(void*,void*,int) )
1017 // -----------------------------------------------------------------------
1019 void AquaSalInstance::SetErrorEventCallback( void* pInstance
, bool(*pCallback
)(void*,void*,int) )
1023 // -----------------------------------------------------------------------
1025 void* AquaSalInstance::GetConnectionIdentifier( ConnectionIdentifierType
& rReturnedType
, int& rReturnedBytes
)
1028 rReturnedType
= AsciiCString
;
1032 // -----------------------------------------------------------------------
1034 SalTimer
* AquaSalInstance::CreateSalTimer()
1036 return new AquaSalTimer();
1039 // -----------------------------------------------------------------------
1041 SalSystem
* AquaSalInstance::CreateSalSystem()
1043 return new AquaSalSystem();
1046 // -----------------------------------------------------------------------
1048 SalBitmap
* AquaSalInstance::CreateSalBitmap()
1050 return new AquaSalBitmap();
1053 // -----------------------------------------------------------------------
1055 SalSession
* AquaSalInstance::CreateSalSession()
1060 // -----------------------------------------------------------------------
1062 class MacImeStatus
: public SalI18NImeStatus
1066 virtual ~MacImeStatus() {}
1068 // asks whether there is a status window available
1069 // to toggle into menubar
1070 virtual bool canToggle() { return false; }
1071 virtual void toggle() {}
1074 // -----------------------------------------------------------------------
1076 SalI18NImeStatus
* AquaSalInstance::CreateI18NImeStatus()
1078 return new MacImeStatus();
1081 // YieldMutexReleaser
1082 YieldMutexReleaser::YieldMutexReleaser() : mnCount( 0 )
1084 SalData
* pSalData
= GetSalData();
1085 if( ! pSalData
->mpFirstInstance
->isNSAppThread() )
1087 SalData::ensureThreadAutoreleasePool();
1088 mnCount
= pSalData
->mpFirstInstance
->ReleaseYieldMutex();
1092 YieldMutexReleaser::~YieldMutexReleaser()
1095 GetSalData()->mpFirstInstance
->AcquireYieldMutex( mnCount
);
1098 //////////////////////////////////////////////////////////////
1099 rtl::OUString
GetOUString( CFStringRef rStr
)
1102 return rtl::OUString();
1103 CFIndex nLength
= CFStringGetLength( rStr
);
1105 return rtl::OUString();
1106 const UniChar
* pConstStr
= CFStringGetCharactersPtr( rStr
);
1108 return rtl::OUString( pConstStr
, nLength
);
1109 UniChar
* pStr
= reinterpret_cast<UniChar
*>( rtl_allocateMemory( sizeof(UniChar
)*nLength
) );
1110 CFRange aRange
= { 0, nLength
};
1111 CFStringGetCharacters( rStr
, aRange
, pStr
);
1112 rtl::OUString
aRet( pStr
, nLength
);
1113 rtl_freeMemory( pStr
);
1117 rtl::OUString
GetOUString( NSString
* pStr
)
1120 return rtl::OUString();
1121 int nLen
= [pStr length
];
1123 return rtl::OUString();
1125 rtl::OUStringBuffer
aBuf( nLen
+1 );
1126 aBuf
.setLength( nLen
);
1127 [pStr getCharacters
: const_cast<sal_Unicode
*>(aBuf
.getStr())];
1128 return aBuf
.makeStringAndClear();
1131 CFStringRef
CreateCFString( const rtl::OUString
& rStr
)
1133 return CFStringCreateWithCharacters(kCFAllocatorDefault
, rStr
.getStr(), rStr
.getLength() );
1136 NSString
* CreateNSString( const rtl::OUString
& rStr
)
1138 return [[NSString alloc
] initWithCharacters
: rStr
.getStr() length
: rStr
.getLength()];
1141 CGImageRef
CreateCGImage( const Image
& rImage
)
1143 BitmapEx
aBmpEx( rImage
.GetBitmapEx() );
1144 Bitmap
aBmp( aBmpEx
.GetBitmap() );
1146 if( ! aBmp
|| ! aBmp
.ImplGetImpBitmap() )
1149 // simple case, no transparency
1150 AquaSalBitmap
* pSalBmp
= static_cast<AquaSalBitmap
*>(aBmp
.ImplGetImpBitmap()->ImplGetSalBitmap());
1155 CGImageRef xImage
= NULL
;
1156 if( ! (aBmpEx
.IsAlpha() || aBmpEx
.IsTransparent() ) )
1157 xImage
= pSalBmp
->CreateCroppedImage( 0, 0, pSalBmp
->mnWidth
, pSalBmp
->mnHeight
);
1158 else if( aBmpEx
.IsAlpha() )
1160 AlphaMask
aAlphaMask( aBmpEx
.GetAlpha() );
1161 Bitmap
aMask( aAlphaMask
.GetBitmap() );
1162 AquaSalBitmap
* pMaskBmp
= static_cast<AquaSalBitmap
*>(aMask
.ImplGetImpBitmap()->ImplGetSalBitmap());
1164 xImage
= pSalBmp
->CreateWithMask( *pMaskBmp
, 0, 0, pSalBmp
->mnWidth
, pSalBmp
->mnHeight
);
1166 xImage
= pSalBmp
->CreateCroppedImage( 0, 0, pSalBmp
->mnWidth
, pSalBmp
->mnHeight
);
1168 else if( aBmpEx
.GetTransparentType() == TRANSPARENT_BITMAP
)
1170 Bitmap
aMask( aBmpEx
.GetMask() );
1171 AquaSalBitmap
* pMaskBmp
= static_cast<AquaSalBitmap
*>(aMask
.ImplGetImpBitmap()->ImplGetSalBitmap());
1173 xImage
= pSalBmp
->CreateWithMask( *pMaskBmp
, 0, 0, pSalBmp
->mnWidth
, pSalBmp
->mnHeight
);
1175 xImage
= pSalBmp
->CreateCroppedImage( 0, 0, pSalBmp
->mnWidth
, pSalBmp
->mnHeight
);
1177 else if( aBmpEx
.GetTransparentType() == TRANSPARENT_COLOR
)
1179 Color
aTransColor( aBmpEx
.GetTransparentColor() );
1180 SalColor nTransColor
= MAKE_SALCOLOR( aTransColor
.GetRed(), aTransColor
.GetGreen(), aTransColor
.GetBlue() );
1181 xImage
= pSalBmp
->CreateColorMask( 0, 0, pSalBmp
->mnWidth
, pSalBmp
->mnHeight
, nTransColor
);
1187 NSImage
* CreateNSImage( const Image
& rImage
)
1189 CGImageRef xImage
= CreateCGImage( rImage
);
1194 Size
aSize( rImage
.GetSizePixel() );
1195 NSImage
* pImage
= [[NSImage alloc
] initWithSize
: NSMakeSize( aSize
.Width(), aSize
.Height() )];
1198 [pImage setFlipped
: YES
];
1201 NSGraphicsContext
* pContext
= [NSGraphicsContext currentContext
];
1202 CGContextRef rCGContext
= reinterpret_cast<CGContextRef
>([pContext graphicsPort
]);
1204 const CGRect aDstRect
= { {0, 0}, { aSize
.Width(), aSize
.Height() } };
1205 CGContextDrawImage( rCGContext
, aDstRect
, xImage
);
1207 [pImage unlockFocus
];
1210 CGImageRelease( xImage
);