bump product version to 4.2.0.1
[LibreOffice.git] / vcl / aqua / source / window / salframe.cxx
blob078fc1d74e5451d3d138b252cb6af2cd429a61d5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <string>
23 #include "rtl/ustrbuf.hxx"
25 #include "osl/file.h"
27 #include "vcl/svapp.hxx"
28 #include "vcl/window.hxx"
29 #include "vcl/syswin.hxx"
31 #include "aqua/saldata.hxx"
32 #include "aqua/salgdi.h"
33 #include "aqua/salframe.h"
34 #include "aqua/salmenu.h"
35 #include "aqua/salinst.h"
36 #include "aqua/salframeview.h"
37 #include "aqua/aqua11yfactory.h"
38 #include "quartz/utils.h"
40 #include "salwtype.hxx"
42 #include "premac.h"
43 #include <objc/objc-runtime.h>
44 // needed for theming
45 // FIXME: move theming code to salnativewidgets.cxx
46 #include <Carbon/Carbon.h>
47 #include "postmac.h"
49 using namespace std;
51 // =======================================================================
53 AquaSalFrame* AquaSalFrame::s_pCaptureFrame = NULL;
55 // =======================================================================
57 AquaSalFrame::AquaSalFrame( SalFrame* pParent, sal_uLong salFrameStyle ) :
58 mpWindow(nil),
59 mpView(nil),
60 mpDockMenuEntry(nil),
61 mpGraphics(NULL),
62 mpParent(NULL),
63 mnMinWidth(0),
64 mnMinHeight(0),
65 mnMaxWidth(0),
66 mnMaxHeight(0),
67 mbGraphics(false),
68 mbFullScreen( false ),
69 mbShown(false),
70 mbInitShow(true),
71 mbPositioned(false),
72 mbSized(false),
73 mbPresentation( false ),
74 mnStyle( salFrameStyle ),
75 mnStyleMask( 0 ),
76 mnLastEventTime( 0 ),
77 mnLastModifierFlags( 0 ),
78 mpMenu( NULL ),
79 mnExtStyle( 0 ),
80 mePointerStyle( POINTER_ARROW ),
81 mnTrackingRectTag( 0 ),
82 mrClippingPath( 0 ),
83 mnICOptions( 0 )
85 maSysData.nSize = sizeof( SystemEnvData );
87 mpParent = dynamic_cast<AquaSalFrame*>(pParent);
89 initWindowAndView();
91 SalData* pSalData = GetSalData();
92 pSalData->maFrames.push_front( this );
93 pSalData->maFrameCheck.insert( this );
96 // -----------------------------------------------------------------------
98 AquaSalFrame::~AquaSalFrame()
100 // if the frame is destroyed and has the current menubar
101 // set the default menubar
102 if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu )
103 AquaSalMenu::setDefaultMenu();
105 // cleanup clipping stuff
106 ResetClipRegion();
108 [SalFrameView unsetMouseFrame: this];
110 SalData* pSalData = GetSalData();
111 pSalData->maFrames.remove( this );
112 pSalData->maFrameCheck.erase( this );
113 pSalData->maPresentationFrames.remove( this );
115 DBG_ASSERT( this != s_pCaptureFrame, "capture frame destroyed" );
116 if( this == s_pCaptureFrame )
117 s_pCaptureFrame = NULL;
119 delete mpGraphics;
121 if( mpDockMenuEntry )
122 // life cycle comment: the menu has ownership of the item, so no release
123 [AquaSalInstance::GetDynamicDockMenu() removeItem: mpDockMenuEntry];
124 if ( mpView ) {
125 [AquaA11yFactory revokeView: mpView];
126 [mpView release];
128 if ( mpWindow )
129 [mpWindow release];
132 // -----------------------------------------------------------------------
134 void AquaSalFrame::initWindowAndView()
136 // initialize mirroring parameters
137 // FIXME: screens changing
138 NSScreen * pScreen = [mpWindow screen];
139 if( pScreen == nil )
140 pScreen = [NSScreen mainScreen];
141 maScreenRect = [pScreen frame];
143 // calculate some default geometry
144 NSRect aVisibleRect = [pScreen visibleFrame];
145 CocoaToVCL( aVisibleRect );
147 maGeometry.nX = static_cast<int>(aVisibleRect.origin.x + aVisibleRect.size.width / 10);
148 maGeometry.nY = static_cast<int>(aVisibleRect.origin.y + aVisibleRect.size.height / 10);
149 maGeometry.nWidth = static_cast<unsigned int>(aVisibleRect.size.width * 0.8);
150 maGeometry.nHeight = static_cast<unsigned int>(aVisibleRect.size.height * 0.8);
152 // calculate style mask
153 if( (mnStyle & SAL_FRAME_STYLE_FLOAT) ||
154 (mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
155 mnStyleMask = NSBorderlessWindowMask;
156 else if( mnStyle & SAL_FRAME_STYLE_DEFAULT )
158 mnStyleMask = NSTitledWindowMask |
159 NSMiniaturizableWindowMask |
160 NSResizableWindowMask |
161 NSClosableWindowMask;
162 // make default window "maximized"
163 maGeometry.nX = static_cast<int>(aVisibleRect.origin.x);
164 maGeometry.nY = static_cast<int>(aVisibleRect.origin.y);
165 maGeometry.nWidth = static_cast<int>(aVisibleRect.size.width);
166 maGeometry.nHeight = static_cast<int>(aVisibleRect.size.height);
167 mbPositioned = mbSized = true;
169 else
171 if( (mnStyle & SAL_FRAME_STYLE_MOVEABLE) )
173 mnStyleMask |= NSTitledWindowMask;
174 if( mpParent == NULL )
175 mnStyleMask |= NSMiniaturizableWindowMask;
177 if( (mnStyle & SAL_FRAME_STYLE_SIZEABLE) )
178 mnStyleMask |= NSResizableWindowMask;
179 if( (mnStyle & SAL_FRAME_STYLE_CLOSEABLE) )
180 mnStyleMask |= NSClosableWindowMask;
181 // documentation says anything other than NSBorderlessWindowMask (=0)
182 // should also include NSTitledWindowMask;
183 if( mnStyleMask != 0 )
184 mnStyleMask |= NSTitledWindowMask;
187 // #i91990# support GUI-less (daemon) execution
188 @try
190 mpWindow = [[SalFrameWindow alloc] initWithSalFrame: this];
191 mpView = [[SalFrameView alloc] initWithSalFrame: this];
193 @catch ( id exception )
195 return;
198 if( (mnStyle & SAL_FRAME_STYLE_TOOLTIP) )
199 [mpWindow setIgnoresMouseEvents: YES];
200 else
201 [mpWindow setAcceptsMouseMovedEvents: YES];
202 [mpWindow setHasShadow: YES];
204 // WTF? With the 10.6 SDK and gcc 4.2.1, we get: class 'NSWindow'
205 // does not implement the 'NSWindowDelegate' protocol. Anyway,
206 // having the window object be its own delegate object is
207 // apparently what the code does on purpose, see discussion in
208 // https://issues.apache.org/ooo/show_bug.cgi?id=91990
210 // So to silence the warning when compiling with -Werror, instead of:
211 // [mpWindow setDelegate: mpWindow];
212 // do this:
213 objc_msgSend(mpWindow, @selector(setDelegate:), mpWindow);
215 if( [mpWindow respondsToSelector: @selector(setRestorable:)])
217 objc_msgSend(mpWindow, @selector(setRestorable:), NO);
219 NSRect aRect = { { 0,0 }, { static_cast<CGFloat>(maGeometry.nWidth), static_cast<CGFloat>(maGeometry.nHeight) } };
220 mnTrackingRectTag = [mpView addTrackingRect: aRect owner: mpView userData: nil assumeInside: NO];
222 maSysData.pView = mpView;
224 UpdateFrameGeometry();
226 [mpWindow setContentView: mpView];
229 // -----------------------------------------------------------------------
231 void AquaSalFrame::CocoaToVCL( 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::VCLToCocoa( NSRect& io_rRect, bool bRelativeToScreen )
241 if( bRelativeToScreen )
242 io_rRect.origin.y = maScreenRect.size.height - (io_rRect.origin.y+io_rRect.size.height);
243 else
244 io_rRect.origin.y = maGeometry.nHeight - (io_rRect.origin.y+io_rRect.size.height);
247 void AquaSalFrame::CocoaToVCL( 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 void AquaSalFrame::VCLToCocoa( NSPoint& io_rPoint, bool bRelativeToScreen )
257 if( bRelativeToScreen )
258 io_rPoint.y = maScreenRect.size.height - io_rPoint.y;
259 else
260 io_rPoint.y = maGeometry.nHeight - io_rPoint.y;
263 // -----------------------------------------------------------------------
265 void AquaSalFrame::screenParametersChanged()
267 UpdateFrameGeometry();
269 if( mpGraphics )
270 mpGraphics->updateResolution();
271 CallCallback( SALEVENT_DISPLAYCHANGED, 0 );
274 // -----------------------------------------------------------------------
276 SalGraphics* AquaSalFrame::GetGraphics()
278 if ( mbGraphics )
279 return NULL;
281 if ( !mpGraphics )
283 mpGraphics = new AquaSalGraphics;
284 mpGraphics->SetWindowGraphics( this );
287 mbGraphics = TRUE;
288 return mpGraphics;
291 // -----------------------------------------------------------------------
293 void AquaSalFrame::ReleaseGraphics( SalGraphics *pGraphics )
295 (void)pGraphics;
296 DBG_ASSERT( pGraphics == mpGraphics, "graphics released on wrong frame" );
297 mbGraphics = FALSE;
300 // -----------------------------------------------------------------------
302 sal_Bool AquaSalFrame::PostEvent( void *pData )
304 GetSalData()->mpFirstInstance->PostUserEvent( this, SALEVENT_USEREVENT, pData );
305 return TRUE;
308 // -----------------------------------------------------------------------
309 void AquaSalFrame::SetTitle(const OUString& rTitle)
311 if ( !mpWindow )
312 return;
314 // #i113170# may not be the main thread if called from UNO API
315 SalData::ensureThreadAutoreleasePool();
317 NSString* pTitle = CreateNSString( rTitle );
318 [mpWindow setTitle: pTitle];
320 // create an entry in the dock menu
321 const sal_uLong nAppWindowStyle = (SAL_FRAME_STYLE_CLOSEABLE | SAL_FRAME_STYLE_MOVEABLE);
322 if( mpParent == NULL &&
323 (mnStyle & nAppWindowStyle) == nAppWindowStyle )
325 if( mpDockMenuEntry == NULL )
327 NSMenu* pDock = AquaSalInstance::GetDynamicDockMenu();
328 mpDockMenuEntry = [pDock insertItemWithTitle: pTitle
329 action: @selector(dockMenuItemTriggered:)
330 keyEquivalent: @""
331 atIndex: 0];
332 [mpDockMenuEntry setTarget: mpWindow];
334 // TODO: image (either the generic window image or an icon
335 // check mark (for "main" window ?)
337 else
338 [mpDockMenuEntry setTitle: pTitle];
341 if (pTitle)
342 [pTitle release];
345 // -----------------------------------------------------------------------
347 void AquaSalFrame::SetIcon( sal_uInt16 )
351 // -----------------------------------------------------------------------
353 void AquaSalFrame::SetRepresentedURL( const OUString& i_rDocURL )
355 // #i113170# may not be the main thread if called from UNO API
356 SalData::ensureThreadAutoreleasePool();
358 if( i_rDocURL.startsWith( "file:" ) )
360 OUString aSysPath;
361 osl_getSystemPathFromFileURL( i_rDocURL.pData, &aSysPath.pData );
362 NSString* pStr = CreateNSString( aSysPath );
363 if( pStr )
365 [pStr autorelease];
366 [mpWindow setRepresentedFilename: pStr];
371 // -----------------------------------------------------------------------
373 void AquaSalFrame::initShow()
375 mbInitShow = false;
376 if( ! mbPositioned && ! mbFullScreen )
378 Rectangle aScreenRect;
379 GetWorkArea( aScreenRect );
380 if( mpParent ) // center relative to parent
382 // center on parent
383 long nNewX = mpParent->maGeometry.nX + ((long)mpParent->maGeometry.nWidth - (long)maGeometry.nWidth)/2;
384 if( nNewX < aScreenRect.Left() )
385 nNewX = aScreenRect.Left();
386 if( long(nNewX + maGeometry.nWidth) > aScreenRect.Right() )
387 nNewX = aScreenRect.Right() - maGeometry.nWidth-1;
388 long nNewY = mpParent->maGeometry.nY + ((long)mpParent->maGeometry.nHeight - (long)maGeometry.nHeight)/2;
389 if( nNewY < aScreenRect.Top() )
390 nNewY = aScreenRect.Top();
391 if( nNewY > aScreenRect.Bottom() )
392 nNewY = aScreenRect.Bottom() - maGeometry.nHeight-1;
393 SetPosSize( nNewX - mpParent->maGeometry.nX,
394 nNewY - mpParent->maGeometry.nY,
395 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y );
397 else if( ! (mnStyle & SAL_FRAME_STYLE_SIZEABLE) )
399 // center on screen
400 long nNewX = (aScreenRect.GetWidth() - maGeometry.nWidth)/2;
401 long nNewY = (aScreenRect.GetHeight() - maGeometry.nHeight)/2;
402 SetPosSize( nNewX, nNewY, 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y );
406 // make sure the view is present in the wrapper list before any children receive focus
407 [AquaA11yFactory registerView: mpView];
410 void AquaSalFrame::SendPaintEvent( const Rectangle* pRect )
412 SalPaintEvent aPaintEvt( 0, 0, maGeometry.nWidth, maGeometry.nHeight, true );
413 if( pRect )
415 aPaintEvt.mnBoundX = pRect->Left();
416 aPaintEvt.mnBoundY = pRect->Top();
417 aPaintEvt.mnBoundWidth = pRect->GetWidth();
418 aPaintEvt.mnBoundHeight = pRect->GetHeight();
421 CallCallback(SALEVENT_PAINT, &aPaintEvt);
424 // -----------------------------------------------------------------------
426 void AquaSalFrame::Show(sal_Bool bVisible, sal_Bool bNoActivate)
428 if ( !mpWindow )
429 return;
431 // #i113170# may not be the main thread if called from UNO API
432 SalData::ensureThreadAutoreleasePool();
434 mbShown = bVisible;
435 if(bVisible)
437 if( mbInitShow )
438 initShow();
440 CallCallback(SALEVENT_RESIZE, 0);
441 // trigger filling our backbuffer
442 SendPaintEvent();
444 if( bNoActivate || [mpWindow canBecomeKeyWindow] == NO )
445 [mpWindow orderFront: NSApp];
446 else
447 [mpWindow makeKeyAndOrderFront: NSApp];
449 if( mpParent )
451 /* #i92674# #i96433# we do not want an invisible parent to show up (which adding a visible
452 child implicitly does). However we also do not want a parentless toolbar.
454 HACK: try to decide when we should not insert a child to its parent
455 floaters and ownerdraw windows have not yet shown up in cases where
456 we don't want the parent to become visible
458 if( mpParent->mbShown || (mnStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION | SAL_FRAME_STYLE_FLOAT) ) )
460 [mpParent->mpWindow addChildWindow: mpWindow ordered: NSWindowAbove];
464 if( mbPresentation )
465 [mpWindow makeMainWindow];
467 else
469 // if the frame holding the current menubar gets hidden
470 // show the default menubar
471 if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu )
472 AquaSalMenu::setDefaultMenu();
474 // #i90440# #i94443# work around the focus going back to some other window
475 // if a child gets hidden for a parent window
476 if( mpParent && mpParent->mbShown && [mpWindow isKeyWindow] )
477 [mpParent->mpWindow makeKeyAndOrderFront: NSApp];
479 [SalFrameView unsetMouseFrame: this];
480 if( mpParent && [mpWindow parentWindow] == mpParent->mpWindow )
481 [mpParent->mpWindow removeChildWindow: mpWindow];
483 [mpWindow orderOut: NSApp];
487 // -----------------------------------------------------------------------
489 void AquaSalFrame::Enable( sal_Bool )
493 // -----------------------------------------------------------------------
495 void AquaSalFrame::SetMinClientSize( long nWidth, long nHeight )
497 // #i113170# may not be the main thread if called from UNO API
498 SalData::ensureThreadAutoreleasePool();
500 mnMinWidth = nWidth;
501 mnMinHeight = nHeight;
503 if( mpWindow )
505 // Always add the decoration as the dimension concerns only
506 // the content rectangle
507 nWidth += maGeometry.nLeftDecoration + maGeometry.nRightDecoration;
508 nHeight += maGeometry.nTopDecoration + maGeometry.nBottomDecoration;
510 NSSize aSize = { static_cast<CGFloat>(nWidth), static_cast<CGFloat>(nHeight) };
512 // Size of full window (content+structure) although we only
513 // have the client size in arguments
514 [mpWindow setMinSize: aSize];
518 // -----------------------------------------------------------------------
520 void AquaSalFrame::SetMaxClientSize( long nWidth, long nHeight )
522 // #i113170# may not be the main thread if called from UNO API
523 SalData::ensureThreadAutoreleasePool();
525 mnMaxWidth = nWidth;
526 mnMaxHeight = nHeight;
528 if( mpWindow )
530 // Always add the decoration as the dimension concerns only
531 // the content rectangle
532 nWidth += maGeometry.nLeftDecoration + maGeometry.nRightDecoration;
533 nHeight += maGeometry.nTopDecoration + maGeometry.nBottomDecoration;
535 // Carbon windows can't have a size greater than 32767x32767
536 if (nWidth>32767) nWidth=32767;
537 if (nHeight>32767) nHeight=32767;
539 NSSize aSize = { static_cast<CGFloat>(nWidth), static_cast<CGFloat>(nHeight) };
541 // Size of full window (content+structure) although we only
542 // have the client size in arguments
543 [mpWindow setMaxSize: aSize];
547 // -----------------------------------------------------------------------
549 void AquaSalFrame::SetClientSize( long nWidth, long nHeight )
551 // #i113170# may not be the main thread if called from UNO API
552 SalData::ensureThreadAutoreleasePool();
554 if( mpWindow )
556 NSSize aSize = { static_cast<CGFloat>(nWidth), static_cast<CGFloat>(nHeight) };
558 [mpWindow setContentSize: aSize];
559 UpdateFrameGeometry();
560 if( mbShown )
561 // trigger filling our backbuffer
562 SendPaintEvent();
566 // -----------------------------------------------------------------------
568 void AquaSalFrame::GetClientSize( long& rWidth, long& rHeight )
570 if( mbShown || mbInitShow )
572 rWidth = maGeometry.nWidth;
573 rHeight = maGeometry.nHeight;
575 else
577 rWidth = 0;
578 rHeight = 0;
582 // -----------------------------------------------------------------------
584 void AquaSalFrame::SetWindowState( const SalFrameState* pState )
586 // #i113170# may not be the main thread if called from UNO API
587 SalData::ensureThreadAutoreleasePool();
589 if ( mpWindow )
591 // set normal state
592 NSRect aStateRect = [mpWindow frame];
593 aStateRect = [NSWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask];
594 CocoaToVCL( aStateRect );
595 if( pState->mnMask & WINDOWSTATE_MASK_X )
596 aStateRect.origin.x = float(pState->mnX);
597 if( pState->mnMask & WINDOWSTATE_MASK_Y )
598 aStateRect.origin.y = float(pState->mnY);
599 if( pState->mnMask & WINDOWSTATE_MASK_WIDTH )
600 aStateRect.size.width = float(pState->mnWidth);
601 if( pState->mnMask & WINDOWSTATE_MASK_HEIGHT )
602 aStateRect.size.height = float(pState->mnHeight);
603 VCLToCocoa( aStateRect );
604 aStateRect = [NSWindow frameRectForContentRect: aStateRect styleMask: mnStyleMask];
606 [mpWindow setFrame: aStateRect display: NO];
607 if( pState->mnState == WINDOWSTATE_STATE_MINIMIZED )
608 [mpWindow miniaturize: NSApp];
609 else if( [mpWindow isMiniaturized] )
610 [mpWindow deminiaturize: NSApp];
613 /* ZOOMED is not really maximized (actually it toggles between a user set size and
614 the program specified one), but comes closest since the default behavior is
615 "maximized" if the user did not intervene
617 if( pState->mnState == WINDOWSTATE_STATE_MAXIMIZED )
619 if(! [mpWindow isZoomed])
620 [mpWindow zoom: NSApp];
622 else
624 if( [mpWindow isZoomed] )
625 [mpWindow zoom: NSApp];
629 // get new geometry
630 UpdateFrameGeometry();
632 sal_uInt16 nEvent = 0;
633 if( pState->mnMask & (WINDOWSTATE_MASK_X | WINDOWSTATE_MASK_Y) )
635 mbPositioned = true;
636 nEvent = SALEVENT_MOVE;
639 if( pState->mnMask & (WINDOWSTATE_MASK_WIDTH | WINDOWSTATE_MASK_HEIGHT) )
641 mbSized = true;
642 nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE;
644 // send event that we were moved/sized
645 if( nEvent )
646 CallCallback( nEvent, NULL );
648 if( mbShown && mpWindow )
650 // trigger filling our backbuffer
651 SendPaintEvent();
653 // tell the system the views need to be updated
654 [mpWindow display];
658 // -----------------------------------------------------------------------
660 sal_Bool AquaSalFrame::GetWindowState( SalFrameState* pState )
662 if ( !mpWindow )
663 return FALSE;
665 // #i113170# may not be the main thread if called from UNO API
666 SalData::ensureThreadAutoreleasePool();
668 pState->mnMask = WINDOWSTATE_MASK_X |
669 WINDOWSTATE_MASK_Y |
670 WINDOWSTATE_MASK_WIDTH |
671 WINDOWSTATE_MASK_HEIGHT |
672 WINDOWSTATE_MASK_STATE;
674 NSRect aStateRect = [mpWindow frame];
675 aStateRect = [NSWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask];
676 CocoaToVCL( aStateRect );
677 pState->mnX = long(aStateRect.origin.x);
678 pState->mnY = long(aStateRect.origin.y);
679 pState->mnWidth = long(aStateRect.size.width);
680 pState->mnHeight = long(aStateRect.size.height);
682 if( [mpWindow isMiniaturized] )
683 pState->mnState = WINDOWSTATE_STATE_MINIMIZED;
684 else if( ! [mpWindow isZoomed] )
685 pState->mnState = WINDOWSTATE_STATE_NORMAL;
686 else
687 pState->mnState = WINDOWSTATE_STATE_MAXIMIZED;
689 return TRUE;
692 // -----------------------------------------------------------------------
694 void AquaSalFrame::SetScreenNumber(unsigned int nScreen)
696 if ( !mpWindow )
697 return;
699 // #i113170# may not be the main thread if called from UNO API
700 SalData::ensureThreadAutoreleasePool();
702 NSArray* pScreens = [NSScreen screens];
703 Rectangle aRet;
704 NSScreen* pScreen = nil;
705 if( pScreens && nScreen < [pScreens count] )
707 // get new screen frame
708 pScreen = [pScreens objectAtIndex: nScreen];
709 NSRect aNewScreen = [pScreen frame];
711 // get current screen frame
712 pScreen = [mpWindow screen];
713 if( pScreen )
715 NSRect aCurScreen = [pScreen frame];
716 if( aCurScreen.origin.x != aNewScreen.origin.x ||
717 aCurScreen.origin.y != aNewScreen.origin.y )
719 NSRect aFrameRect = [mpWindow frame];
720 aFrameRect.origin.x += aNewScreen.origin.x - aCurScreen.origin.x;
721 aFrameRect.origin.y += aNewScreen.origin.y - aCurScreen.origin.y;
722 [mpWindow setFrame: aFrameRect display: NO];
723 UpdateFrameGeometry();
729 void AquaSalFrame::SetApplicationID( const OUString &/*rApplicationID*/ )
733 // -----------------------------------------------------------------------
735 void AquaSalFrame::ShowFullScreen( sal_Bool bFullScreen, sal_Int32 nDisplay )
737 if ( !mpWindow )
738 return;
740 // #i113170# may not be the main thread if called from UNO API
741 SalData::ensureThreadAutoreleasePool();
743 SAL_INFO("vcl.macosx", OSL_THIS_FUNC << ": mbFullScreen=" << mbFullScreen << ", bFullScreen=" << bFullScreen);
745 if( mbFullScreen == bFullScreen )
746 return;
748 mbFullScreen = bFullScreen;
750 if( bFullScreen )
752 // hide the dock and the menubar if we are on the menu screen
753 // which is always on index 0 according to documentation
754 bool bHideMenu = (nDisplay == 0);
756 NSRect aNewContentRect = { { 0, 0 }, { 0, 0 } };
757 // get correct screen
758 NSScreen* pScreen = nil;
759 NSArray* pScreens = [NSScreen screens];
760 if( pScreens )
762 if( nDisplay >= 0 && (unsigned int)nDisplay < [pScreens count] )
763 pScreen = [pScreens objectAtIndex: nDisplay];
764 else
766 // this means span all screens
767 bHideMenu = true;
768 NSEnumerator* pEnum = [pScreens objectEnumerator];
769 while( (pScreen = [pEnum nextObject]) != nil )
771 NSRect aScreenRect = [pScreen frame];
772 if( aScreenRect.origin.x < aNewContentRect.origin.x )
774 aNewContentRect.size.width += aNewContentRect.origin.x - aScreenRect.origin.x;
775 aNewContentRect.origin.x = aScreenRect.origin.x;
777 if( aScreenRect.origin.y < aNewContentRect.origin.y )
779 aNewContentRect.size.height += aNewContentRect.origin.y - aScreenRect.origin.y;
780 aNewContentRect.origin.y = aScreenRect.origin.y;
782 if( aScreenRect.origin.x + aScreenRect.size.width > aNewContentRect.origin.x + aNewContentRect.size.width )
783 aNewContentRect.size.width = aScreenRect.origin.x + aScreenRect.size.width - aNewContentRect.origin.x;
784 if( aScreenRect.origin.y + aScreenRect.size.height > aNewContentRect.origin.y + aNewContentRect.size.height )
785 aNewContentRect.size.height = aScreenRect.origin.y + aScreenRect.size.height - aNewContentRect.origin.y;
789 if( aNewContentRect.size.width == 0 && aNewContentRect.size.height == 0 )
791 if( pScreen == nil )
792 pScreen = [mpWindow screen];
793 if( pScreen == nil )
794 pScreen = [NSScreen mainScreen];
796 aNewContentRect = [pScreen frame];
799 if( bHideMenu )
800 [NSMenu setMenuBarVisible:NO];
802 maFullScreenRect = [mpWindow frame];
804 [mpWindow setFrame: [NSWindow frameRectForContentRect: aNewContentRect styleMask: mnStyleMask] display: mbShown ? YES : NO];
807 UpdateFrameGeometry();
809 if( mbShown )
810 CallCallback( SALEVENT_MOVERESIZE, NULL );
812 else
815 [mpWindow setFrame: maFullScreenRect display: mbShown ? YES : NO];
817 UpdateFrameGeometry();
819 if( mbShown )
820 CallCallback( SALEVENT_MOVERESIZE, NULL );
822 // show the dock and the menubar
823 [NSMenu setMenuBarVisible:YES];
825 if( mbShown )
826 // trigger filling our backbuffer
827 SendPaintEvent();
830 // -----------------------------------------------------------------------
832 void AquaSalFrame::StartPresentation( sal_Bool bStart )
834 if ( !mpWindow )
835 return;
837 // #i113170# may not be the main thread if called from UNO API
838 SalData::ensureThreadAutoreleasePool();
840 if( bStart )
842 GetSalData()->maPresentationFrames.push_back( this );
843 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
844 kIOPMAssertionLevelOn,
845 CFSTR("LibreOffice presentation running"),
846 &mnAssertionID);
847 [mpWindow setLevel: NSPopUpMenuWindowLevel];
848 if( mbShown )
849 [mpWindow makeMainWindow];
851 else
853 GetSalData()->maPresentationFrames.remove( this );
854 IOPMAssertionRelease(mnAssertionID);
855 [mpWindow setLevel: NSNormalWindowLevel];
859 // -----------------------------------------------------------------------
861 void AquaSalFrame::SetAlwaysOnTop( sal_Bool )
865 // -----------------------------------------------------------------------
867 void AquaSalFrame::ToTop(sal_uInt16 nFlags)
869 if ( !mpWindow )
870 return;
872 // #i113170# may not be the main thread if called from UNO API
873 SalData::ensureThreadAutoreleasePool();
875 if( ! (nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN) )
877 if( ! [mpWindow isVisible] || [mpWindow isMiniaturized] )
878 return;
880 if( nFlags & SAL_FRAME_TOTOP_GRABFOCUS )
881 [mpWindow makeKeyAndOrderFront: NSApp];
882 else
883 [mpWindow orderFront: NSApp];
886 // -----------------------------------------------------------------------
888 NSCursor* AquaSalFrame::getCurrentCursor() const
890 NSCursor* pCursor = nil;
891 switch( mePointerStyle )
893 case POINTER_TEXT: pCursor = [NSCursor IBeamCursor]; break;
894 case POINTER_CROSS: pCursor = [NSCursor crosshairCursor]; break;
895 case POINTER_HAND:
896 case POINTER_MOVE: pCursor = [NSCursor openHandCursor]; break;
897 case POINTER_NSIZE: pCursor = [NSCursor resizeUpCursor]; break;
898 case POINTER_SSIZE: pCursor = [NSCursor resizeDownCursor]; break;
899 case POINTER_ESIZE: pCursor = [NSCursor resizeRightCursor]; break;
900 case POINTER_WSIZE: pCursor = [NSCursor resizeLeftCursor]; break;
901 case POINTER_ARROW: pCursor = [NSCursor arrowCursor]; break;
902 case POINTER_VSPLIT:
903 case POINTER_VSIZEBAR:
904 case POINTER_WINDOW_NSIZE:
905 case POINTER_WINDOW_SSIZE:
906 pCursor = [NSCursor resizeUpDownCursor]; break;
907 case POINTER_HSPLIT:
908 case POINTER_HSIZEBAR:
909 case POINTER_WINDOW_ESIZE:
910 case POINTER_WINDOW_WSIZE:
911 pCursor = [NSCursor resizeLeftRightCursor]; break;
912 case POINTER_REFHAND: pCursor = [NSCursor pointingHandCursor]; break;
913 case POINTER_NULL: [NSCursor hide]; break;
915 default:
916 pCursor = GetSalData()->getCursor( mePointerStyle );
917 if( pCursor == nil )
919 OSL_FAIL( "unmapped cursor" );
920 pCursor = [NSCursor arrowCursor];
922 break;
924 return pCursor;
927 void AquaSalFrame::SetPointer( PointerStyle ePointerStyle )
929 if ( !mpWindow )
930 return;
932 // #i113170# may not be the main thread if called from UNO API
933 SalData::ensureThreadAutoreleasePool();
935 if( ePointerStyle >= POINTER_COUNT || ePointerStyle == mePointerStyle )
936 return;
937 mePointerStyle = ePointerStyle;
939 [mpWindow invalidateCursorRectsForView: mpView];
942 // -----------------------------------------------------------------------
944 void AquaSalFrame::SetPointerPos( long nX, long nY )
946 // FIXME: use Cocoa functions
948 // FIXME: multiscreen support
949 CGPoint aPoint = { static_cast<CGFloat>(nX + maGeometry.nX), static_cast<CGFloat>(nY + maGeometry.nY) };
950 CGDirectDisplayID mainDisplayID = CGMainDisplayID();
951 CGDisplayMoveCursorToPoint( mainDisplayID, aPoint );
954 // -----------------------------------------------------------------------
956 void AquaSalFrame::Flush( void )
958 if( !(mbGraphics && mpGraphics && mpView && mbShown) )
959 return;
961 // #i113170# may not be the main thread if called from UNO API
962 SalData::ensureThreadAutoreleasePool();
965 [mpView setNeedsDisplay: YES];
967 // outside of the application's event loop (e.g. IntroWindow)
968 // nothing would trigger paint event handling
969 // => fall back to synchronous painting
970 if( ImplGetSVData()->maAppData.mnDispatchLevel <= 0 )
972 [mpView display];
976 // -----------------------------------------------------------------------
978 void AquaSalFrame::Flush( const Rectangle& rRect )
980 if( !(mbGraphics && mpGraphics && mpView && mbShown) )
981 return;
983 // #i113170# may not be the main thread if called from UNO API
984 SalData::ensureThreadAutoreleasePool();
986 NSRect aNSRect = { { static_cast<CGFloat>(rRect.Left()), static_cast<CGFloat>(rRect.Top()) }, { static_cast<CGFloat>(rRect.GetWidth()), static_cast<CGFloat>(rRect.GetHeight()) } };
987 VCLToCocoa( aNSRect, false );
988 [mpView setNeedsDisplayInRect: aNSRect];
990 // outside of the application's event loop (e.g. IntroWindow)
991 // nothing would trigger paint event handling
992 // => fall back to synchronous painting
993 if( ImplGetSVData()->maAppData.mnDispatchLevel <= 0 )
995 [mpView display];
999 // -----------------------------------------------------------------------
1001 void AquaSalFrame::Sync()
1003 if( mbGraphics && mpGraphics && mpView && mbShown )
1005 // #i113170# may not be the main thread if called from UNO API
1006 SalData::ensureThreadAutoreleasePool();
1008 [mpView setNeedsDisplay: YES];
1009 [mpView display];
1013 // -----------------------------------------------------------------------
1015 void AquaSalFrame::SetInputContext( SalInputContext* pContext )
1017 if (!pContext)
1019 mnICOptions = 0;
1020 return;
1023 mnICOptions = pContext->mnOptions;
1025 if(!(pContext->mnOptions & SAL_INPUTCONTEXT_TEXT))
1026 return;
1029 // -----------------------------------------------------------------------
1031 void AquaSalFrame::EndExtTextInput( sal_uInt16 )
1035 // -----------------------------------------------------------------------
1037 OUString AquaSalFrame::GetKeyName( sal_uInt16 nKeyCode )
1039 static std::map< sal_uInt16, OUString > aKeyMap;
1040 if( aKeyMap.empty() )
1042 sal_uInt16 i;
1043 for( i = KEY_A; i <= KEY_Z; i++ )
1044 aKeyMap[ i ] = OUString( sal_Unicode( 'A' + (i - KEY_A) ) );
1045 for( i = KEY_0; i <= KEY_9; i++ )
1046 aKeyMap[ i ] = OUString( sal_Unicode( '0' + (i - KEY_0) ) );
1047 for( i = KEY_F1; i <= KEY_F26; i++ )
1049 OUStringBuffer aKey( 3 );
1050 aKey.append( 'F' );
1051 aKey.append( sal_Int32( i - KEY_F1 + 1 ) );
1052 aKeyMap[ i ] = aKey.makeStringAndClear();
1055 aKeyMap[ KEY_DOWN ] = OUString( sal_Unicode( 0x21e3 ) );
1056 aKeyMap[ KEY_UP ] = OUString( sal_Unicode( 0x21e1 ) );
1057 aKeyMap[ KEY_LEFT ] = OUString( sal_Unicode( 0x21e0 ) );
1058 aKeyMap[ KEY_RIGHT ] = OUString( sal_Unicode( 0x21e2 ) );
1059 aKeyMap[ KEY_HOME ] = OUString( sal_Unicode( 0x2196 ) );
1060 aKeyMap[ KEY_END ] = OUString( sal_Unicode( 0x2198 ) );
1061 aKeyMap[ KEY_PAGEUP ] = OUString( sal_Unicode( 0x21de ) );
1062 aKeyMap[ KEY_PAGEDOWN ] = OUString( sal_Unicode( 0x21df ) );
1063 aKeyMap[ KEY_RETURN ] = OUString( sal_Unicode( 0x21a9 ) );
1064 aKeyMap[ KEY_ESCAPE ] = OUString( "esc" );
1065 aKeyMap[ KEY_TAB ] = OUString( sal_Unicode( 0x21e5 ) );
1066 aKeyMap[ KEY_BACKSPACE ]= OUString( sal_Unicode( 0x232b ) );
1067 aKeyMap[ KEY_SPACE ] = OUString( sal_Unicode( 0x2423 ) );
1068 aKeyMap[ KEY_DELETE ] = OUString( sal_Unicode( 0x2326 ) );
1069 aKeyMap[ KEY_ADD ] = OUString( '+' );
1070 aKeyMap[ KEY_SUBTRACT ] = OUString( '-' );
1071 aKeyMap[ KEY_DIVIDE ] = OUString( '/' );
1072 aKeyMap[ KEY_MULTIPLY ] = OUString( '*' );
1073 aKeyMap[ KEY_POINT ] = OUString( '.' );
1074 aKeyMap[ KEY_COMMA ] = OUString( ',' );
1075 aKeyMap[ KEY_LESS ] = OUString( '<' );
1076 aKeyMap[ KEY_GREATER ] = OUString( '>' );
1077 aKeyMap[ KEY_EQUAL ] = OUString( '=' );
1078 aKeyMap[ KEY_OPEN ] = OUString( sal_Unicode( 0x23cf ) );
1080 /* yet unmapped KEYCODES:
1081 aKeyMap[ KEY_INSERT ] = OUString( sal_Unicode( ) );
1082 aKeyMap[ KEY_CUT ] = OUString( sal_Unicode( ) );
1083 aKeyMap[ KEY_COPY ] = OUString( sal_Unicode( ) );
1084 aKeyMap[ KEY_PASTE ] = OUString( sal_Unicode( ) );
1085 aKeyMap[ KEY_UNDO ] = OUString( sal_Unicode( ) );
1086 aKeyMap[ KEY_REPEAT ] = OUString( sal_Unicode( ) );
1087 aKeyMap[ KEY_FIND ] = OUString( sal_Unicode( ) );
1088 aKeyMap[ KEY_PROPERTIES ] = OUString( sal_Unicode( ) );
1089 aKeyMap[ KEY_FRONT ] = OUString( sal_Unicode( ) );
1090 aKeyMap[ KEY_CONTEXTMENU ] = OUString( sal_Unicode( ) );
1091 aKeyMap[ KEY_MENU ] = OUString( sal_Unicode( ) );
1092 aKeyMap[ KEY_HELP ] = OUString( sal_Unicode( ) );
1093 aKeyMap[ KEY_HANGUL_HANJA ] = OUString( sal_Unicode( ) );
1094 aKeyMap[ KEY_DECIMAL ] = OUString( sal_Unicode( ) );
1095 aKeyMap[ KEY_TILDE ] = OUString( sal_Unicode( ) );
1096 aKeyMap[ KEY_QUOTELEFT ]= OUString( sal_Unicode( ) );
1101 OUStringBuffer aResult( 16 );
1103 sal_uInt16 nUnmodifiedCode = (nKeyCode & KEY_CODE);
1104 std::map< sal_uInt16, OUString >::const_iterator it = aKeyMap.find( nUnmodifiedCode );
1105 if( it != aKeyMap.end() )
1107 if( (nKeyCode & KEY_SHIFT) != 0 )
1108 aResult.append( sal_Unicode( 0x21e7 ) );
1109 if( (nKeyCode & KEY_MOD1) != 0 )
1110 aResult.append( sal_Unicode( 0x2318 ) );
1111 // we do not really handle Alt (see below)
1112 // we map it to MOD3, whichis actually Command
1113 if( (nKeyCode & (KEY_MOD2|KEY_MOD3)) != 0 )
1114 aResult.append( sal_Unicode( 0x2303 ) );
1116 aResult.append( it->second );
1119 return aResult.makeStringAndClear();
1122 // -----------------------------------------------------------------------
1124 static void getAppleScrollBarVariant(StyleSettings &rSettings)
1126 bool bIsScrollbarDoubleMax = true; // default is DoubleMax
1128 CFStringRef AppleScrollBarType = CFSTR("AppleScrollBarVariant");
1129 if( AppleScrollBarType )
1131 CFStringRef ScrollBarVariant = ((CFStringRef)CFPreferencesCopyAppValue( AppleScrollBarType, kCFPreferencesCurrentApplication ));
1132 if( ScrollBarVariant )
1134 if( CFGetTypeID( ScrollBarVariant ) == CFStringGetTypeID() )
1136 // TODO: check for the less important variants "DoubleMin" and "DoubleBoth" too
1137 CFStringRef DoubleMax = CFSTR("DoubleMax");
1138 if (DoubleMax)
1140 if ( !CFStringCompare(ScrollBarVariant, DoubleMax, kCFCompareCaseInsensitive) )
1141 bIsScrollbarDoubleMax = true;
1142 else
1143 bIsScrollbarDoubleMax = false;
1144 CFRelease(DoubleMax);
1147 CFRelease( ScrollBarVariant );
1149 CFRelease(AppleScrollBarType);
1152 GetSalData()->mbIsScrollbarDoubleMax = bIsScrollbarDoubleMax;
1154 CFStringRef jumpScroll = CFSTR("AppleScrollerPagingBehavior");
1155 if( jumpScroll )
1157 CFBooleanRef jumpStr = ((CFBooleanRef)CFPreferencesCopyAppValue( jumpScroll, kCFPreferencesCurrentApplication ));
1158 if( jumpStr )
1160 if( CFGetTypeID( jumpStr ) == CFBooleanGetTypeID() )
1161 rSettings.SetPrimaryButtonWarpsSlider(jumpStr == kCFBooleanTrue);
1162 CFRelease( jumpStr );
1164 CFRelease( jumpScroll );
1168 static Color getColor( NSColor* pSysColor, const Color& rDefault, NSWindow* pWin )
1170 Color aRet( rDefault );
1171 if( pSysColor )
1173 // transform to RGB
1174 NSColor* pRBGColor = [pSysColor colorUsingColorSpaceName: NSDeviceRGBColorSpace device: [pWin deviceDescription]];
1175 if( pRBGColor )
1177 CGFloat r = 0, g = 0, b = 0, a = 0;
1178 [pRBGColor getRed: &r green: &g blue: &b alpha: &a];
1179 aRet = Color( int(r*255.999), int(g*255.999), int(b*255.999) );
1181 do not release here; leads to duplicate free in yield
1182 it seems the converted color comes out autoreleased, although this
1183 is not documented
1184 [pRBGColor release];
1188 return aRet;
1191 static Font getFont( NSFont* pFont, long nDPIY, const Font& rDefault )
1193 Font aResult( rDefault );
1194 if( pFont )
1196 aResult.SetName( GetOUString( [pFont familyName] ) );
1197 aResult.SetHeight( static_cast<int>(([pFont pointSize] * 72.0 / (float)nDPIY)+0.5) );
1198 aResult.SetItalic( ([pFont italicAngle] != 0.0) ? ITALIC_NORMAL : ITALIC_NONE );
1199 // FIMXE: bold ?
1202 return aResult;
1205 void AquaSalFrame::getResolution( sal_Int32& o_rDPIX, sal_Int32& o_rDPIY )
1207 if( ! mpGraphics )
1209 GetGraphics();
1210 ReleaseGraphics( mpGraphics );
1212 mpGraphics->GetResolution( o_rDPIX, o_rDPIY );
1215 // on OSX-Aqua the style settings are independent of the frame, so it does
1216 // not really belong here. Since the connection to the Appearance_Manager
1217 // is currently done in salnativewidgets.cxx this would be a good place.
1218 // On the other hand VCL's platform independent code currently only asks
1219 // SalFrames for system settings anyway, so moving the code somewhere else
1220 // doesn't make the anything cleaner for now
1221 void AquaSalFrame::UpdateSettings( AllSettings& rSettings )
1223 if ( !mpWindow )
1224 return;
1226 // #i113170# may not be the main thread if called from UNO API
1227 SalData::ensureThreadAutoreleasePool();
1229 [mpView lockFocus];
1231 StyleSettings aStyleSettings = rSettings.GetStyleSettings();
1233 // Background Color
1234 Color aBackgroundColor = Color( 0xEC, 0xEC, 0xEC );
1235 aStyleSettings.Set3DColors( aBackgroundColor );
1236 aStyleSettings.SetFaceColor( aBackgroundColor );
1237 Color aInactiveTabColor( aBackgroundColor );
1238 aInactiveTabColor.DecreaseLuminance( 32 );
1239 aStyleSettings.SetInactiveTabColor( aInactiveTabColor );
1241 aStyleSettings.SetDialogColor( aBackgroundColor );
1242 aStyleSettings.SetLightBorderColor( aBackgroundColor );
1243 Color aShadowColor( aStyleSettings.GetShadowColor() );
1244 aShadowColor.IncreaseLuminance( 32 );
1245 aStyleSettings.SetShadowColor( aShadowColor );
1247 // get the system font settings
1248 Font aAppFont = aStyleSettings.GetAppFont();
1249 sal_Int32 nDPIX = 72, nDPIY = 72;
1250 getResolution( nDPIX, nDPIY );
1251 aAppFont = getFont( [NSFont systemFontOfSize: 0], nDPIY, aAppFont );
1253 aStyleSettings.SetToolbarIconSize( STYLE_TOOLBAR_ICONSIZE_LARGE );
1255 // TODO: better mapping of aqua<->ooo font settings
1256 aStyleSettings.SetAppFont( aAppFont );
1257 aStyleSettings.SetHelpFont( aAppFont );
1258 aStyleSettings.SetPushButtonFont( aAppFont );
1260 Font aTitleFont( getFont( [NSFont titleBarFontOfSize: 0], nDPIY, aAppFont ) );
1261 aStyleSettings.SetTitleFont( aTitleFont );
1262 aStyleSettings.SetFloatTitleFont( aTitleFont );
1264 Font aMenuFont( getFont( [NSFont menuFontOfSize: 0], nDPIY, aAppFont ) );
1265 aStyleSettings.SetMenuFont( aMenuFont );
1267 aStyleSettings.SetToolFont( aAppFont );
1269 Font aLabelFont( getFont( [NSFont labelFontOfSize: 0], nDPIY, aAppFont ) );
1270 aStyleSettings.SetLabelFont( aLabelFont );
1271 aStyleSettings.SetInfoFont( aLabelFont );
1272 aStyleSettings.SetRadioCheckFont( aLabelFont );
1273 aStyleSettings.SetFieldFont( aLabelFont );
1274 aStyleSettings.SetGroupFont( aLabelFont );
1275 aStyleSettings.SetIconFont( aLabelFont );
1277 Color aHighlightColor( getColor( [NSColor selectedTextBackgroundColor],
1278 aStyleSettings.GetHighlightColor(), mpWindow ) );
1279 aStyleSettings.SetHighlightColor( aHighlightColor );
1280 Color aHighlightTextColor( getColor( [NSColor selectedTextColor],
1281 aStyleSettings.GetHighlightTextColor(), mpWindow ) );
1282 aStyleSettings.SetHighlightTextColor( aHighlightTextColor );
1284 Color aMenuHighlightColor( getColor( [NSColor selectedMenuItemColor],
1285 aStyleSettings.GetMenuHighlightColor(), mpWindow ) );
1286 aStyleSettings.SetMenuHighlightColor( aMenuHighlightColor );
1287 Color aMenuHighlightTextColor( getColor( [NSColor selectedMenuItemTextColor],
1288 aStyleSettings.GetMenuHighlightTextColor(), mpWindow ) );
1289 aStyleSettings.SetMenuHighlightTextColor( aMenuHighlightTextColor );
1291 aStyleSettings.SetMenuColor( aBackgroundColor );
1292 Color aMenuTextColor( getColor( [NSColor textColor],
1293 aStyleSettings.GetMenuTextColor(), mpWindow ) );
1294 aStyleSettings.SetMenuTextColor( aMenuTextColor );
1295 aStyleSettings.SetMenuBarTextColor( aMenuTextColor );
1296 aStyleSettings.SetMenuBarRolloverTextColor( aMenuTextColor );
1298 aStyleSettings.SetCursorBlinkTime( 500 );
1300 // no mnemonics on aqua
1301 aStyleSettings.SetOptions( aStyleSettings.GetOptions() | STYLE_OPTION_NOMNEMONICS );
1303 getAppleScrollBarVariant(aStyleSettings);
1305 // set scrollbar size
1306 aStyleSettings.SetScrollBarSize( static_cast<long int>([NSScroller scrollerWidth]) );
1308 // images in menus false for MacOSX
1309 aStyleSettings.SetPreferredUseImagesInMenus( false );
1310 aStyleSettings.SetHideDisabledMenuItems( sal_True );
1311 aStyleSettings.SetAcceleratorsInContextMenus( sal_False );
1313 rSettings.SetStyleSettings( aStyleSettings );
1315 [mpView unlockFocus];
1318 // -----------------------------------------------------------------------
1320 const SystemEnvData* AquaSalFrame::GetSystemData() const
1322 return &maSysData;
1325 // -----------------------------------------------------------------------
1327 void AquaSalFrame::Beep()
1329 NSBeep();
1332 // -----------------------------------------------------------------------
1334 void AquaSalFrame::SetPosSize(long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags)
1336 if ( !mpWindow )
1337 return;
1339 // #i113170# may not be the main thread if called from UNO API
1340 SalData::ensureThreadAutoreleasePool();
1342 sal_uInt16 nEvent = 0;
1344 if( [mpWindow isMiniaturized] )
1345 [mpWindow deminiaturize: NSApp]; // expand the window
1347 if (nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y))
1349 mbPositioned = true;
1350 nEvent = SALEVENT_MOVE;
1353 if (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT))
1355 mbSized = true;
1356 nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE;
1359 NSRect aFrameRect = [mpWindow frame];
1360 NSRect aContentRect = [NSWindow contentRectForFrameRect: aFrameRect styleMask: mnStyleMask];
1362 // position is always relative to parent frame
1363 NSRect aParentContentRect;
1365 if( mpParent )
1367 if( Application::GetSettings().GetLayoutRTL() )
1369 if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 )
1370 nX = mpParent->maGeometry.nWidth - nWidth-1 - nX;
1371 else
1372 nX = mpParent->maGeometry.nWidth - static_cast<long int>( aContentRect.size.width-1) - nX;
1374 NSRect aParentFrameRect = [mpParent->mpWindow frame];
1375 aParentContentRect = [NSWindow contentRectForFrameRect: aParentFrameRect styleMask: mpParent->mnStyleMask];
1377 else
1378 aParentContentRect = maScreenRect; // use screen if no parent
1380 CocoaToVCL( aContentRect );
1381 CocoaToVCL( aParentContentRect );
1383 bool bPaint = false;
1384 if( (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) != 0 )
1386 if( nWidth != aContentRect.size.width || nHeight != aContentRect.size.height )
1387 bPaint = true;
1390 // use old window pos if no new pos requested
1391 if( (nFlags & SAL_FRAME_POSSIZE_X) != 0 )
1392 aContentRect.origin.x = nX + aParentContentRect.origin.x;
1393 if( (nFlags & SAL_FRAME_POSSIZE_Y) != 0)
1394 aContentRect.origin.y = nY + aParentContentRect.origin.y;
1396 // use old size if no new size requested
1397 if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 )
1398 aContentRect.size.width = nWidth;
1399 if( (nFlags & SAL_FRAME_POSSIZE_HEIGHT) != 0)
1400 aContentRect.size.height = nHeight;
1402 VCLToCocoa( aContentRect );
1404 // do not display yet, we need to update our backbuffer
1406 [mpWindow setFrame: [NSWindow frameRectForContentRect: aContentRect styleMask: mnStyleMask] display: NO];
1409 UpdateFrameGeometry();
1411 if (nEvent)
1412 CallCallback(nEvent, NULL);
1414 if( mbShown && bPaint )
1416 // trigger filling our backbuffer
1417 SendPaintEvent();
1419 // now inform the system that the views need to be drawn
1420 [mpWindow display];
1424 void AquaSalFrame::GetWorkArea( Rectangle& rRect )
1426 if ( !mpWindow )
1427 return;
1429 // #i113170# may not be the main thread if called from UNO API
1430 SalData::ensureThreadAutoreleasePool();
1432 NSScreen* pScreen = [mpWindow screen];
1433 if( pScreen == nil )
1434 pScreen = [NSScreen mainScreen];
1435 NSRect aRect = [pScreen visibleFrame];
1436 CocoaToVCL( aRect );
1437 rRect.Left() = static_cast<long>(aRect.origin.x);
1438 rRect.Top() = static_cast<long>(aRect.origin.y);
1439 rRect.Right() = static_cast<long>(aRect.origin.x + aRect.size.width - 1);
1440 rRect.Bottom() = static_cast<long>(aRect.origin.y + aRect.size.height - 1);
1443 SalPointerState AquaSalFrame::GetPointerState()
1445 // #i113170# may not be the main thread if called from UNO API
1446 SalData::ensureThreadAutoreleasePool();
1448 SalPointerState state;
1449 state.mnState = 0;
1451 // get position
1452 NSPoint aPt = [mpWindow mouseLocationOutsideOfEventStream];
1453 CocoaToVCL( aPt, false );
1454 state.maPos = Point(static_cast<long>(aPt.x), static_cast<long>(aPt.y));
1456 NSEvent* pCur = [NSApp currentEvent];
1457 bool bMouseEvent = false;
1458 if( pCur )
1460 bMouseEvent = true;
1461 switch( [pCur type] )
1463 case NSLeftMouseDown: state.mnState |= MOUSE_LEFT; break;
1464 case NSLeftMouseUp: break;
1465 case NSRightMouseDown: state.mnState |= MOUSE_RIGHT; break;
1466 case NSRightMouseUp: break;
1467 case NSOtherMouseDown: state.mnState |= ([pCur buttonNumber] == 2) ? MOUSE_MIDDLE : 0; break;
1468 case NSOtherMouseUp: break;
1469 case NSMouseMoved: break;
1470 case NSLeftMouseDragged: state.mnState |= MOUSE_LEFT; break;
1471 case NSRightMouseDragged: state.mnState |= MOUSE_RIGHT; break;
1472 case NSOtherMouseDragged: state.mnState |= ([pCur buttonNumber] == 2) ? MOUSE_MIDDLE : 0; break;
1473 break;
1474 default:
1475 bMouseEvent = false;
1476 break;
1479 if( bMouseEvent )
1481 unsigned int nMask = (unsigned int)[pCur modifierFlags];
1482 if( (nMask & NSShiftKeyMask) != 0 )
1483 state.mnState |= KEY_SHIFT;
1484 if( (nMask & NSControlKeyMask) != 0 )
1485 state.mnState |= KEY_MOD3;
1486 if( (nMask & NSAlternateKeyMask) != 0 )
1487 state.mnState |= KEY_MOD2;
1488 if( (nMask & NSCommandKeyMask) != 0 )
1489 state.mnState |= KEY_MOD1;
1492 else
1494 // FIXME: replace Carbon by Cocoa
1495 // Cocoa does not have an equivalent for GetCurrentEventButtonState
1496 // and GetCurrentEventKeyModifiers.
1497 // we could try to get away with tracking all events for modifierKeys
1498 // and all mouse events for button state in VCL_NSApllication::sendEvent,
1499 // but it is unclear whether this will get us the same result.
1500 // leave in GetCurrentEventButtonState and GetCurrentEventKeyModifiers for now
1502 // fill in button state
1503 UInt32 nState = GetCurrentEventButtonState();
1504 state.mnState = 0;
1505 if( nState & 1 )
1506 state.mnState |= MOUSE_LEFT; // primary button
1507 if( nState & 2 )
1508 state.mnState |= MOUSE_RIGHT; // secondary button
1509 if( nState & 4 )
1510 state.mnState |= MOUSE_MIDDLE; // tertiary button
1512 // fill in modifier state
1513 nState = GetCurrentEventKeyModifiers();
1514 if( nState & shiftKey )
1515 state.mnState |= KEY_SHIFT;
1516 if( nState & controlKey )
1517 state.mnState |= KEY_MOD3;
1518 if( nState & optionKey )
1519 state.mnState |= KEY_MOD2;
1520 if( nState & cmdKey )
1521 state.mnState |= KEY_MOD1;
1525 return state;
1528 SalFrame::SalIndicatorState AquaSalFrame::GetIndicatorState()
1530 SalIndicatorState aState;
1531 aState.mnState = 0;
1532 return aState;
1535 void AquaSalFrame::SimulateKeyPress( sal_uInt16 /*nKeyCode*/ )
1539 bool AquaSalFrame::SetPluginParent( SystemParentData* )
1541 // plugin parent may be killed unexpectedly by
1542 // plugging process;
1544 //TODO: implement
1545 return sal_False;
1548 sal_Bool AquaSalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , KeyCode& )
1550 // not supported yet
1551 return FALSE;
1554 LanguageType AquaSalFrame::GetInputLanguage()
1556 //TODO: implement
1557 return LANGUAGE_DONTKNOW;
1560 void AquaSalFrame::DrawMenuBar()
1564 void AquaSalFrame::SetMenu( SalMenu* pSalMenu )
1566 // #i113170# may not be the main thread if called from UNO API
1567 SalData::ensureThreadAutoreleasePool();
1569 AquaSalMenu* pMenu = static_cast<AquaSalMenu*>(pSalMenu);
1570 DBG_ASSERT( ! pMenu || pMenu->mbMenuBar, "setting non menubar on frame" );
1571 mpMenu = pMenu;
1572 if( mpMenu )
1573 mpMenu->setMainMenu();
1576 void AquaSalFrame::SetExtendedFrameStyle( SalExtStyle nStyle )
1578 if ( mpWindow )
1580 // #i113170# may not be the main thread if called from UNO API
1581 SalData::ensureThreadAutoreleasePool();
1583 if( (mnExtStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) != (nStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) )
1584 [mpWindow setDocumentEdited: (nStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) ? YES : NO];
1587 mnExtStyle = nStyle;
1590 SalFrame* AquaSalFrame::GetParent() const
1592 return mpParent;
1595 void AquaSalFrame::SetParent( SalFrame* pNewParent )
1597 bool bShown = mbShown;
1598 // remove from child list
1599 Show( FALSE );
1600 mpParent = (AquaSalFrame*)pNewParent;
1601 // insert to correct parent and paint
1602 Show( bShown );
1605 void AquaSalFrame::UpdateFrameGeometry()
1607 if ( !mpWindow )
1609 return;
1612 // keep in mind that view and window coordinates are lower left
1613 // whereas vcl's are upper left
1615 // update screen rect
1616 NSScreen * pScreen = [mpWindow screen];
1617 if( pScreen )
1619 maScreenRect = [pScreen frame];
1620 NSArray* pScreens = [NSScreen screens];
1621 if( pScreens )
1622 maGeometry.nDisplayScreenNumber = [pScreens indexOfObject: pScreen];
1625 NSRect aFrameRect = [mpWindow frame];
1626 NSRect aContentRect = [NSWindow contentRectForFrameRect: aFrameRect styleMask: mnStyleMask];
1628 // release old track rect
1629 [mpView removeTrackingRect: mnTrackingRectTag];
1630 // install the new track rect
1631 NSRect aTrackRect = { { 0, 0 }, aContentRect.size };
1632 mnTrackingRectTag = [mpView addTrackingRect: aTrackRect owner: mpView userData: nil assumeInside: NO];
1634 // convert to vcl convention
1635 CocoaToVCL( aFrameRect );
1636 CocoaToVCL( aContentRect );
1638 maGeometry.nX = static_cast<int>(aContentRect.origin.x);
1639 maGeometry.nY = static_cast<int>(aContentRect.origin.y);
1641 maGeometry.nLeftDecoration = static_cast<unsigned int>(aContentRect.origin.x - aFrameRect.origin.x);
1642 maGeometry.nRightDecoration = static_cast<unsigned int>((aFrameRect.origin.x + aFrameRect.size.width) -
1643 (aContentRect.origin.x + aContentRect.size.width));
1645 maGeometry.nTopDecoration = static_cast<unsigned int>(aContentRect.origin.y - aFrameRect.origin.y);
1646 maGeometry.nBottomDecoration = static_cast<unsigned int>((aFrameRect.origin.y + aFrameRect.size.height) -
1647 (aContentRect.origin.y + aContentRect.size.height));
1649 maGeometry.nWidth = static_cast<unsigned int>(aContentRect.size.width);
1650 maGeometry.nHeight = static_cast<unsigned int>(aContentRect.size.height);
1653 // -----------------------------------------------------------------------
1655 void AquaSalFrame::CaptureMouse( sal_Bool bCapture )
1657 /* Remark:
1658 we'll try to use a pidgin version of capture mouse
1659 on MacOSX (neither carbon nor cocoa) there is a
1660 CaptureMouse equivalent (in Carbon there is TrackMouseLocation
1661 but this is useless to use since it is blocking)
1663 However on cocoa the active frame seems to get mouse events
1664 also outside the window, so we'll try to forward mouse events
1665 to the capture frame in the hope that one of our frames
1666 gets a mouse event.
1668 This will break as soon as the user activates another app, but
1669 a mouse click will normally lead to a release of the mouse anyway.
1671 Let's see how far we get this way. Alternatively we could use one
1672 large overlay window like we did for the carbon implementation,
1673 however that is resource intensive.
1676 if( bCapture )
1677 s_pCaptureFrame = this;
1678 else if( ! bCapture && s_pCaptureFrame == this )
1679 s_pCaptureFrame = NULL;
1682 void AquaSalFrame::ResetClipRegion()
1684 if ( !mpWindow )
1686 return;
1689 // #i113170# may not be the main thread if called from UNO API
1690 SalData::ensureThreadAutoreleasePool();
1692 // release old path and indicate no clipping
1693 CGPathRelease( mrClippingPath );
1694 mrClippingPath = NULL;
1696 if( mpView && mbShown )
1697 [mpView setNeedsDisplay: YES];
1698 if( mpWindow )
1700 [mpWindow setOpaque: YES];
1701 [mpWindow invalidateShadow];
1705 void AquaSalFrame::BeginSetClipRegion( sal_uLong nRects )
1707 if ( !mpWindow )
1709 return;
1712 // #i113170# may not be the main thread if called from UNO API
1713 SalData::ensureThreadAutoreleasePool();
1715 // release old path
1716 if( mrClippingPath )
1718 CGPathRelease( mrClippingPath );
1719 mrClippingPath = NULL;
1722 if( maClippingRects.size() > SAL_CLIPRECT_COUNT && nRects < maClippingRects.size() )
1724 std::vector<CGRect> aEmptyVec;
1725 maClippingRects.swap( aEmptyVec );
1727 maClippingRects.clear();
1728 maClippingRects.reserve( nRects );
1731 void AquaSalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
1733 // #i113170# may not be the main thread if called from UNO API
1734 SalData::ensureThreadAutoreleasePool();
1736 if( nWidth && nHeight )
1738 NSRect aRect = { { static_cast<CGFloat>(nX), static_cast<CGFloat>(nY) }, { static_cast<CGFloat>(nWidth), static_cast<CGFloat>(nHeight) } };
1739 VCLToCocoa( aRect, false );
1740 maClippingRects.push_back( CGRectMake(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height) );
1744 void AquaSalFrame::EndSetClipRegion()
1746 if ( !mpWindow )
1748 return;
1751 // #i113170# may not be the main thread if called from UNO API
1752 SalData::ensureThreadAutoreleasePool();
1754 if( ! maClippingRects.empty() )
1756 mrClippingPath = CGPathCreateMutable();
1757 CGPathAddRects( mrClippingPath, NULL, &maClippingRects[0], maClippingRects.size() );
1759 if( mpView && mbShown )
1760 [mpView setNeedsDisplay: YES];
1761 if( mpWindow )
1763 [mpWindow setOpaque: (mrClippingPath != NULL) ? NO : YES];
1764 [mpWindow setBackgroundColor: [NSColor clearColor]];
1765 // shadow is invalidated when view gets drawn again
1769 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */