update dev300-m58
[ooovba.git] / vcl / aqua / source / window / salframe.cxx
blobff635ffd82b39a235fdb55ab46b41cec0e67f3f5
1 /************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salframe.cxx,v $
10 * $Revision: 1.69 $
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"
34 #include <string>
36 #include "saldata.hxx"
37 #include "salgdi.h"
38 #include "salframe.h"
39 #include "salmenu.h"
40 #include "saltimer.h"
41 #include "salinst.h"
42 #include "salframeview.h"
43 #include "aqua11yfactory.h"
44 #include "vcl/salwtype.hxx"
45 #include "vcl/window.hxx"
46 #include "vcl/timer.hxx"
48 #include "premac.h"
49 // needed for theming
50 // FIXME: move theming code to salnativewidgets.cxx
51 #include <Carbon/Carbon.h>
52 #include "postmac.h"
54 #include "boost/assert.hpp"
55 #include "vcl/svapp.hxx"
56 #include "rtl/ustrbuf.hxx"
58 #include <premac.h>
59 #include <CoreFoundation/CoreFoundation.h>
60 #include <postmac.h>
62 using namespace std;
64 // =======================================================================
66 AquaSalFrame* AquaSalFrame::s_pCaptureFrame = NULL;
68 // =======================================================================
70 AquaSalFrame::AquaSalFrame( SalFrame* pParent, ULONG salFrameStyle ) :
71 mpWindow(nil),
72 mpView(nil),
73 mpDockMenuEntry(nil),
74 mpGraphics(NULL),
75 mpParent(NULL),
76 mnMinWidth(0),
77 mnMinHeight(0),
78 mnMaxWidth(0),
79 mnMaxHeight(0),
80 mbGraphics(false),
81 mbFullScreen( false ),
82 mbShown(false),
83 mbInitShow(true),
84 mbPositioned(false),
85 mbSized(false),
86 mbPresentation( false ),
87 mnStyle( salFrameStyle ),
88 mnStyleMask( 0 ),
89 mnLastEventTime( 0 ),
90 mnLastModifierFlags( 0 ),
91 mpMenu( NULL ),
92 mnExtStyle( 0 ),
93 mePointerStyle( POINTER_ARROW ),
94 mnTrackingRectTag( 0 ),
95 mrClippingPath( 0 ),
96 mnICOptions( 0 )
98 maSysData.nSize = sizeof( SystemEnvData );
100 mpParent = dynamic_cast<AquaSalFrame*>(pParent);
102 initWindowAndView();
104 SalData* pSalData = GetSalData();
105 pSalData->maFrames.push_front( this );
106 pSalData->maFrameCheck.insert( this );
109 // -----------------------------------------------------------------------
111 AquaSalFrame::~AquaSalFrame()
113 // if the frame is destroyed and has the current menubar
114 // set the default menubar
115 if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu )
116 AquaSalMenu::setDefaultMenu();
118 // cleanup clipping stuff
119 ResetClipRegion();
121 [SalFrameView unsetMouseFrame: this];
123 SalData* pSalData = GetSalData();
124 pSalData->maFrames.remove( this );
125 pSalData->maFrameCheck.erase( this );
127 DBG_ASSERT( this != s_pCaptureFrame, "capture frame destroyed" );
128 if( this == s_pCaptureFrame )
129 s_pCaptureFrame = NULL;
131 if ( mpGraphics )
132 delete mpGraphics;
134 if( mpDockMenuEntry )
135 // life cycle comment: the menu has ownership of the item, so no release
136 [AquaSalInstance::GetDynamicDockMenu() removeItem: mpDockMenuEntry];
137 if ( mpView ) {
138 [AquaA11yFactory revokeView: mpView];
139 [mpView release];
141 if ( mpWindow )
142 [mpWindow release];
145 // -----------------------------------------------------------------------
147 void AquaSalFrame::initWindowAndView()
149 // initialize mirroring parameters
150 // FIXME: screens changing
151 NSScreen * pScreen = [mpWindow screen];
152 if( pScreen == nil )
153 pScreen = [NSScreen mainScreen];
154 maScreenRect = [pScreen frame];
156 // calculate some default geometry
157 NSRect aVisibleRect = [pScreen visibleFrame];
158 CocoaToVCL( aVisibleRect );
160 maGeometry.nX = static_cast<int>(aVisibleRect.origin.x + aVisibleRect.size.width / 10);
161 maGeometry.nY = static_cast<int>(aVisibleRect.origin.y + aVisibleRect.size.height / 10);
162 maGeometry.nWidth = static_cast<unsigned int>(aVisibleRect.size.width * 0.8);
163 maGeometry.nHeight = static_cast<unsigned int>(aVisibleRect.size.height * 0.8);
165 // calculate style mask
166 if( (mnStyle & SAL_FRAME_STYLE_FLOAT) ||
167 (mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
168 mnStyleMask = NSBorderlessWindowMask;
169 else if( mnStyle & SAL_FRAME_STYLE_DEFAULT )
171 mnStyleMask = NSTitledWindowMask |
172 NSMiniaturizableWindowMask |
173 NSResizableWindowMask |
174 NSClosableWindowMask;
175 // make default window "maximized"
176 maGeometry.nX = static_cast<int>(aVisibleRect.origin.x);
177 maGeometry.nY = static_cast<int>(aVisibleRect.origin.y);
178 maGeometry.nWidth = static_cast<int>(aVisibleRect.size.width);
179 maGeometry.nHeight = static_cast<int>(aVisibleRect.size.height);
180 mbPositioned = mbSized = true;
182 else
184 if( (mnStyle & SAL_FRAME_STYLE_MOVEABLE) )
186 mnStyleMask |= NSTitledWindowMask;
187 if( mpParent == NULL )
188 mnStyleMask |= NSMiniaturizableWindowMask;
190 if( (mnStyle & SAL_FRAME_STYLE_SIZEABLE) )
191 mnStyleMask |= NSResizableWindowMask;
192 if( (mnStyle & SAL_FRAME_STYLE_CLOSEABLE) )
193 mnStyleMask |= NSClosableWindowMask;
194 // documentation says anything other than NSBorderlessWindowMask (=0)
195 // should also include NSTitledWindowMask;
196 if( mnStyleMask != 0 )
197 mnStyleMask |= NSTitledWindowMask;
200 mpWindow = [[SalFrameWindow alloc] initWithSalFrame: this];
201 mpView = [[SalFrameView alloc] initWithSalFrame: this];
202 if( (mnStyle & SAL_FRAME_STYLE_TOOLTIP) )
203 [mpWindow setIgnoresMouseEvents: YES];
204 else
205 [mpWindow setAcceptsMouseMovedEvents: YES];
206 [mpWindow setHasShadow: YES];
207 [mpWindow setDelegate: mpWindow];
209 NSRect aRect = { { 0,0 }, { maGeometry.nWidth, maGeometry.nHeight } };
210 mnTrackingRectTag = [mpView addTrackingRect: aRect owner: mpView userData: nil assumeInside: NO];
212 maSysData.pView = mpView;
214 UpdateFrameGeometry();
216 // setContentView causes a display; in multithreaded use this can deadlock
217 //YieldMutexReleaser aRel;
218 [mpWindow setContentView: mpView];
221 // -----------------------------------------------------------------------
223 void AquaSalFrame::CocoaToVCL( NSRect& io_rRect, bool bRelativeToScreen )
225 if( bRelativeToScreen )
226 io_rRect.origin.y = maScreenRect.size.height - (io_rRect.origin.y+io_rRect.size.height);
227 else
228 io_rRect.origin.y = maGeometry.nHeight - (io_rRect.origin.y+io_rRect.size.height);
231 void AquaSalFrame::VCLToCocoa( NSRect& io_rRect, bool bRelativeToScreen )
233 if( bRelativeToScreen )
234 io_rRect.origin.y = maScreenRect.size.height - (io_rRect.origin.y+io_rRect.size.height);
235 else
236 io_rRect.origin.y = maGeometry.nHeight - (io_rRect.origin.y+io_rRect.size.height);
239 void AquaSalFrame::CocoaToVCL( NSPoint& io_rPoint, bool bRelativeToScreen )
241 if( bRelativeToScreen )
242 io_rPoint.y = maScreenRect.size.height - io_rPoint.y;
243 else
244 io_rPoint.y = maGeometry.nHeight - io_rPoint.y;
247 void AquaSalFrame::VCLToCocoa( NSPoint& io_rPoint, bool bRelativeToScreen )
249 if( bRelativeToScreen )
250 io_rPoint.y = maScreenRect.size.height - io_rPoint.y;
251 else
252 io_rPoint.y = maGeometry.nHeight - io_rPoint.y;
255 // -----------------------------------------------------------------------
257 void AquaSalFrame::screenParametersChanged()
259 UpdateFrameGeometry();
261 if( mpGraphics )
262 mpGraphics->updateResolution();
263 CallCallback( SALEVENT_DISPLAYCHANGED, 0 );
266 // -----------------------------------------------------------------------
268 SalGraphics* AquaSalFrame::GetGraphics()
270 if ( mbGraphics )
271 return NULL;
273 if ( !mpGraphics )
275 mpGraphics = new AquaSalGraphics;
276 mpGraphics->SetWindowGraphics( this );
279 mbGraphics = TRUE;
280 return mpGraphics;
283 // -----------------------------------------------------------------------
285 void AquaSalFrame::ReleaseGraphics( SalGraphics *pGraphics )
287 DBG_ASSERT( pGraphics == mpGraphics, "graphics released on wrong frame" );
288 mbGraphics = FALSE;
291 // -----------------------------------------------------------------------
293 BOOL AquaSalFrame::PostEvent( void *pData )
295 GetSalData()->mpFirstInstance->PostUserEvent( this, SALEVENT_USEREVENT, pData );
296 return TRUE;
299 // -----------------------------------------------------------------------
300 void AquaSalFrame::SetTitle(const XubString& rTitle)
302 NSString* pTitle = CreateNSString( rTitle );
303 [mpWindow setTitle: pTitle];
305 // create an entry in the dock menu
306 const ULONG nAppWindowStyle = (SAL_FRAME_STYLE_CLOSEABLE | SAL_FRAME_STYLE_MOVEABLE);
307 if( mpParent == NULL &&
308 (mnStyle & nAppWindowStyle) == nAppWindowStyle )
310 if( mpDockMenuEntry == NULL )
312 NSMenu* pDock = AquaSalInstance::GetDynamicDockMenu();
313 mpDockMenuEntry = [pDock insertItemWithTitle: pTitle
314 action: @selector(dockMenuItemTriggered:)
315 keyEquivalent: @""
316 atIndex: 0];
317 [mpDockMenuEntry setTarget: mpWindow];
319 // TODO: image (either the generic window image or an icon
320 // check mark (for "main" window ?)
322 else
323 [mpDockMenuEntry setTitle: pTitle];
326 if (pTitle)
327 [pTitle release];
330 // -----------------------------------------------------------------------
332 void AquaSalFrame::SetIcon( USHORT nIcon )
336 // -----------------------------------------------------------------------
338 void AquaSalFrame::initShow()
340 mbInitShow = false;
341 if( ! mbPositioned && ! mbFullScreen )
343 Rectangle aScreenRect;
344 GetWorkArea( aScreenRect );
345 if( mpParent ) // center relative to parent
347 // center on parent
348 long nNewX = mpParent->maGeometry.nX + (mpParent->maGeometry.nWidth - maGeometry.nWidth)/2;
349 if( nNewX < aScreenRect.Left() )
350 nNewX = aScreenRect.Left();
351 if( long(nNewX + maGeometry.nWidth) > aScreenRect.Right() )
352 nNewX = aScreenRect.Right() - maGeometry.nWidth-1;
353 long nNewY = mpParent->maGeometry.nY + (mpParent->maGeometry.nHeight - maGeometry.nHeight)/2;
354 if( nNewY < aScreenRect.Top() )
355 nNewY = aScreenRect.Top();
356 if( nNewY > aScreenRect.Bottom() )
357 nNewY = aScreenRect.Bottom() - maGeometry.nHeight-1;
358 SetPosSize( nNewX - mpParent->maGeometry.nX,
359 nNewY - mpParent->maGeometry.nY,
360 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y );
362 else if( ! (mnStyle & SAL_FRAME_STYLE_SIZEABLE) )
364 // center on screen
365 long nNewX = (aScreenRect.GetWidth() - maGeometry.nWidth)/2;
366 long nNewY = (aScreenRect.GetHeight() - maGeometry.nHeight)/2;
367 SetPosSize( nNewX, nNewY, 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y );
371 // make sure the view is present in the wrapper list before any children receive focus
372 [AquaA11yFactory registerView: mpView];
375 void AquaSalFrame::SendPaintEvent( const Rectangle* pRect )
377 SalPaintEvent aPaintEvt( 0, 0, maGeometry.nWidth, maGeometry.nHeight, true );
378 if( pRect )
380 aPaintEvt.mnBoundX = pRect->Left();
381 aPaintEvt.mnBoundY = pRect->Top();
382 aPaintEvt.mnBoundWidth = pRect->GetWidth();
383 aPaintEvt.mnBoundHeight = pRect->GetHeight();
386 CallCallback(SALEVENT_PAINT, &aPaintEvt);
389 // -----------------------------------------------------------------------
391 void AquaSalFrame::Show(BOOL bVisible, BOOL bNoActivate)
393 mbShown = bVisible;
394 if(bVisible)
396 if( mbInitShow )
397 initShow();
399 CallCallback(SALEVENT_RESIZE, 0);
400 // trigger filling our backbuffer
401 SendPaintEvent();
403 //YieldMutexReleaser aRel;
405 if( bNoActivate || [mpWindow canBecomeKeyWindow] == NO )
406 [mpWindow orderFront: NSApp];
407 else
408 [mpWindow makeKeyAndOrderFront: NSApp];
410 if( mpParent )
412 /* #i92674# #i96433# we do not want an invisible parent to show up (which adding a visible
413 child implicitly does). However we also do not want a parentless toolbar.
415 HACK: try to decide when we should not insert a child to its parent
416 floaters and ownerdraw windows have not yet shown up in cases where
417 we don't want the parent to become visible
419 if( mpParent->mbShown || (mnStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION | SAL_FRAME_STYLE_FLOAT) ) )
421 [mpParent->mpWindow addChildWindow: mpWindow ordered: NSWindowAbove];
425 if( mbPresentation )
426 [mpWindow makeMainWindow];
428 else
430 // if the frame holding the current menubar gets hidden
431 // show the default menubar
432 if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu )
433 AquaSalMenu::setDefaultMenu();
435 //YieldMutexReleaser aRel;
437 // #i90440# #i94443# work around the focus going back to some other window
438 // if a child gets hidden for a parent window
439 if( mpParent && mpParent->mbShown && [mpWindow isKeyWindow] )
440 [mpParent->mpWindow makeKeyAndOrderFront: NSApp];
442 [SalFrameView unsetMouseFrame: this];
443 if( mpParent && [mpWindow parentWindow] == mpParent->mpWindow )
444 [mpParent->mpWindow removeChildWindow: mpWindow];
446 [mpWindow orderOut: NSApp];
450 // -----------------------------------------------------------------------
452 void AquaSalFrame::Enable( BOOL bEnable )
456 // -----------------------------------------------------------------------
458 void AquaSalFrame::SetMinClientSize( long nWidth, long nHeight )
460 mnMinWidth = nWidth;
461 mnMinHeight = nHeight;
463 if( mpWindow )
465 // Always add the decoration as the dimension concerns only
466 // the content rectangle
467 nWidth += maGeometry.nLeftDecoration + maGeometry.nRightDecoration;
468 nHeight += maGeometry.nTopDecoration + maGeometry.nBottomDecoration;
470 NSSize aSize = { nWidth, nHeight };
472 // Size of full window (content+structure) although we only
473 // have the client size in arguments
474 [mpWindow setMinSize: aSize];
478 // -----------------------------------------------------------------------
480 void AquaSalFrame::SetMaxClientSize( long nWidth, long nHeight )
482 mnMaxWidth = nWidth;
483 mnMaxHeight = nHeight;
485 if( mpWindow )
487 // Always add the decoration as the dimension concerns only
488 // the content rectangle
489 nWidth += maGeometry.nLeftDecoration + maGeometry.nRightDecoration;
490 nHeight += maGeometry.nTopDecoration + maGeometry.nBottomDecoration;
492 // Carbon windows can't have a size greater than 32767x32767
493 if (nWidth>32767) nWidth=32767;
494 if (nHeight>32767) nHeight=32767;
496 NSSize aSize = { nWidth, nHeight };
498 // Size of full window (content+structure) although we only
499 // have the client size in arguments
500 [mpWindow setMaxSize: aSize];
504 // -----------------------------------------------------------------------
506 void AquaSalFrame::SetClientSize( long nWidth, long nHeight )
508 if( mpWindow )
510 NSSize aSize = { nWidth, nHeight };
512 [mpWindow setContentSize: aSize];
513 UpdateFrameGeometry();
514 if( mbShown )
515 // trigger filling our backbuffer
516 SendPaintEvent();
520 // -----------------------------------------------------------------------
522 void AquaSalFrame::GetClientSize( long& rWidth, long& rHeight )
524 if( mbShown || mbInitShow )
526 rWidth = maGeometry.nWidth;
527 rHeight = maGeometry.nHeight;
529 else
531 rWidth = 0;
532 rHeight = 0;
536 // -----------------------------------------------------------------------
538 void AquaSalFrame::SetWindowState( const SalFrameState* pState )
540 // set normal state
541 NSRect aStateRect = [mpWindow frame];
542 aStateRect = [NSWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask];
543 CocoaToVCL( aStateRect );
544 if( pState->mnMask & SAL_FRAMESTATE_MASK_X )
545 aStateRect.origin.x = float(pState->mnX);
546 if( pState->mnMask & SAL_FRAMESTATE_MASK_Y )
547 aStateRect.origin.y = float(pState->mnY);
548 if( pState->mnMask & SAL_FRAMESTATE_MASK_WIDTH )
549 aStateRect.size.width = float(pState->mnWidth);
550 if( pState->mnMask & SAL_FRAMESTATE_MASK_HEIGHT )
551 aStateRect.size.height = float(pState->mnHeight);
552 VCLToCocoa( aStateRect );
553 aStateRect = [NSWindow frameRectForContentRect: aStateRect styleMask: mnStyleMask];
555 // relase and acquire mutex again since this call can block waiting for an internal lock
557 //YieldMutexReleaser aRel;
558 [mpWindow setFrame: aStateRect display: NO];
561 // FIXME: HTH maximized state ?
563 // get new geometry
564 UpdateFrameGeometry();
566 USHORT nEvent = 0;
567 if( pState->mnMask & (SAL_FRAMESTATE_MASK_X | SAL_FRAMESTATE_MASK_X) )
569 mbPositioned = true;
570 nEvent = SALEVENT_MOVE;
573 if( pState->mnMask & (SAL_FRAMESTATE_MASK_WIDTH | SAL_FRAMESTATE_MASK_HEIGHT) )
575 mbSized = true;
576 nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE;
578 // send event that we were moved/sized
579 if( nEvent )
580 CallCallback( nEvent, NULL );
582 if( mbShown )
584 // trigger filling our backbuffer
585 SendPaintEvent();
587 // tell the system the views need to be updated
588 //YieldMutexReleaser aRel;
590 [mpWindow display];
594 // -----------------------------------------------------------------------
596 BOOL AquaSalFrame::GetWindowState( SalFrameState* pState )
598 pState->mnMask = SAL_FRAMESTATE_MASK_X |
599 SAL_FRAMESTATE_MASK_Y |
600 SAL_FRAMESTATE_MASK_WIDTH |
601 SAL_FRAMESTATE_MASK_HEIGHT |
602 #if 0
603 SAL_FRAMESTATE_MASK_MAXIMIZED_X |
604 SAL_FRAMESTATE_MASK_MAXIMIZED_Y |
605 SAL_FRAMESTATE_MASK_MAXIMIZED_WIDTH |
606 SAL_FRAMESTATE_MASK_MAXIMIZED_HEIGHT |
607 #endif
608 SAL_FRAMESTATE_MASK_STATE;
610 NSRect aStateRect = [mpWindow frame];
611 aStateRect = [NSWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask];
612 CocoaToVCL( aStateRect );
613 pState->mnX = long(aStateRect.origin.x);
614 pState->mnY = long(aStateRect.origin.y);
615 pState->mnWidth = long(aStateRect.size.width);
616 pState->mnHeight = long(aStateRect.size.height);
618 // FIXME: HTH maximized state ?
620 if( [mpWindow isMiniaturized] )
621 pState->mnState = SAL_FRAMESTATE_MINIMIZED;
622 else if( ! [mpWindow isZoomed] )
623 pState->mnState = SAL_FRAMESTATE_NORMAL;
624 else
625 pState->mnState = SAL_FRAMESTATE_MAXIMIZED;
627 return TRUE;
630 // -----------------------------------------------------------------------
632 void AquaSalFrame::SetScreenNumber(unsigned int nScreen)
634 NSArray* pScreens = [NSScreen screens];
635 Rectangle aRet;
636 NSScreen* pScreen = nil;
637 if( pScreens && nScreen < [pScreens count] )
639 // get new screen frame
640 pScreen = [pScreens objectAtIndex: nScreen];
641 NSRect aNewScreen = [pScreen frame];
643 // get current screen frame
644 pScreen = [mpWindow screen];
645 if( pScreen )
647 NSRect aCurScreen = [pScreen frame];
648 if( aCurScreen.origin.x != aNewScreen.origin.x ||
649 aCurScreen.origin.y != aNewScreen.origin.y )
651 NSRect aFrameRect = [mpWindow frame];
652 aFrameRect.origin.x += aNewScreen.origin.x - aCurScreen.origin.x;
653 aFrameRect.origin.y += aNewScreen.origin.y - aCurScreen.origin.y;
654 [mpWindow setFrame: aFrameRect display: NO];
655 UpdateFrameGeometry();
661 // -----------------------------------------------------------------------
663 void AquaSalFrame::ShowFullScreen( BOOL bFullScreen, sal_Int32 nDisplay )
665 if( mbFullScreen == bFullScreen )
666 return;
668 mbFullScreen = bFullScreen;
669 if( bFullScreen )
671 // hide the dock and the menubar if we are on the menu screen
672 // which is always on index 0 according to documentation
673 bool bHideMenu = (nDisplay == 0);
675 NSRect aNewContentRect = { { 0, 0 }, { 0, 0 } };
676 // get correct screen
677 NSScreen* pScreen = nil;
678 NSArray* pScreens = [NSScreen screens];
679 if( pScreens )
681 if( nDisplay >= 0 && (unsigned int)nDisplay < [pScreens count] )
682 pScreen = [pScreens objectAtIndex: nDisplay];
683 else
685 // this means span all screens
686 bHideMenu = true;
687 NSEnumerator* pEnum = [pScreens objectEnumerator];
688 while( (pScreen = [pEnum nextObject]) != nil )
690 NSRect aScreenRect = [pScreen frame];
691 if( aScreenRect.origin.x < aNewContentRect.origin.x )
693 aNewContentRect.size.width += aNewContentRect.origin.x - aScreenRect.origin.x;
694 aNewContentRect.origin.x = aScreenRect.origin.x;
696 if( aScreenRect.origin.y < aNewContentRect.origin.y )
698 aNewContentRect.size.height += aNewContentRect.origin.y - aScreenRect.origin.y;
699 aNewContentRect.origin.y = aScreenRect.origin.y;
701 if( aScreenRect.origin.x + aScreenRect.size.width > aNewContentRect.origin.x + aNewContentRect.size.width )
702 aNewContentRect.size.width = aScreenRect.origin.x + aScreenRect.size.width - aNewContentRect.origin.x;
703 if( aScreenRect.origin.y + aScreenRect.size.height > aNewContentRect.origin.y + aNewContentRect.size.height )
704 aNewContentRect.size.height = aScreenRect.origin.y + aScreenRect.size.height - aNewContentRect.origin.y;
708 if( aNewContentRect.size.width == 0 && aNewContentRect.size.height == 0 )
710 if( pScreen == nil )
711 pScreen = [mpWindow screen];
712 if( pScreen == nil )
713 pScreen = [NSScreen mainScreen];
715 aNewContentRect = [pScreen frame];
718 if( bHideMenu )
719 [NSMenu setMenuBarVisible:NO];
721 maFullScreenRect = [mpWindow frame];
723 //YieldMutexReleaser aRel;
724 [mpWindow setFrame: [NSWindow frameRectForContentRect: aNewContentRect styleMask: mnStyleMask] display: mbShown ? YES : NO];
727 UpdateFrameGeometry();
729 if( mbShown )
730 CallCallback( SALEVENT_MOVERESIZE, NULL );
732 else
735 //YieldMutexReleaser aRel;
736 [mpWindow setFrame: maFullScreenRect display: mbShown ? YES : NO];
738 UpdateFrameGeometry();
740 if( mbShown )
741 CallCallback( SALEVENT_MOVERESIZE, NULL );
743 // show the dock and the menubar
744 [NSMenu setMenuBarVisible:YES];
746 if( mbShown )
747 // trigger filling our backbuffer
748 SendPaintEvent();
751 // -----------------------------------------------------------------------
753 class PreventSleepTimer : public AutoTimer
755 public:
756 PreventSleepTimer()
758 SetTimeout( 30000 );
759 Start();
762 virtual ~PreventSleepTimer()
766 virtual void Timeout()
768 UpdateSystemActivity(OverallAct);
772 void AquaSalFrame::StartPresentation( BOOL bStart )
774 if( bStart )
776 mpActivityTimer.reset( new PreventSleepTimer() );
777 [mpWindow setLevel: NSScreenSaverWindowLevel];
778 if( mbShown )
779 [mpWindow makeMainWindow];
781 else
783 mpActivityTimer.reset();
784 [mpWindow setLevel: NSNormalWindowLevel];
788 // -----------------------------------------------------------------------
790 void AquaSalFrame::SetAlwaysOnTop( BOOL bOnTop )
794 // -----------------------------------------------------------------------
796 void AquaSalFrame::ToTop(USHORT nFlags)
798 if( ! (nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN) )
800 if( ! [mpWindow isVisible] || [mpWindow isMiniaturized] )
801 return;
803 if( nFlags & SAL_FRAME_TOTOP_GRABFOCUS )
804 [mpWindow makeKeyAndOrderFront: NSApp];
805 else
806 [mpWindow orderFront: NSApp];
809 // -----------------------------------------------------------------------
811 NSCursor* AquaSalFrame::getCurrentCursor() const
813 NSCursor* pCursor = nil;
814 switch( mePointerStyle )
816 case POINTER_TEXT: pCursor = [NSCursor IBeamCursor]; break;
817 case POINTER_CROSS: pCursor = [NSCursor crosshairCursor]; break;
818 case POINTER_HAND:
819 case POINTER_MOVE: pCursor = [NSCursor openHandCursor]; break;
820 case POINTER_NSIZE: pCursor = [NSCursor resizeUpCursor]; break;
821 case POINTER_SSIZE: pCursor = [NSCursor resizeDownCursor]; break;
822 case POINTER_ESIZE: pCursor = [NSCursor resizeRightCursor]; break;
823 case POINTER_WSIZE: pCursor = [NSCursor resizeLeftCursor]; break;
824 case POINTER_ARROW: pCursor = [NSCursor arrowCursor]; break;
825 case POINTER_VSPLIT:
826 case POINTER_VSIZEBAR:
827 case POINTER_WINDOW_NSIZE:
828 case POINTER_WINDOW_SSIZE:
829 pCursor = [NSCursor resizeUpDownCursor]; break;
830 case POINTER_HSPLIT:
831 case POINTER_HSIZEBAR:
832 case POINTER_WINDOW_ESIZE:
833 case POINTER_WINDOW_WSIZE:
834 pCursor = [NSCursor resizeLeftRightCursor]; break;
835 case POINTER_REFHAND: pCursor = [NSCursor pointingHandCursor]; break;
837 default:
838 pCursor = GetSalData()->getCursor( mePointerStyle );
839 if( pCursor == nil )
841 DBG_ERROR( "unmapped cursor" );
842 pCursor = [NSCursor arrowCursor];
844 break;
846 return pCursor;
849 void AquaSalFrame::SetPointer( PointerStyle ePointerStyle )
851 if( ePointerStyle >= POINTER_COUNT || ePointerStyle == mePointerStyle )
852 return;
853 mePointerStyle = ePointerStyle;
855 [mpWindow invalidateCursorRectsForView: mpView];
858 // -----------------------------------------------------------------------
860 void AquaSalFrame::SetPointerPos( long nX, long nY )
862 // FIXME: use Cocoa functions
864 // FIXME: multiscreen support
865 CGPoint aPoint = { nX + maGeometry.nX, nY + maGeometry.nY };
866 CGDirectDisplayID mainDisplayID = CGMainDisplayID();
867 CGDisplayMoveCursorToPoint( mainDisplayID, aPoint );
870 // -----------------------------------------------------------------------
872 void AquaSalFrame::Flush( void )
874 if( !(mbGraphics && mpGraphics && mpView && mbShown) )
875 return;
877 [mpView setNeedsDisplay: YES];
879 // outside of the application's event loop (e.g. IntroWindow)
880 // nothing would trigger paint event handling
881 // => fall back to synchronous painting
882 if( ImplGetSVData()->maAppData.mnDispatchLevel <= 0 )
884 [mpView display];
888 // -----------------------------------------------------------------------
890 void AquaSalFrame::Flush( const Rectangle& rRect )
892 if( !(mbGraphics && mpGraphics && mpView && mbShown) )
893 return;
895 NSRect aNSRect = { {rRect.Left(), rRect.Top()}, { rRect.GetWidth(), rRect.GetHeight() } };
896 VCLToCocoa( aNSRect, false );
897 [mpView setNeedsDisplayInRect: aNSRect];
899 // outside of the application's event loop (e.g. IntroWindow)
900 // nothing would trigger paint event handling
901 // => fall back to synchronous painting
902 if( ImplGetSVData()->maAppData.mnDispatchLevel <= 0 )
904 [mpView display];
908 // -----------------------------------------------------------------------
910 void AquaSalFrame::Sync()
912 if( mbGraphics && mpGraphics && mpView && mbShown )
914 //YieldMutexReleaser aRel;
916 [mpView setNeedsDisplay: YES];
917 [mpView display];
921 // -----------------------------------------------------------------------
923 void AquaSalFrame::SetInputContext( SalInputContext* pContext )
925 if (!pContext)
927 mnICOptions = 0;
928 return;
931 mnICOptions = pContext->mnOptions;
933 if(!(pContext->mnOptions & SAL_INPUTCONTEXT_TEXT))
934 return;
937 // -----------------------------------------------------------------------
939 void AquaSalFrame::EndExtTextInput( USHORT nFlags )
943 // -----------------------------------------------------------------------
945 XubString AquaSalFrame::GetKeyName( USHORT nKeyCode )
947 static std::map< USHORT, rtl::OUString > aKeyMap;
948 if( aKeyMap.empty() )
950 USHORT i;
951 for( i = KEY_A; i <= KEY_Z; i++ )
952 aKeyMap[ i ] = rtl::OUString( sal_Unicode( 'A' + (i - KEY_A) ) );
953 for( i = KEY_0; i <= KEY_9; i++ )
954 aKeyMap[ i ] = rtl::OUString( sal_Unicode( '0' + (i - KEY_0) ) );
955 for( i = KEY_F1; i <= KEY_F26; i++ )
957 rtl::OUStringBuffer aKey( 3 );
958 aKey.append( sal_Unicode( 'F' ) );
959 aKey.append( sal_Int32( i - KEY_F1 + 1 ) );
960 aKeyMap[ i ] = aKey.makeStringAndClear();
963 aKeyMap[ KEY_DOWN ] = rtl::OUString( sal_Unicode( 0x21e3 ) );
964 aKeyMap[ KEY_UP ] = rtl::OUString( sal_Unicode( 0x21e1 ) );
965 aKeyMap[ KEY_LEFT ] = rtl::OUString( sal_Unicode( 0x21e0 ) );
966 aKeyMap[ KEY_RIGHT ] = rtl::OUString( sal_Unicode( 0x21e2 ) );
967 aKeyMap[ KEY_HOME ] = rtl::OUString( sal_Unicode( 0x2196 ) );
968 aKeyMap[ KEY_END ] = rtl::OUString( sal_Unicode( 0x2198 ) );
969 aKeyMap[ KEY_PAGEUP ] = rtl::OUString( sal_Unicode( 0x21de ) );
970 aKeyMap[ KEY_PAGEDOWN ] = rtl::OUString( sal_Unicode( 0x21df ) );
971 aKeyMap[ KEY_RETURN ] = rtl::OUString( sal_Unicode( 0x21a9 ) );
972 aKeyMap[ KEY_ESCAPE ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "esc" ) );
973 aKeyMap[ KEY_TAB ] = rtl::OUString( sal_Unicode( 0x21e5 ) );
974 aKeyMap[ KEY_BACKSPACE ]= rtl::OUString( sal_Unicode( 0x232b ) );
975 aKeyMap[ KEY_SPACE ] = rtl::OUString( sal_Unicode( 0x2423 ) );
976 aKeyMap[ KEY_DELETE ] = rtl::OUString( sal_Unicode( 0x2326 ) );
977 aKeyMap[ KEY_ADD ] = rtl::OUString( sal_Unicode( '+' ) );
978 aKeyMap[ KEY_SUBTRACT ] = rtl::OUString( sal_Unicode( '-' ) );
979 aKeyMap[ KEY_DIVIDE ] = rtl::OUString( sal_Unicode( '/' ) );
980 aKeyMap[ KEY_MULTIPLY ] = rtl::OUString( sal_Unicode( '*' ) );
981 aKeyMap[ KEY_POINT ] = rtl::OUString( sal_Unicode( '.' ) );
982 aKeyMap[ KEY_COMMA ] = rtl::OUString( sal_Unicode( ',' ) );
983 aKeyMap[ KEY_LESS ] = rtl::OUString( sal_Unicode( '<' ) );
984 aKeyMap[ KEY_GREATER ] = rtl::OUString( sal_Unicode( '>' ) );
985 aKeyMap[ KEY_EQUAL ] = rtl::OUString( sal_Unicode( '=' ) );
986 aKeyMap[ KEY_OPEN ] = rtl::OUString( sal_Unicode( 0x23cf ) );
988 /* yet unmapped KEYCODES:
989 aKeyMap[ KEY_INSERT ] = rtl::OUString( sal_Unicode( ) );
990 aKeyMap[ KEY_CUT ] = rtl::OUString( sal_Unicode( ) );
991 aKeyMap[ KEY_COPY ] = rtl::OUString( sal_Unicode( ) );
992 aKeyMap[ KEY_PASTE ] = rtl::OUString( sal_Unicode( ) );
993 aKeyMap[ KEY_UNDO ] = rtl::OUString( sal_Unicode( ) );
994 aKeyMap[ KEY_REPEAT ] = rtl::OUString( sal_Unicode( ) );
995 aKeyMap[ KEY_FIND ] = rtl::OUString( sal_Unicode( ) );
996 aKeyMap[ KEY_PROPERTIES ] = rtl::OUString( sal_Unicode( ) );
997 aKeyMap[ KEY_FRONT ] = rtl::OUString( sal_Unicode( ) );
998 aKeyMap[ KEY_CONTEXTMENU ] = rtl::OUString( sal_Unicode( ) );
999 aKeyMap[ KEY_MENU ] = rtl::OUString( sal_Unicode( ) );
1000 aKeyMap[ KEY_HELP ] = rtl::OUString( sal_Unicode( ) );
1001 aKeyMap[ KEY_HANGUL_HANJA ] = rtl::OUString( sal_Unicode( ) );
1002 aKeyMap[ KEY_DECIMAL ] = rtl::OUString( sal_Unicode( ) );
1003 aKeyMap[ KEY_TILDE ] = rtl::OUString( sal_Unicode( ) );
1004 aKeyMap[ KEY_QUOTELEFT ]= rtl::OUString( sal_Unicode( ) );
1009 rtl::OUStringBuffer aResult( 16 );
1011 USHORT nUnmodifiedCode = (nKeyCode & KEY_CODE);
1012 std::map< USHORT, rtl::OUString >::const_iterator it = aKeyMap.find( nUnmodifiedCode );
1013 if( it != aKeyMap.end() )
1015 if( (nKeyCode & KEY_SHIFT) != 0 )
1016 aResult.append( sal_Unicode( 0x21e7 ) );
1017 if( (nKeyCode & KEY_MOD1) != 0 )
1018 aResult.append( sal_Unicode( 0x2318 ) );
1019 // we do not really handle Alt (see below)
1020 // we map it to MOD3, whichis actually Command
1021 if( (nKeyCode & (KEY_MOD2|KEY_MOD3)) != 0 )
1022 aResult.append( sal_Unicode( 0x2303 ) );
1024 aResult.append( it->second );
1027 return aResult.makeStringAndClear();
1030 // -----------------------------------------------------------------------
1032 XubString AquaSalFrame::GetSymbolKeyName( const XubString&, USHORT nKeyCode )
1034 return GetKeyName( nKeyCode );
1037 // -----------------------------------------------------------------------
1039 static void getAppleScrollBarVariant(void)
1041 bool bIsScrollbarDoubleMax = true; // default is DoubleMax
1043 CFStringRef AppleScrollBarType = CFSTR("AppleScrollBarVariant");
1044 if( AppleScrollBarType )
1046 CFStringRef ScrollBarVariant = ((CFStringRef)CFPreferencesCopyAppValue( AppleScrollBarType, kCFPreferencesCurrentApplication ));
1047 if( ScrollBarVariant )
1049 if( CFGetTypeID( ScrollBarVariant ) == CFStringGetTypeID() )
1051 // TODO: check for the less important variants "DoubleMin" and "DoubleBoth" too
1052 CFStringRef DoubleMax = CFSTR("DoubleMax");
1053 if (DoubleMax)
1055 if ( !CFStringCompare(ScrollBarVariant, DoubleMax, kCFCompareCaseInsensitive) )
1056 bIsScrollbarDoubleMax = true;
1057 else
1058 bIsScrollbarDoubleMax = false;
1059 CFRelease(DoubleMax);
1062 CFRelease( ScrollBarVariant );
1064 CFRelease(AppleScrollBarType);
1067 GetSalData()->mbIsScrollbarDoubleMax = bIsScrollbarDoubleMax;
1069 CFStringRef jumpScroll = CFSTR("AppleScrollerPagingBehavior");
1070 if( jumpScroll )
1072 CFBooleanRef jumpStr = ((CFBooleanRef)CFPreferencesCopyAppValue( jumpScroll, kCFPreferencesCurrentApplication ));
1073 if( jumpStr )
1075 if( CFGetTypeID( jumpStr ) == CFBooleanGetTypeID() )
1076 ImplGetSVData()->maNWFData.mbScrollbarJumpPage = (jumpStr == kCFBooleanTrue);
1077 CFRelease( jumpStr );
1079 CFRelease( jumpScroll );
1083 static Color getColor( NSColor* pSysColor, const Color& rDefault, NSWindow* pWin )
1085 Color aRet( rDefault );
1086 if( pSysColor )
1088 // transform to RGB
1089 NSColor* pRBGColor = [pSysColor colorUsingColorSpaceName: NSDeviceRGBColorSpace device: [pWin deviceDescription]];
1090 if( pRBGColor )
1092 float r = 0, g = 0, b = 0, a = 0;
1093 [pRBGColor getRed: &r green: &g blue: &b alpha: &a];
1094 aRet = Color( int(r*255.999), int(g*255.999), int(b*255.999) );
1096 do not release here; leads to duplicate free in yield
1097 it seems the converted color comes out autoreleased, although this
1098 is not documented
1099 [pRBGColor release];
1103 return aRet;
1106 static Font getFont( NSFont* pFont, long nDPIY, const Font& rDefault )
1108 Font aResult( rDefault );
1109 if( pFont )
1111 aResult.SetName( GetOUString( [pFont familyName] ) );
1112 aResult.SetHeight( static_cast<int>(([pFont pointSize] * 72.0 / (float)nDPIY)+0.5) );
1113 aResult.SetItalic( ([pFont italicAngle] != 0.0) ? ITALIC_NORMAL : ITALIC_NONE );
1114 // FIMXE: bold ?
1117 return aResult;
1120 // on OSX-Aqua the style settings are independent of the frame, so it does
1121 // not really belong here. Since the connection to the Appearance_Manager
1122 // is currently done in salnativewidgets.cxx this would be a good place.
1123 // On the other hand VCL's platform independent code currently only asks
1124 // SalFrames for system settings anyway, so moving the code somewhere else
1125 // doesn't make the anything cleaner for now
1126 void AquaSalFrame::UpdateSettings( AllSettings& rSettings )
1128 [mpView lockFocus];
1130 StyleSettings aStyleSettings = rSettings.GetStyleSettings();
1132 // Background Color
1133 Color aBackgroundColor = Color( 0xEC, 0xEC, 0xEC );
1134 aStyleSettings.Set3DColors( aBackgroundColor );
1135 aStyleSettings.SetFaceColor( aBackgroundColor );
1136 Color aInactiveTabColor( aBackgroundColor );
1137 aInactiveTabColor.DecreaseLuminance( 32 );
1138 aStyleSettings.SetInactiveTabColor( aInactiveTabColor );
1140 aStyleSettings.SetDialogColor( aBackgroundColor );
1141 aStyleSettings.SetLightBorderColor( aBackgroundColor );
1142 Color aShadowColor( aStyleSettings.GetShadowColor() );
1143 aStyleSettings.SetDarkShadowColor( aShadowColor );
1144 aShadowColor.IncreaseLuminance( 32 );
1145 aStyleSettings.SetShadowColor( aShadowColor );
1147 // get the system font settings
1148 Font aAppFont = aStyleSettings.GetAppFont();
1149 if( ! mpGraphics )
1151 GetGraphics();
1152 ReleaseGraphics( mpGraphics );
1154 long nDPIX = 72, nDPIY = 72;
1155 mpGraphics->GetResolution( nDPIX, nDPIY );
1156 aAppFont = getFont( [NSFont systemFontOfSize: 0], nDPIY, aAppFont );
1158 // TODO: better mapping of aqua<->ooo font settings
1159 aStyleSettings.SetAppFont( aAppFont );
1160 aStyleSettings.SetHelpFont( aAppFont );
1161 aStyleSettings.SetPushButtonFont( aAppFont );
1163 Font aTitleFont( getFont( [NSFont titleBarFontOfSize: 0], nDPIY, aAppFont ) );
1164 aStyleSettings.SetTitleFont( aTitleFont );
1165 aStyleSettings.SetFloatTitleFont( aTitleFont );
1167 Font aMenuFont( getFont( [NSFont menuFontOfSize: 0], nDPIY, aAppFont ) );
1168 aStyleSettings.SetMenuFont( aMenuFont );
1170 aStyleSettings.SetToolFont( aAppFont );
1172 Font aLabelFont( getFont( [NSFont labelFontOfSize: 0], nDPIY, aAppFont ) );
1173 aStyleSettings.SetLabelFont( aLabelFont );
1174 aStyleSettings.SetInfoFont( aLabelFont );
1175 aStyleSettings.SetRadioCheckFont( aLabelFont );
1176 aStyleSettings.SetFieldFont( aLabelFont );
1177 aStyleSettings.SetGroupFont( aLabelFont );
1178 aStyleSettings.SetIconFont( aLabelFont );
1180 Color aHighlightColor( getColor( [NSColor selectedTextBackgroundColor],
1181 aStyleSettings.GetHighlightColor(), mpWindow ) );
1182 aStyleSettings.SetHighlightColor( aHighlightColor );
1183 Color aHighlightTextColor( getColor( [NSColor selectedTextColor],
1184 aStyleSettings.GetHighlightTextColor(), mpWindow ) );
1185 aStyleSettings.SetHighlightTextColor( aHighlightTextColor );
1187 Color aMenuHighlightColor( getColor( [NSColor selectedMenuItemColor],
1188 aStyleSettings.GetMenuHighlightColor(), mpWindow ) );
1189 aStyleSettings.SetMenuHighlightColor( aMenuHighlightColor );
1190 Color aMenuHighlightTextColor( getColor( [NSColor selectedMenuItemTextColor],
1191 aStyleSettings.GetMenuHighlightTextColor(), mpWindow ) );
1192 aStyleSettings.SetMenuHighlightTextColor( aMenuHighlightTextColor );
1194 aStyleSettings.SetMenuColor( aBackgroundColor );
1195 Color aMenuTextColor( getColor( [NSColor textColor],
1196 aStyleSettings.GetMenuTextColor(), mpWindow ) );
1197 aStyleSettings.SetMenuTextColor( aMenuTextColor );
1198 aStyleSettings.SetMenuBarTextColor( aMenuTextColor );
1200 aStyleSettings.SetCursorBlinkTime( 500 );
1202 // no mnemonics on aqua
1203 aStyleSettings.SetOptions( aStyleSettings.GetOptions() | STYLE_OPTION_NOMNEMONICS );
1205 getAppleScrollBarVariant();
1207 // set scrollbar size
1208 aStyleSettings.SetScrollBarSize( static_cast<long int>([NSScroller scrollerWidth]) );
1210 // images in menus false for MacOSX
1211 aStyleSettings.SetUseImagesInMenus( false );
1213 rSettings.SetStyleSettings( aStyleSettings );
1215 [mpView unlockFocus];
1218 // -----------------------------------------------------------------------
1220 const SystemEnvData* AquaSalFrame::GetSystemData() const
1222 return &maSysData;
1225 // -----------------------------------------------------------------------
1227 void AquaSalFrame::Beep( SoundType eSoundType )
1229 switch( eSoundType )
1231 case SOUND_DISABLE:
1232 // don't beep
1233 break;
1234 default:
1235 NSBeep();
1236 break;
1240 // -----------------------------------------------------------------------
1242 void AquaSalFrame::SetPosSize(long nX, long nY, long nWidth, long nHeight, USHORT nFlags)
1244 USHORT nEvent = 0;
1246 if( [mpWindow isMiniaturized] )
1247 [mpWindow deminiaturize: NSApp]; // expand the window
1249 if (nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y))
1251 mbPositioned = true;
1252 nEvent = SALEVENT_MOVE;
1255 if (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT))
1257 mbSized = true;
1258 nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE;
1261 NSRect aFrameRect = [mpWindow frame];
1262 NSRect aContentRect = [NSWindow contentRectForFrameRect: aFrameRect styleMask: mnStyleMask];
1264 // position is always relative to parent frame
1265 NSRect aParentContentRect;
1267 if( mpParent )
1269 if( Application::GetSettings().GetLayoutRTL() )
1271 if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 )
1272 nX = mpParent->maGeometry.nWidth - nWidth-1 - nX;
1273 else
1274 nX = mpParent->maGeometry.nWidth - static_cast<long int>( aContentRect.size.width-1) - nX;
1276 NSRect aParentFrameRect = [mpParent->mpWindow frame];
1277 aParentContentRect = [NSWindow contentRectForFrameRect: aParentFrameRect styleMask: mpParent->mnStyleMask];
1279 else
1280 aParentContentRect = maScreenRect; // use screen if no parent
1282 CocoaToVCL( aContentRect );
1283 CocoaToVCL( aParentContentRect );
1285 bool bPaint = false;
1286 if( (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) != 0 )
1288 if( nWidth != aContentRect.size.width || nHeight != aContentRect.size.height )
1289 bPaint = true;
1292 // use old window pos if no new pos requested
1293 if( (nFlags & SAL_FRAME_POSSIZE_X) != 0 )
1294 aContentRect.origin.x = nX + aParentContentRect.origin.x;
1295 if( (nFlags & SAL_FRAME_POSSIZE_Y) != 0)
1296 aContentRect.origin.y = nY + aParentContentRect.origin.y;
1298 // use old size if no new size requested
1299 if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 )
1300 aContentRect.size.width = nWidth;
1301 if( (nFlags & SAL_FRAME_POSSIZE_HEIGHT) != 0)
1302 aContentRect.size.height = nHeight;
1304 VCLToCocoa( aContentRect );
1306 // do not display yet, we need to update our backbuffer
1308 //YieldMutexReleaser aRel;
1309 [mpWindow setFrame: [NSWindow frameRectForContentRect: aContentRect styleMask: mnStyleMask] display: NO];
1312 UpdateFrameGeometry();
1314 if (nEvent)
1315 CallCallback(nEvent, NULL);
1317 if( mbShown && bPaint )
1319 // trigger filling our backbuffer
1320 SendPaintEvent();
1322 // now inform the system that the views need to be drawn
1323 //YieldMutexReleaser aRel;
1324 [mpWindow display];
1328 void AquaSalFrame::GetWorkArea( Rectangle& rRect )
1330 NSScreen* pScreen = [mpWindow screen];
1331 if( pScreen == nil )
1332 pScreen = [NSScreen mainScreen];
1333 NSRect aRect = [pScreen visibleFrame];
1334 CocoaToVCL( aRect );
1335 rRect.nLeft = static_cast<long>(aRect.origin.x);
1336 rRect.nTop = static_cast<long>(aRect.origin.y);
1337 rRect.nRight = static_cast<long>(aRect.origin.x + aRect.size.width - 1);
1338 rRect.nBottom = static_cast<long>(aRect.origin.y + aRect.size.height - 1);
1341 SalPointerState AquaSalFrame::GetPointerState()
1343 SalPointerState state;
1345 // get position
1346 NSPoint aPt = [mpWindow mouseLocationOutsideOfEventStream];
1347 CocoaToVCL( aPt, false );
1348 state.maPos = Point(static_cast<long>(aPt.x), static_cast<long>(aPt.y));
1350 // FIXME: replace Carbon by Cocoa
1351 // Cocoa does not have an equivalent for GetCurrentEventButtonState
1352 // and GetCurrentEventKeyModifiers.
1353 // we could try to get away with tracking all events for modifierKeys
1354 // and all mouse events for button state in VCL_NSApllication::sendEvent,
1355 // but it is unclear whether this will get us the same result.
1356 // leave in GetCurrentEventButtonState and GetCurrentEventKeyModifiers for now
1358 // fill in button state
1359 UInt32 nState = GetCurrentEventButtonState();
1360 state.mnState = 0;
1361 if( nState & 1 )
1362 state.mnState |= MOUSE_LEFT; // primary button
1363 if( nState & 2 )
1364 state.mnState |= MOUSE_RIGHT; // secondary button
1365 if( nState & 4 )
1366 state.mnState |= MOUSE_MIDDLE; // tertiary button
1368 // fill in modifier state
1369 nState = GetCurrentEventKeyModifiers();
1370 if( nState & shiftKey )
1371 state.mnState |= KEY_SHIFT;
1372 if( nState & controlKey )
1373 state.mnState |= KEY_MOD3;
1374 if( nState & optionKey )
1375 state.mnState |= KEY_MOD2;
1376 if( nState & cmdKey )
1377 state.mnState |= KEY_MOD1;
1379 return state;
1382 SalFrame::SalIndicatorState AquaSalFrame::GetIndicatorState()
1384 SalIndicatorState aState;
1385 aState.mnState = 0;
1386 return aState;
1389 void AquaSalFrame::SimulateKeyPress( USHORT /*nKeyCode*/ )
1393 bool AquaSalFrame::SetPluginParent( SystemParentData* pNewParent )
1395 // plugin parent may be killed unexpectedly by
1396 // plugging process;
1398 //TODO: implement
1399 return sal_False;
1402 BOOL AquaSalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , KeyCode& )
1404 // not supported yet
1405 return FALSE;
1408 LanguageType AquaSalFrame::GetInputLanguage()
1410 //TODO: implement
1411 return LANGUAGE_DONTKNOW;
1414 void AquaSalFrame::DrawMenuBar()
1418 void AquaSalFrame::SetMenu( SalMenu* pSalMenu )
1420 AquaSalMenu* pMenu = static_cast<AquaSalMenu*>(pSalMenu);
1421 DBG_ASSERT( ! pMenu || pMenu->mbMenuBar, "setting non menubar on frame" );
1422 mpMenu = pMenu;
1423 if( mpMenu )
1424 mpMenu->setMainMenu();
1427 void AquaSalFrame::SetExtendedFrameStyle( SalExtStyle nStyle )
1429 if( (mnExtStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) != (nStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) )
1430 [mpWindow setDocumentEdited: (nStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) ? YES : NO];
1431 mnExtStyle = nStyle;
1434 void AquaSalFrame::SetBackgroundBitmap( SalBitmap* )
1436 //TODO: implement
1439 SalBitmap* AquaSalFrame::SnapShot()
1441 return mpGraphics ? mpGraphics->getBitmap( 0, 0, maGeometry.nWidth, maGeometry.nHeight ) : NULL;
1444 SalFrame* AquaSalFrame::GetParent() const
1446 return mpParent;
1449 void AquaSalFrame::SetParent( SalFrame* pNewParent )
1451 bool bShown = mbShown;
1452 // remove from child list
1453 Show( FALSE );
1454 mpParent = (AquaSalFrame*)pNewParent;
1455 // insert to correct parent and paint
1456 Show( bShown );
1459 void AquaSalFrame::UpdateFrameGeometry()
1461 // keep in mind that view and window coordinates are lower left
1462 // whereas vcl's are upper left
1464 // update screen rect
1465 NSScreen * pScreen = [mpWindow screen];
1466 if( pScreen )
1468 maScreenRect = [pScreen frame];
1469 NSArray* pScreens = [NSScreen screens];
1470 if( pScreens )
1471 maGeometry.nScreenNumber = [pScreens indexOfObject: pScreen];
1474 NSRect aFrameRect = [mpWindow frame];
1475 NSRect aContentRect = [NSWindow contentRectForFrameRect: aFrameRect styleMask: mnStyleMask];
1477 // release old track rect
1478 [mpView removeTrackingRect: mnTrackingRectTag];
1479 // install the new track rect
1480 NSRect aTrackRect = { { 0, 0 }, aContentRect.size };
1481 mnTrackingRectTag = [mpView addTrackingRect: aTrackRect owner: mpView userData: nil assumeInside: NO];
1483 // convert to vcl convention
1484 CocoaToVCL( aFrameRect );
1485 CocoaToVCL( aContentRect );
1487 maGeometry.nX = static_cast<int>(aContentRect.origin.x);
1488 maGeometry.nY = static_cast<int>(aContentRect.origin.y);
1490 maGeometry.nLeftDecoration = static_cast<unsigned int>(aContentRect.origin.x - aFrameRect.origin.x);
1491 maGeometry.nRightDecoration = static_cast<unsigned int>((aFrameRect.origin.x + aFrameRect.size.width) -
1492 (aContentRect.origin.x + aContentRect.size.width));
1494 maGeometry.nTopDecoration = static_cast<unsigned int>(aContentRect.origin.y - aFrameRect.origin.y);
1495 maGeometry.nBottomDecoration = static_cast<unsigned int>((aFrameRect.origin.y + aFrameRect.size.height) -
1496 (aContentRect.origin.y + aContentRect.size.height));
1498 maGeometry.nWidth = static_cast<unsigned int>(aContentRect.size.width);
1499 maGeometry.nHeight = static_cast<unsigned int>(aContentRect.size.height);
1502 // -----------------------------------------------------------------------
1504 void AquaSalFrame::CaptureMouse( BOOL bCapture )
1506 /* Remark:
1507 we'll try to use a pidgin version of capture mouse
1508 on MacOSX (neither carbon nor cocoa) there is a
1509 CaptureMouse equivalent (in Carbon there is TrackMouseLocation
1510 but this is useless to use since it is blocking)
1512 However on cocoa the active frame seems to get mouse events
1513 also outside the window, so we'll try to forward mouse events
1514 to the capture frame in the hope that one of our frames
1515 gets a mouse event.
1517 This will break as soon as the user activates another app, but
1518 a mouse click will normally lead to a release of the mouse anyway.
1520 Let's see how far we get this way. Alternatively we could use one
1521 large overlay window like we did for the carbon implementation,
1522 however that is resource intensive.
1525 if( bCapture )
1526 s_pCaptureFrame = this;
1527 else if( ! bCapture && s_pCaptureFrame == this )
1528 s_pCaptureFrame = NULL;
1531 void AquaSalFrame::ResetClipRegion()
1533 // release old path and indicate no clipping
1534 CGPathRelease( mrClippingPath );
1535 mrClippingPath = NULL;
1537 if( mpView && mbShown )
1538 [mpView setNeedsDisplay: YES];
1539 if( mpWindow )
1541 [mpWindow setOpaque: YES];
1542 [mpWindow invalidateShadow];
1546 void AquaSalFrame::BeginSetClipRegion( ULONG nRects )
1548 // release old path
1549 if( mrClippingPath )
1551 CGPathRelease( mrClippingPath );
1552 mrClippingPath = NULL;
1555 if( maClippingRects.size() > SAL_CLIPRECT_COUNT && nRects < maClippingRects.size() )
1557 std::vector<CGRect> aEmptyVec;
1558 maClippingRects.swap( aEmptyVec );
1560 maClippingRects.clear();
1561 maClippingRects.reserve( nRects );
1564 void AquaSalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
1566 if( nWidth && nHeight )
1568 NSRect aRect = { { nX, nY }, { nWidth, nHeight } };
1569 VCLToCocoa( aRect, false );
1570 maClippingRects.push_back( CGRectMake(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height) );
1574 void AquaSalFrame::EndSetClipRegion()
1576 if( ! maClippingRects.empty() )
1578 mrClippingPath = CGPathCreateMutable();
1579 CGPathAddRects( mrClippingPath, NULL, &maClippingRects[0], maClippingRects.size() );
1581 if( mpView && mbShown )
1582 [mpView setNeedsDisplay: YES];
1583 if( mpWindow )
1585 [mpWindow setOpaque: (mrClippingPath != NULL) ? NO : YES];
1586 [mpWindow setBackgroundColor: [NSColor clearColor]];
1587 // shadow is invalidated when view gets drawn again