Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / osx / salframe.cxx
blob251f5c3d08abecdf12e3dda41726276563286328
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 .
20 #include <string>
22 #include "rtl/ustrbuf.hxx"
24 #include "osl/file.h"
26 #include "vcl/svapp.hxx"
27 #include "vcl/window.hxx"
28 #include "vcl/syswin.hxx"
29 #include <vcl/settings.hxx>
31 #include "osx/saldata.hxx"
32 #include "quartz/salgdi.h"
33 #include "osx/salframe.h"
34 #include "osx/salmenu.h"
35 #include "osx/salinst.h"
36 #include "osx/salframeview.h"
37 #include "osx/a11yfactory.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 AquaSalFrame* AquaSalFrame::s_pCaptureFrame = NULL;
53 AquaSalFrame::AquaSalFrame( SalFrame* pParent, sal_uLong salFrameStyle ) :
54 mpNSWindow(nil),
55 mpNSView(nil),
56 mpDockMenuEntry(nil),
57 mpGraphics(NULL),
58 mpParent(NULL),
59 mnMinWidth(0),
60 mnMinHeight(0),
61 mnMaxWidth(0),
62 mnMaxHeight(0),
63 mbGraphics(false),
64 mbFullScreen( false ),
65 mbShown(false),
66 mbInitShow(true),
67 mbPositioned(false),
68 mbSized(false),
69 mbPresentation( false ),
70 mnStyle( salFrameStyle ),
71 mnStyleMask( 0 ),
72 mnLastEventTime( 0 ),
73 mnLastModifierFlags( 0 ),
74 mpMenu( NULL ),
75 mnExtStyle( 0 ),
76 mePointerStyle( PointerStyle::Arrow ),
77 mnTrackingRectTag( 0 ),
78 mrClippingPath( 0 ),
79 mnICOptions( InputContextFlags::NONE )
81 maSysData.nSize = sizeof( SystemEnvData );
83 mpParent = dynamic_cast<AquaSalFrame*>(pParent);
85 initWindowAndView();
87 SalData* pSalData = GetSalData();
88 pSalData->maFrames.push_front( this );
89 pSalData->maFrameCheck.insert( this );
92 AquaSalFrame::~AquaSalFrame()
94 // if the frame is destroyed and has the current menubar
95 // set the default menubar
96 if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu )
97 AquaSalMenu::setDefaultMenu();
99 // cleanup clipping stuff
100 ResetClipRegion();
102 [SalFrameView unsetMouseFrame: this];
104 SalData* pSalData = GetSalData();
105 pSalData->maFrames.remove( this );
106 pSalData->maFrameCheck.erase( this );
107 pSalData->maPresentationFrames.remove( this );
109 DBG_ASSERT( this != s_pCaptureFrame, "capture frame destroyed" );
110 if( this == s_pCaptureFrame )
111 s_pCaptureFrame = NULL;
113 delete mpGraphics;
115 if( mpDockMenuEntry )
116 // life cycle comment: the menu has ownership of the item, so no release
117 [AquaSalInstance::GetDynamicDockMenu() removeItem: mpDockMenuEntry];
118 if ( mpNSView ) {
119 [AquaA11yFactory revokeView: mpNSView];
120 [mpNSView release];
122 if ( mpNSWindow )
123 [mpNSWindow release];
126 void AquaSalFrame::initWindowAndView()
128 // initialize mirroring parameters
129 // FIXME: screens changing
130 NSScreen* pNSScreen = [mpNSWindow screen];
131 if( pNSScreen == nil )
132 pNSScreen = [NSScreen mainScreen];
133 maScreenRect = [pNSScreen frame];
135 // calculate some default geometry
136 NSRect aVisibleRect = [pNSScreen visibleFrame];
137 CocoaToVCL( aVisibleRect );
139 maGeometry.nX = static_cast<int>(aVisibleRect.origin.x + aVisibleRect.size.width / 10);
140 maGeometry.nY = static_cast<int>(aVisibleRect.origin.y + aVisibleRect.size.height / 10);
141 maGeometry.nWidth = static_cast<unsigned int>(aVisibleRect.size.width * 0.8);
142 maGeometry.nHeight = static_cast<unsigned int>(aVisibleRect.size.height * 0.8);
144 // calculate style mask
145 if( (mnStyle & SAL_FRAME_STYLE_FLOAT) ||
146 (mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
147 mnStyleMask = NSBorderlessWindowMask;
148 else if( mnStyle & SAL_FRAME_STYLE_DEFAULT )
150 mnStyleMask = NSTitledWindowMask |
151 NSMiniaturizableWindowMask |
152 NSResizableWindowMask |
153 NSClosableWindowMask;
154 // make default window "maximized"
155 maGeometry.nX = static_cast<int>(aVisibleRect.origin.x);
156 maGeometry.nY = static_cast<int>(aVisibleRect.origin.y);
157 maGeometry.nWidth = static_cast<int>(aVisibleRect.size.width);
158 maGeometry.nHeight = static_cast<int>(aVisibleRect.size.height);
159 mbPositioned = mbSized = true;
161 else
163 if( (mnStyle & SAL_FRAME_STYLE_MOVEABLE) )
165 mnStyleMask |= NSTitledWindowMask;
166 if( mpParent == NULL )
167 mnStyleMask |= NSMiniaturizableWindowMask;
169 if( (mnStyle & SAL_FRAME_STYLE_SIZEABLE) )
170 mnStyleMask |= NSResizableWindowMask;
171 if( (mnStyle & SAL_FRAME_STYLE_CLOSEABLE) )
172 mnStyleMask |= NSClosableWindowMask;
173 // documentation says anything other than NSBorderlessWindowMask (=0)
174 // should also include NSTitledWindowMask;
175 if( mnStyleMask != 0 )
176 mnStyleMask |= NSTitledWindowMask;
179 // #i91990# support GUI-less (daemon) execution
180 @try
182 mpNSWindow = [[SalFrameWindow alloc] initWithSalFrame: this];
183 mpNSView = [[SalFrameView alloc] initWithSalFrame: this];
185 @catch ( id exception )
187 return;
190 if( (mnStyle & SAL_FRAME_STYLE_TOOLTIP) )
191 [mpNSWindow setIgnoresMouseEvents: YES];
192 else
193 [mpNSWindow setAcceptsMouseMovedEvents: YES];
194 [mpNSWindow setHasShadow: YES];
196 [mpNSWindow setDelegate: static_cast<id<NSWindowDelegate> >(mpNSWindow)];
198 if( [mpNSWindow respondsToSelector: @selector(setRestorable:)])
200 objc_msgSend(mpNSWindow, @selector(setRestorable:), NO);
202 const NSRect aRect = { NSZeroPoint, NSMakeSize( maGeometry.nWidth, maGeometry.nHeight )};
203 mnTrackingRectTag = [mpNSView addTrackingRect: aRect owner: mpNSView userData: nil assumeInside: NO];
205 maSysData.mpNSView = mpNSView;
207 UpdateFrameGeometry();
209 [mpNSWindow setContentView: mpNSView];
212 void AquaSalFrame::CocoaToVCL( NSRect& io_rRect, bool bRelativeToScreen )
214 if( bRelativeToScreen )
215 io_rRect.origin.y = maScreenRect.size.height - (io_rRect.origin.y+io_rRect.size.height);
216 else
217 io_rRect.origin.y = maGeometry.nHeight - (io_rRect.origin.y+io_rRect.size.height);
220 void AquaSalFrame::VCLToCocoa( NSRect& io_rRect, bool bRelativeToScreen )
222 if( bRelativeToScreen )
223 io_rRect.origin.y = maScreenRect.size.height - (io_rRect.origin.y+io_rRect.size.height);
224 else
225 io_rRect.origin.y = maGeometry.nHeight - (io_rRect.origin.y+io_rRect.size.height);
228 void AquaSalFrame::CocoaToVCL( NSPoint& io_rPoint, bool bRelativeToScreen )
230 if( bRelativeToScreen )
231 io_rPoint.y = maScreenRect.size.height - io_rPoint.y;
232 else
233 io_rPoint.y = maGeometry.nHeight - io_rPoint.y;
236 void AquaSalFrame::VCLToCocoa( NSPoint& io_rPoint, bool bRelativeToScreen )
238 if( bRelativeToScreen )
239 io_rPoint.y = maScreenRect.size.height - io_rPoint.y;
240 else
241 io_rPoint.y = maGeometry.nHeight - io_rPoint.y;
244 void AquaSalFrame::screenParametersChanged()
246 UpdateFrameGeometry();
248 if( mpGraphics )
249 mpGraphics->updateResolution();
250 CallCallback( SALEVENT_DISPLAYCHANGED, 0 );
253 SalGraphics* AquaSalFrame::AcquireGraphics()
255 if ( mbGraphics )
256 return NULL;
258 if ( !mpGraphics )
260 mpGraphics = new AquaSalGraphics;
261 mpGraphics->SetWindowGraphics( this );
264 mbGraphics = TRUE;
265 return mpGraphics;
268 void AquaSalFrame::ReleaseGraphics( SalGraphics *pGraphics )
270 (void)pGraphics;
271 DBG_ASSERT( pGraphics == mpGraphics, "graphics released on wrong frame" );
272 mbGraphics = FALSE;
275 bool AquaSalFrame::PostEvent( void *pData )
277 GetSalData()->mpFirstInstance->PostUserEvent( this, SALEVENT_USEREVENT, pData );
278 return TRUE;
281 void AquaSalFrame::SetTitle(const OUString& rTitle)
283 if ( !mpNSWindow )
284 return;
286 // #i113170# may not be the main thread if called from UNO API
287 SalData::ensureThreadAutoreleasePool();
289 NSString* pTitle = CreateNSString( rTitle );
290 [mpNSWindow setTitle: pTitle];
292 // create an entry in the dock menu
293 const sal_uLong nAppWindowStyle = (SAL_FRAME_STYLE_CLOSEABLE | SAL_FRAME_STYLE_MOVEABLE);
294 if( mpParent == NULL &&
295 (mnStyle & nAppWindowStyle) == nAppWindowStyle )
297 if( mpDockMenuEntry == NULL )
299 NSMenu* pDock = AquaSalInstance::GetDynamicDockMenu();
300 mpDockMenuEntry = [pDock insertItemWithTitle: pTitle
301 action: @selector(dockMenuItemTriggered:)
302 keyEquivalent: @""
303 atIndex: 0];
304 [mpDockMenuEntry setTarget: mpNSWindow];
306 // TODO: image (either the generic window image or an icon
307 // check mark (for "main" window ?)
309 else
310 [mpDockMenuEntry setTitle: pTitle];
313 if (pTitle)
314 [pTitle release];
317 void AquaSalFrame::SetIcon( sal_uInt16 )
321 void AquaSalFrame::SetRepresentedURL( const OUString& i_rDocURL )
323 // #i113170# may not be the main thread if called from UNO API
324 SalData::ensureThreadAutoreleasePool();
326 if( i_rDocURL.startsWith( "file:" ) )
328 OUString aSysPath;
329 osl_getSystemPathFromFileURL( i_rDocURL.pData, &aSysPath.pData );
330 NSString* pStr = CreateNSString( aSysPath );
331 if( pStr )
333 [pStr autorelease];
334 [mpNSWindow setRepresentedFilename: pStr];
339 void AquaSalFrame::initShow()
341 mbInitShow = false;
342 if( ! mbPositioned && ! mbFullScreen )
344 Rectangle aScreenRect;
345 GetWorkArea( aScreenRect );
346 if( mpParent ) // center relative to parent
348 // center on parent
349 long nNewX = mpParent->maGeometry.nX + ((long)mpParent->maGeometry.nWidth - (long)maGeometry.nWidth)/2;
350 if( nNewX < aScreenRect.Left() )
351 nNewX = aScreenRect.Left();
352 if( long(nNewX + maGeometry.nWidth) > aScreenRect.Right() )
353 nNewX = aScreenRect.Right() - maGeometry.nWidth-1;
354 long nNewY = mpParent->maGeometry.nY + ((long)mpParent->maGeometry.nHeight - (long)maGeometry.nHeight)/2;
355 if( nNewY < aScreenRect.Top() )
356 nNewY = aScreenRect.Top();
357 if( nNewY > aScreenRect.Bottom() )
358 nNewY = aScreenRect.Bottom() - maGeometry.nHeight-1;
359 SetPosSize( nNewX - mpParent->maGeometry.nX,
360 nNewY - mpParent->maGeometry.nY,
361 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y );
363 else if( ! (mnStyle & SAL_FRAME_STYLE_SIZEABLE) )
365 // center on screen
366 long nNewX = (aScreenRect.GetWidth() - maGeometry.nWidth)/2;
367 long nNewY = (aScreenRect.GetHeight() - maGeometry.nHeight)/2;
368 SetPosSize( nNewX, nNewY, 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y );
372 // make sure the view is present in the wrapper list before any children receive focus
373 [AquaA11yFactory registerView: mpNSView];
376 void AquaSalFrame::SendPaintEvent( const Rectangle* pRect )
378 SalPaintEvent aPaintEvt( 0, 0, maGeometry.nWidth, maGeometry.nHeight, true );
379 if( pRect )
381 aPaintEvt.mnBoundX = pRect->Left();
382 aPaintEvt.mnBoundY = pRect->Top();
383 aPaintEvt.mnBoundWidth = pRect->GetWidth();
384 aPaintEvt.mnBoundHeight = pRect->GetHeight();
387 CallCallback(SALEVENT_PAINT, &aPaintEvt);
390 void AquaSalFrame::Show(bool bVisible, bool bNoActivate)
392 if ( !mpNSWindow )
393 return;
395 // #i113170# may not be the main thread if called from UNO API
396 SalData::ensureThreadAutoreleasePool();
398 mbShown = bVisible;
399 if(bVisible)
401 if( mbInitShow )
402 initShow();
404 CallCallback(SALEVENT_RESIZE, 0);
405 // trigger filling our backbuffer
406 SendPaintEvent();
408 if( bNoActivate || [mpNSWindow canBecomeKeyWindow] == NO )
409 [mpNSWindow orderFront: NSApp];
410 else
411 [mpNSWindow makeKeyAndOrderFront: NSApp];
413 if( mpParent )
415 /* #i92674# #i96433# we do not want an invisible parent to show up (which adding a visible
416 child implicitly does). However we also do not want a parentless toolbar.
418 HACK: try to decide when we should not insert a child to its parent
419 floaters and ownerdraw windows have not yet shown up in cases where
420 we don't want the parent to become visible
422 if( mpParent->mbShown || (mnStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION | SAL_FRAME_STYLE_FLOAT) ) )
424 [mpParent->mpNSWindow addChildWindow: mpNSWindow ordered: NSWindowAbove];
428 if( mbPresentation )
429 [mpNSWindow makeMainWindow];
431 else
433 // if the frame holding the current menubar gets hidden
434 // show the default menubar
435 if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu )
436 AquaSalMenu::setDefaultMenu();
438 // #i90440# #i94443# work around the focus going back to some other window
439 // if a child gets hidden for a parent window
440 if( mpParent && mpParent->mbShown && [mpNSWindow isKeyWindow] )
441 [mpParent->mpNSWindow makeKeyAndOrderFront: NSApp];
443 [SalFrameView unsetMouseFrame: this];
444 if( mpParent && [mpNSWindow parentWindow] == mpParent->mpNSWindow )
445 [mpParent->mpNSWindow removeChildWindow: mpNSWindow];
447 [mpNSWindow orderOut: NSApp];
451 void AquaSalFrame::SetMinClientSize( long nWidth, long nHeight )
453 // #i113170# may not be the main thread if called from UNO API
454 SalData::ensureThreadAutoreleasePool();
456 mnMinWidth = nWidth;
457 mnMinHeight = nHeight;
459 if( mpNSWindow )
461 // Always add the decoration as the dimension concerns only
462 // the content rectangle
463 nWidth += maGeometry.nLeftDecoration + maGeometry.nRightDecoration;
464 nHeight += maGeometry.nTopDecoration + maGeometry.nBottomDecoration;
466 NSSize aSize = { static_cast<CGFloat>(nWidth), static_cast<CGFloat>(nHeight) };
468 // Size of full window (content+structure) although we only
469 // have the client size in arguments
470 [mpNSWindow setMinSize: aSize];
474 void AquaSalFrame::SetMaxClientSize( long nWidth, long nHeight )
476 // #i113170# may not be the main thread if called from UNO API
477 SalData::ensureThreadAutoreleasePool();
479 mnMaxWidth = nWidth;
480 mnMaxHeight = nHeight;
482 if( mpNSWindow )
484 // Always add the decoration as the dimension concerns only
485 // the content rectangle
486 nWidth += maGeometry.nLeftDecoration + maGeometry.nRightDecoration;
487 nHeight += maGeometry.nTopDecoration + maGeometry.nBottomDecoration;
489 // Carbon windows can't have a size greater than 32767x32767
490 if (nWidth>32767) nWidth=32767;
491 if (nHeight>32767) nHeight=32767;
493 NSSize aSize = { static_cast<CGFloat>(nWidth), static_cast<CGFloat>(nHeight) };
495 // Size of full window (content+structure) although we only
496 // have the client size in arguments
497 [mpNSWindow setMaxSize: aSize];
501 void AquaSalFrame::GetClientSize( long& rWidth, long& rHeight )
503 if( mbShown || mbInitShow )
505 rWidth = maGeometry.nWidth;
506 rHeight = maGeometry.nHeight;
508 else
510 rWidth = 0;
511 rHeight = 0;
515 void AquaSalFrame::SetWindowState( const SalFrameState* pState )
517 // #i113170# may not be the main thread if called from UNO API
518 SalData::ensureThreadAutoreleasePool();
520 if ( mpNSWindow )
522 // set normal state
523 NSRect aStateRect = [mpNSWindow frame];
524 aStateRect = [NSWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask];
525 CocoaToVCL( aStateRect );
526 if( pState->mnMask & WINDOWSTATE_MASK_X )
527 aStateRect.origin.x = float(pState->mnX);
528 if( pState->mnMask & WINDOWSTATE_MASK_Y )
529 aStateRect.origin.y = float(pState->mnY);
530 if( pState->mnMask & WINDOWSTATE_MASK_WIDTH )
531 aStateRect.size.width = float(pState->mnWidth);
532 if( pState->mnMask & WINDOWSTATE_MASK_HEIGHT )
533 aStateRect.size.height = float(pState->mnHeight);
534 VCLToCocoa( aStateRect );
535 aStateRect = [NSWindow frameRectForContentRect: aStateRect styleMask: mnStyleMask];
537 [mpNSWindow setFrame: aStateRect display: NO];
538 if( pState->mnState == WINDOWSTATE_STATE_MINIMIZED )
539 [mpNSWindow miniaturize: NSApp];
540 else if( [mpNSWindow isMiniaturized] )
541 [mpNSWindow deminiaturize: NSApp];
543 /* ZOOMED is not really maximized (actually it toggles between a user set size and
544 the program specified one), but comes closest since the default behavior is
545 "maximized" if the user did not intervene
547 if( pState->mnState == WINDOWSTATE_STATE_MAXIMIZED )
549 if(! [mpNSWindow isZoomed])
550 [mpNSWindow zoom: NSApp];
552 else
554 if( [mpNSWindow isZoomed] )
555 [mpNSWindow zoom: NSApp];
559 // get new geometry
560 UpdateFrameGeometry();
562 sal_uInt16 nEvent = 0;
563 if( pState->mnMask & (WINDOWSTATE_MASK_X | WINDOWSTATE_MASK_Y) )
565 mbPositioned = true;
566 nEvent = SALEVENT_MOVE;
569 if( pState->mnMask & (WINDOWSTATE_MASK_WIDTH | WINDOWSTATE_MASK_HEIGHT) )
571 mbSized = true;
572 nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE;
574 // send event that we were moved/sized
575 if( nEvent )
576 CallCallback( nEvent, NULL );
578 if( mbShown && mpNSWindow )
580 // trigger filling our backbuffer
581 SendPaintEvent();
583 // tell the system the views need to be updated
584 [mpNSWindow display];
588 bool AquaSalFrame::GetWindowState( SalFrameState* pState )
590 if ( !mpNSWindow )
591 return FALSE;
593 // #i113170# may not be the main thread if called from UNO API
594 SalData::ensureThreadAutoreleasePool();
596 pState->mnMask = WINDOWSTATE_MASK_X |
597 WINDOWSTATE_MASK_Y |
598 WINDOWSTATE_MASK_WIDTH |
599 WINDOWSTATE_MASK_HEIGHT |
600 WINDOWSTATE_MASK_STATE;
602 NSRect aStateRect = [mpNSWindow frame];
603 aStateRect = [NSWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask];
604 CocoaToVCL( aStateRect );
605 pState->mnX = long(aStateRect.origin.x);
606 pState->mnY = long(aStateRect.origin.y);
607 pState->mnWidth = long(aStateRect.size.width);
608 pState->mnHeight = long(aStateRect.size.height);
610 if( [mpNSWindow isMiniaturized] )
611 pState->mnState = WINDOWSTATE_STATE_MINIMIZED;
612 else if( ! [mpNSWindow isZoomed] )
613 pState->mnState = WINDOWSTATE_STATE_NORMAL;
614 else
615 pState->mnState = WINDOWSTATE_STATE_MAXIMIZED;
617 return TRUE;
620 void AquaSalFrame::SetScreenNumber(unsigned int nScreen)
622 if ( !mpNSWindow )
623 return;
625 // #i113170# may not be the main thread if called from UNO API
626 SalData::ensureThreadAutoreleasePool();
628 NSArray* pScreens = [NSScreen screens];
629 NSScreen* pScreen = nil;
630 if( pScreens && nScreen < [pScreens count] )
632 // get new screen frame
633 pScreen = [pScreens objectAtIndex: nScreen];
634 NSRect aNewScreen = [pScreen frame];
636 // get current screen frame
637 pScreen = [mpNSWindow screen];
638 if( pScreen )
640 NSRect aCurScreen = [pScreen frame];
641 if( aCurScreen.origin.x != aNewScreen.origin.x ||
642 aCurScreen.origin.y != aNewScreen.origin.y )
644 NSRect aFrameRect = [mpNSWindow frame];
645 aFrameRect.origin.x += aNewScreen.origin.x - aCurScreen.origin.x;
646 aFrameRect.origin.y += aNewScreen.origin.y - aCurScreen.origin.y;
647 [mpNSWindow setFrame: aFrameRect display: NO];
648 UpdateFrameGeometry();
654 void AquaSalFrame::SetApplicationID( const OUString &/*rApplicationID*/ )
658 void AquaSalFrame::ShowFullScreen( bool bFullScreen, sal_Int32 nDisplay )
660 if ( !mpNSWindow )
661 return;
663 // #i113170# may not be the main thread if called from UNO API
664 SalData::ensureThreadAutoreleasePool();
666 SAL_INFO("vcl.osx", OSL_THIS_FUNC << ": mbFullScreen=" << mbFullScreen << ", bFullScreen=" << bFullScreen);
668 if( mbFullScreen == bFullScreen )
669 return;
671 mbFullScreen = bFullScreen;
673 if( bFullScreen )
675 // hide the dock and the menubar if we are on the menu screen
676 // which is always on index 0 according to documentation
677 bool bHideMenu = (nDisplay == 0);
679 NSRect aNewContentRect = NSZeroRect;
680 // get correct screen
681 NSScreen* pScreen = nil;
682 NSArray* pScreens = [NSScreen screens];
683 if( pScreens )
685 if( nDisplay >= 0 && (unsigned int)nDisplay < [pScreens count] )
686 pScreen = [pScreens objectAtIndex: nDisplay];
687 else
689 // this means span all screens
690 bHideMenu = true;
691 NSEnumerator* pEnum = [pScreens objectEnumerator];
692 while( (pScreen = [pEnum nextObject]) != nil )
694 NSRect aScreenRect = [pScreen frame];
695 if( aScreenRect.origin.x < aNewContentRect.origin.x )
697 aNewContentRect.size.width += aNewContentRect.origin.x - aScreenRect.origin.x;
698 aNewContentRect.origin.x = aScreenRect.origin.x;
700 if( aScreenRect.origin.y < aNewContentRect.origin.y )
702 aNewContentRect.size.height += aNewContentRect.origin.y - aScreenRect.origin.y;
703 aNewContentRect.origin.y = aScreenRect.origin.y;
705 if( aScreenRect.origin.x + aScreenRect.size.width > aNewContentRect.origin.x + aNewContentRect.size.width )
706 aNewContentRect.size.width = aScreenRect.origin.x + aScreenRect.size.width - aNewContentRect.origin.x;
707 if( aScreenRect.origin.y + aScreenRect.size.height > aNewContentRect.origin.y + aNewContentRect.size.height )
708 aNewContentRect.size.height = aScreenRect.origin.y + aScreenRect.size.height - aNewContentRect.origin.y;
712 if( aNewContentRect.size.width == 0 && aNewContentRect.size.height == 0 )
714 if( pScreen == nil )
715 pScreen = [mpNSWindow screen];
716 if( pScreen == nil )
717 pScreen = [NSScreen mainScreen];
719 aNewContentRect = [pScreen frame];
722 if( bHideMenu )
723 [NSMenu setMenuBarVisible:NO];
725 maFullScreenRect = [mpNSWindow frame];
727 [mpNSWindow setFrame: [NSWindow frameRectForContentRect: aNewContentRect styleMask: mnStyleMask] display: mbShown ? YES : NO];
730 UpdateFrameGeometry();
732 if( mbShown )
733 CallCallback( SALEVENT_MOVERESIZE, NULL );
735 else
738 [mpNSWindow setFrame: maFullScreenRect display: mbShown ? YES : NO];
740 UpdateFrameGeometry();
742 if( mbShown )
743 CallCallback( SALEVENT_MOVERESIZE, NULL );
745 // show the dock and the menubar
746 [NSMenu setMenuBarVisible:YES];
748 if( mbShown )
749 // trigger filling our backbuffer
750 SendPaintEvent();
753 void AquaSalFrame::StartPresentation( bool bStart )
755 if ( !mpNSWindow )
756 return;
758 // #i113170# may not be the main thread if called from UNO API
759 SalData::ensureThreadAutoreleasePool();
761 if( bStart )
763 GetSalData()->maPresentationFrames.push_back( this );
764 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
765 kIOPMAssertionLevelOn,
766 CFSTR("LibreOffice presentation running"),
767 &mnAssertionID);
768 [mpNSWindow setLevel: NSPopUpMenuWindowLevel];
769 if( mbShown )
770 [mpNSWindow makeMainWindow];
772 else
774 GetSalData()->maPresentationFrames.remove( this );
775 IOPMAssertionRelease(mnAssertionID);
776 [mpNSWindow setLevel: NSNormalWindowLevel];
780 void AquaSalFrame::SetAlwaysOnTop( bool )
784 void AquaSalFrame::ToTop(sal_uInt16 nFlags)
786 if ( !mpNSWindow )
787 return;
789 // #i113170# may not be the main thread if called from UNO API
790 SalData::ensureThreadAutoreleasePool();
792 if( ! (nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN) )
794 if( ! [mpNSWindow isVisible] || [mpNSWindow isMiniaturized] )
795 return;
797 if( nFlags & SAL_FRAME_TOTOP_GRABFOCUS )
798 [mpNSWindow makeKeyAndOrderFront: NSApp];
799 else
800 [mpNSWindow orderFront: NSApp];
803 NSCursor* AquaSalFrame::getCurrentCursor() const
805 NSCursor* pCursor = nil;
806 switch( mePointerStyle )
808 case PointerStyle::Text: pCursor = [NSCursor IBeamCursor]; break;
809 case PointerStyle::Cross: pCursor = [NSCursor crosshairCursor]; break;
810 case PointerStyle::Hand:
811 case PointerStyle::Move: pCursor = [NSCursor openHandCursor]; break;
812 case PointerStyle::NSize: pCursor = [NSCursor resizeUpCursor]; break;
813 case PointerStyle::SSize: pCursor = [NSCursor resizeDownCursor]; break;
814 case PointerStyle::ESize: pCursor = [NSCursor resizeRightCursor]; break;
815 case PointerStyle::WSize: pCursor = [NSCursor resizeLeftCursor]; break;
816 case PointerStyle::Arrow: pCursor = [NSCursor arrowCursor]; break;
817 case PointerStyle::VSplit:
818 case PointerStyle::VSizeBar:
819 case PointerStyle::WindowNSize:
820 case PointerStyle::WindowSSize:
821 pCursor = [NSCursor resizeUpDownCursor]; break;
822 case PointerStyle::HSplit:
823 case PointerStyle::HSizeBar:
824 case PointerStyle::WindowESize:
825 case PointerStyle::WindowWSize:
826 pCursor = [NSCursor resizeLeftRightCursor]; break;
827 case PointerStyle::RefHand: pCursor = [NSCursor pointingHandCursor]; break;
829 default:
830 pCursor = GetSalData()->getCursor( mePointerStyle );
831 if( pCursor == nil )
833 OSL_FAIL( "unmapped cursor" );
834 pCursor = [NSCursor arrowCursor];
836 break;
838 return pCursor;
841 void AquaSalFrame::SetPointer( PointerStyle ePointerStyle )
843 if ( !mpNSWindow )
844 return;
846 // #i113170# may not be the main thread if called from UNO API
847 SalData::ensureThreadAutoreleasePool();
849 if( ePointerStyle == mePointerStyle )
850 return;
851 mePointerStyle = ePointerStyle;
853 [mpNSWindow invalidateCursorRectsForView: mpNSView];
856 void AquaSalFrame::SetPointerPos( long nX, long nY )
858 // FIXME: use Cocoa functions
860 // FIXME: multiscreen support
861 CGPoint aPoint = { static_cast<CGFloat>(nX + maGeometry.nX), static_cast<CGFloat>(nY + maGeometry.nY) };
862 CGDirectDisplayID mainDisplayID = CGMainDisplayID();
863 CGDisplayMoveCursorToPoint( mainDisplayID, aPoint );
866 void AquaSalFrame::Flush()
868 if( !(mbGraphics && mpGraphics && mpNSView && mbShown) )
869 return;
871 // #i113170# may not be the main thread if called from UNO API
872 SalData::ensureThreadAutoreleasePool();
874 [mpNSView setNeedsDisplay: YES];
876 // outside of the application's event loop (e.g. IntroWindow)
877 // nothing would trigger paint event handling
878 // => fall back to synchronous painting
879 if( ImplGetSVData()->maAppData.mnDispatchLevel <= 0 )
881 [mpNSView display];
885 void AquaSalFrame::Flush( const Rectangle& rRect )
887 if( !(mbGraphics && mpGraphics && mpNSView && mbShown) )
888 return;
890 // #i113170# may not be the main thread if called from UNO API
891 SalData::ensureThreadAutoreleasePool();
893 NSRect aNSRect = { { static_cast<CGFloat>(rRect.Left()), static_cast<CGFloat>(rRect.Top()) }, { static_cast<CGFloat>(rRect.GetWidth()), static_cast<CGFloat>(rRect.GetHeight()) } };
894 VCLToCocoa( aNSRect, false );
895 [mpNSView setNeedsDisplayInRect: aNSRect];
897 // outside of the application's event loop (e.g. IntroWindow)
898 // nothing would trigger paint event handling
899 // => fall back to synchronous painting
900 if( ImplGetSVData()->maAppData.mnDispatchLevel <= 0 )
902 [mpNSView display];
906 void AquaSalFrame::Sync()
908 if( mbGraphics && mpGraphics && mpNSView && mbShown )
910 // #i113170# may not be the main thread if called from UNO API
911 SalData::ensureThreadAutoreleasePool();
913 [mpNSView setNeedsDisplay: YES];
914 [mpNSView display];
918 void AquaSalFrame::SetInputContext( SalInputContext* pContext )
920 if (!pContext)
922 mnICOptions = InputContextFlags::NONE;
923 return;
926 mnICOptions = pContext->mnOptions;
928 if(!(pContext->mnOptions & InputContextFlags::Text))
929 return;
932 void AquaSalFrame::EndExtTextInput( sal_uInt16 )
936 OUString AquaSalFrame::GetKeyName( sal_uInt16 nKeyCode )
938 static std::map< sal_uInt16, OUString > aKeyMap;
939 if( aKeyMap.empty() )
941 sal_uInt16 i;
942 for( i = KEY_A; i <= KEY_Z; i++ )
943 aKeyMap[ i ] = OUString( sal_Unicode( 'A' + (i - KEY_A) ) );
944 for( i = KEY_0; i <= KEY_9; i++ )
945 aKeyMap[ i ] = OUString( sal_Unicode( '0' + (i - KEY_0) ) );
946 for( i = KEY_F1; i <= KEY_F26; i++ )
948 OUStringBuffer aKey( 3 );
949 aKey.append( 'F' );
950 aKey.append( sal_Int32( i - KEY_F1 + 1 ) );
951 aKeyMap[ i ] = aKey.makeStringAndClear();
954 aKeyMap[ KEY_DOWN ] = OUString( sal_Unicode( 0x21e3 ) );
955 aKeyMap[ KEY_UP ] = OUString( sal_Unicode( 0x21e1 ) );
956 aKeyMap[ KEY_LEFT ] = OUString( sal_Unicode( 0x21e0 ) );
957 aKeyMap[ KEY_RIGHT ] = OUString( sal_Unicode( 0x21e2 ) );
958 aKeyMap[ KEY_HOME ] = OUString( sal_Unicode( 0x2196 ) );
959 aKeyMap[ KEY_END ] = OUString( sal_Unicode( 0x2198 ) );
960 aKeyMap[ KEY_PAGEUP ] = OUString( sal_Unicode( 0x21de ) );
961 aKeyMap[ KEY_PAGEDOWN ] = OUString( sal_Unicode( 0x21df ) );
962 aKeyMap[ KEY_RETURN ] = OUString( sal_Unicode( 0x21a9 ) );
963 aKeyMap[ KEY_ESCAPE ] = "esc";
964 aKeyMap[ KEY_TAB ] = OUString( sal_Unicode( 0x21e5 ) );
965 aKeyMap[ KEY_BACKSPACE ]= OUString( sal_Unicode( 0x232b ) );
966 aKeyMap[ KEY_SPACE ] = OUString( sal_Unicode( 0x2423 ) );
967 aKeyMap[ KEY_DELETE ] = OUString( sal_Unicode( 0x2326 ) );
968 aKeyMap[ KEY_ADD ] = "+";
969 aKeyMap[ KEY_SUBTRACT ] = "-";
970 aKeyMap[ KEY_DIVIDE ] = "/";
971 aKeyMap[ KEY_MULTIPLY ] = "*";
972 aKeyMap[ KEY_POINT ] = ".";
973 aKeyMap[ KEY_COMMA ] = ",";
974 aKeyMap[ KEY_LESS ] = "<";
975 aKeyMap[ KEY_GREATER ] = ">";
976 aKeyMap[ KEY_EQUAL ] = "=";
977 aKeyMap[ KEY_OPEN ] = OUString( sal_Unicode( 0x23cf ) );
978 aKeyMap[ KEY_TILDE ] = "~";
979 aKeyMap[ KEY_BRACKETLEFT ] = "[";
980 aKeyMap[ KEY_BRACKETRIGHT ] = "]";
981 aKeyMap[ KEY_SEMICOLON ] = ";";
982 aKeyMap[ KEY_QUOTERIGHT ] = "'";
984 /* yet unmapped KEYCODES:
985 aKeyMap[ KEY_INSERT ] = OUString( sal_Unicode( ) );
986 aKeyMap[ KEY_CUT ] = OUString( sal_Unicode( ) );
987 aKeyMap[ KEY_COPY ] = OUString( sal_Unicode( ) );
988 aKeyMap[ KEY_PASTE ] = OUString( sal_Unicode( ) );
989 aKeyMap[ KEY_UNDO ] = OUString( sal_Unicode( ) );
990 aKeyMap[ KEY_REPEAT ] = OUString( sal_Unicode( ) );
991 aKeyMap[ KEY_FIND ] = OUString( sal_Unicode( ) );
992 aKeyMap[ KEY_PROPERTIES ] = OUString( sal_Unicode( ) );
993 aKeyMap[ KEY_FRONT ] = OUString( sal_Unicode( ) );
994 aKeyMap[ KEY_CONTEXTMENU ] = OUString( sal_Unicode( ) );
995 aKeyMap[ KEY_MENU ] = OUString( sal_Unicode( ) );
996 aKeyMap[ KEY_HELP ] = OUString( sal_Unicode( ) );
997 aKeyMap[ KEY_HANGUL_HANJA ] = OUString( sal_Unicode( ) );
998 aKeyMap[ KEY_DECIMAL ] = OUString( sal_Unicode( ) );
999 aKeyMap[ KEY_QUOTELEFT ]= OUString( sal_Unicode( ) );
1000 aKeyMap[ KEY_CAPSLOCK ]= OUString( sal_Unicode( ) );
1001 aKeyMap[ KEY_NUMLOCK ]= OUString( sal_Unicode( ) );
1002 aKeyMap[ KEY_SCROLLLOCK ]= OUString( sal_Unicode( ) );
1007 OUStringBuffer aResult( 16 );
1009 sal_uInt16 nUnmodifiedCode = (nKeyCode & KEY_CODE_MASK);
1010 std::map< sal_uInt16, OUString >::const_iterator it = aKeyMap.find( nUnmodifiedCode );
1011 if( it != aKeyMap.end() )
1013 if( (nKeyCode & KEY_SHIFT) != 0 )
1014 aResult.append( sal_Unicode( 0x21e7 ) );
1015 if( (nKeyCode & KEY_MOD1) != 0 )
1016 aResult.append( sal_Unicode( 0x2318 ) );
1017 // we do not really handle Alt (see below)
1018 // we map it to MOD3, whichis actually Command
1019 if( (nKeyCode & (KEY_MOD2|KEY_MOD3)) != 0 )
1020 aResult.append( sal_Unicode( 0x2325 ) );
1022 aResult.append( it->second );
1025 return aResult.makeStringAndClear();
1028 static void getAppleScrollBarVariant(StyleSettings &rSettings)
1030 bool bIsScrollbarDoubleMax = true; // default is DoubleMax
1032 CFStringRef AppleScrollBarType = CFSTR("AppleScrollBarVariant");
1033 if( AppleScrollBarType )
1035 CFStringRef ScrollBarVariant = static_cast<CFStringRef>(CFPreferencesCopyAppValue( AppleScrollBarType, kCFPreferencesCurrentApplication ));
1036 if( ScrollBarVariant )
1038 if( CFGetTypeID( ScrollBarVariant ) == CFStringGetTypeID() )
1040 // TODO: check for the less important variants "DoubleMin" and "DoubleBoth" too
1041 CFStringRef DoubleMax = CFSTR("DoubleMax");
1042 if (DoubleMax)
1044 if ( !CFStringCompare(ScrollBarVariant, DoubleMax, kCFCompareCaseInsensitive) )
1045 bIsScrollbarDoubleMax = true;
1046 else
1047 bIsScrollbarDoubleMax = false;
1048 CFRelease(DoubleMax);
1051 CFRelease( ScrollBarVariant );
1053 CFRelease(AppleScrollBarType);
1056 GetSalData()->mbIsScrollbarDoubleMax = bIsScrollbarDoubleMax;
1058 CFStringRef jumpScroll = CFSTR("AppleScrollerPagingBehavior");
1059 if( jumpScroll )
1061 CFBooleanRef jumpStr = static_cast<CFBooleanRef>(CFPreferencesCopyAppValue( jumpScroll, kCFPreferencesCurrentApplication ));
1062 if( jumpStr )
1064 if( CFGetTypeID( jumpStr ) == CFBooleanGetTypeID() )
1065 rSettings.SetPrimaryButtonWarpsSlider(jumpStr == kCFBooleanTrue);
1066 CFRelease( jumpStr );
1068 CFRelease( jumpScroll );
1072 static Color getColor( NSColor* pSysColor, const Color& rDefault, NSWindow* pWin )
1074 Color aRet( rDefault );
1075 if( pSysColor )
1077 // transform to RGB
1078 NSColor* pRBGColor = [pSysColor colorUsingColorSpaceName: NSDeviceRGBColorSpace device: [pWin deviceDescription]];
1079 if( pRBGColor )
1081 CGFloat r = 0, g = 0, b = 0, a = 0;
1082 [pRBGColor getRed: &r green: &g blue: &b alpha: &a];
1083 aRet = Color( int(r*255.999), int(g*255.999), int(b*255.999) );
1085 do not release here; leads to duplicate free in yield
1086 it seems the converted color comes out autoreleased, although this
1087 is not documented
1088 [pRBGColor release];
1092 return aRet;
1095 static vcl::Font getFont( NSFont* pFont, long nDPIY, const vcl::Font& rDefault )
1097 vcl::Font aResult( rDefault );
1098 if( pFont )
1100 aResult.SetName( GetOUString( [pFont familyName] ) );
1101 aResult.SetHeight( static_cast<int>(([pFont pointSize] * 72.0 / (float)nDPIY)+0.5) );
1102 aResult.SetItalic( ([pFont italicAngle] != 0.0) ? ITALIC_NORMAL : ITALIC_NONE );
1103 // FIMXE: bold ?
1106 return aResult;
1109 void AquaSalFrame::getResolution( sal_Int32& o_rDPIX, sal_Int32& o_rDPIY )
1111 if( ! mpGraphics )
1113 AcquireGraphics();
1114 ReleaseGraphics( mpGraphics );
1116 mpGraphics->GetResolution( o_rDPIX, o_rDPIY );
1119 // on OSX-Aqua the style settings are independent of the frame, so it does
1120 // not really belong here. Since the connection to the Appearance_Manager
1121 // is currently done in salnativewidgets.cxx this would be a good place.
1122 // On the other hand VCL's platform independent code currently only asks
1123 // SalFrames for system settings anyway, so moving the code somewhere else
1124 // doesn't make the anything cleaner for now
1125 void AquaSalFrame::UpdateSettings( AllSettings& rSettings )
1127 if ( !mpNSWindow )
1128 return;
1130 // #i113170# may not be the main thread if called from UNO API
1131 SalData::ensureThreadAutoreleasePool();
1133 [mpNSView lockFocus];
1135 StyleSettings aStyleSettings = rSettings.GetStyleSettings();
1137 // Background Color
1138 Color aBackgroundColor = Color( 0xEC, 0xEC, 0xEC );
1139 aStyleSettings.Set3DColors( aBackgroundColor );
1140 aStyleSettings.SetFaceColor( aBackgroundColor );
1141 Color aInactiveTabColor( aBackgroundColor );
1142 aInactiveTabColor.DecreaseLuminance( 32 );
1143 aStyleSettings.SetInactiveTabColor( aInactiveTabColor );
1145 aStyleSettings.SetDialogColor( aBackgroundColor );
1146 aStyleSettings.SetLightBorderColor( aBackgroundColor );
1147 Color aShadowColor( aStyleSettings.GetShadowColor() );
1148 aShadowColor.IncreaseLuminance( 32 );
1149 aStyleSettings.SetShadowColor( aShadowColor );
1151 // get the system font settings
1152 vcl::Font aAppFont = aStyleSettings.GetAppFont();
1153 sal_Int32 nDPIX = 72, nDPIY = 72;
1154 getResolution( nDPIX, nDPIY );
1155 aAppFont = getFont( [NSFont systemFontOfSize: 0], nDPIY, aAppFont );
1157 aStyleSettings.SetToolbarIconSize( ToolbarIconSize::Large );
1159 // TODO: better mapping of OS X<->LibreOffice font settings
1160 aStyleSettings.SetAppFont( aAppFont );
1161 aStyleSettings.SetHelpFont( aAppFont );
1162 aStyleSettings.SetPushButtonFont( aAppFont );
1164 vcl::Font aTitleFont( getFont( [NSFont titleBarFontOfSize: 0], nDPIY, aAppFont ) );
1165 aStyleSettings.SetTitleFont( aTitleFont );
1166 aStyleSettings.SetFloatTitleFont( aTitleFont );
1168 vcl::Font aMenuFont( getFont( [NSFont menuFontOfSize: 0], nDPIY, aAppFont ) );
1169 aStyleSettings.SetMenuFont( aMenuFont );
1171 aStyleSettings.SetToolFont( aAppFont );
1173 vcl::Font aLabelFont( getFont( [NSFont labelFontOfSize: 0], nDPIY, aAppFont ) );
1174 aStyleSettings.SetLabelFont( aLabelFont );
1175 aStyleSettings.SetInfoFont( aLabelFont );
1176 aStyleSettings.SetRadioCheckFont( aLabelFont );
1177 aStyleSettings.SetFieldFont( aLabelFont );
1178 aStyleSettings.SetGroupFont( aLabelFont );
1179 aStyleSettings.SetTabFont( aLabelFont );
1180 aStyleSettings.SetIconFont( aLabelFont );
1182 Color aHighlightColor( getColor( [NSColor selectedTextBackgroundColor],
1183 aStyleSettings.GetHighlightColor(), mpNSWindow ) );
1184 aStyleSettings.SetHighlightColor( aHighlightColor );
1185 Color aHighlightTextColor( getColor( [NSColor selectedTextColor],
1186 aStyleSettings.GetHighlightTextColor(), mpNSWindow ) );
1187 aStyleSettings.SetHighlightTextColor( aHighlightTextColor );
1189 Color aMenuHighlightColor( getColor( [NSColor selectedMenuItemColor],
1190 aStyleSettings.GetMenuHighlightColor(), mpNSWindow ) );
1191 aStyleSettings.SetMenuHighlightColor( aMenuHighlightColor );
1192 Color aMenuHighlightTextColor( getColor( [NSColor selectedMenuItemTextColor],
1193 aStyleSettings.GetMenuHighlightTextColor(), mpNSWindow ) );
1194 aStyleSettings.SetMenuHighlightTextColor( aMenuHighlightTextColor );
1196 aStyleSettings.SetMenuColor( aBackgroundColor );
1197 Color aMenuTextColor( getColor( [NSColor textColor],
1198 aStyleSettings.GetMenuTextColor(), mpNSWindow ) );
1199 aStyleSettings.SetMenuTextColor( aMenuTextColor );
1200 aStyleSettings.SetMenuBarTextColor( aMenuTextColor );
1201 aStyleSettings.SetMenuBarRolloverTextColor( aMenuTextColor );
1202 aStyleSettings.SetMenuBarHighlightTextColor(aStyleSettings.GetMenuHighlightTextColor());
1204 aStyleSettings.SetCursorBlinkTime( 500 );
1206 // no mnemonics on OS X
1207 aStyleSettings.SetOptions( aStyleSettings.GetOptions() | StyleSettingsOptions::NoMnemonics );
1209 getAppleScrollBarVariant(aStyleSettings);
1211 // set scrollbar size
1212 aStyleSettings.SetScrollBarSize( static_cast<long int>([NSScroller scrollerWidthForControlSize:NSRegularControlSize scrollerStyle:NSScrollerStyleLegacy]) );
1213 // images in menus false for MacOSX
1214 aStyleSettings.SetPreferredUseImagesInMenus( false );
1215 aStyleSettings.SetHideDisabledMenuItems( true );
1216 aStyleSettings.SetAcceleratorsInContextMenus( false );
1218 rSettings.SetStyleSettings( aStyleSettings );
1220 // don't draw frame around each and every toolbar
1221 ImplGetSVData()->maNWFData.mbDockingAreaAvoidTBFrames = true;
1223 [mpNSView unlockFocus];
1226 const SystemEnvData* AquaSalFrame::GetSystemData() const
1228 return &maSysData;
1231 void AquaSalFrame::Beep()
1233 NSBeep();
1236 void AquaSalFrame::SetPosSize(long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags)
1238 if ( !mpNSWindow )
1239 return;
1241 // #i113170# may not be the main thread if called from UNO API
1242 SalData::ensureThreadAutoreleasePool();
1244 sal_uInt16 nEvent = 0;
1246 if( [mpNSWindow isMiniaturized] )
1247 [mpNSWindow 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 = [mpNSWindow 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( AllSettings::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->mpNSWindow 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 [mpNSWindow setFrame: [NSWindow frameRectForContentRect: aContentRect styleMask: mnStyleMask] display: NO];
1311 UpdateFrameGeometry();
1313 if (nEvent)
1314 CallCallback(nEvent, NULL);
1316 if( mbShown && bPaint )
1318 // trigger filling our backbuffer
1319 SendPaintEvent();
1321 // now inform the system that the views need to be drawn
1322 [mpNSWindow display];
1326 void AquaSalFrame::GetWorkArea( Rectangle& rRect )
1328 if ( !mpNSWindow )
1329 return;
1331 // #i113170# may not be the main thread if called from UNO API
1332 SalData::ensureThreadAutoreleasePool();
1334 NSScreen* pScreen = [mpNSWindow screen];
1335 if( pScreen == nil )
1336 pScreen = [NSScreen mainScreen];
1337 NSRect aRect = [pScreen visibleFrame];
1338 CocoaToVCL( aRect );
1339 rRect.Left() = static_cast<long>(aRect.origin.x);
1340 rRect.Top() = static_cast<long>(aRect.origin.y);
1341 rRect.Right() = static_cast<long>(aRect.origin.x + aRect.size.width - 1);
1342 rRect.Bottom() = static_cast<long>(aRect.origin.y + aRect.size.height - 1);
1345 SalPointerState AquaSalFrame::GetPointerState()
1347 // #i113170# may not be the main thread if called from UNO API
1348 SalData::ensureThreadAutoreleasePool();
1350 SalPointerState state;
1351 state.mnState = 0;
1353 // get position
1354 NSPoint aPt = [mpNSWindow mouseLocationOutsideOfEventStream];
1355 CocoaToVCL( aPt, false );
1356 state.maPos = Point(static_cast<long>(aPt.x), static_cast<long>(aPt.y));
1358 NSEvent* pCur = [NSApp currentEvent];
1359 bool bMouseEvent = false;
1360 if( pCur )
1362 bMouseEvent = true;
1363 switch( [pCur type] )
1365 case NSLeftMouseDown: state.mnState |= MOUSE_LEFT; break;
1366 case NSLeftMouseUp: break;
1367 case NSRightMouseDown: state.mnState |= MOUSE_RIGHT; break;
1368 case NSRightMouseUp: break;
1369 case NSOtherMouseDown: state.mnState |= ([pCur buttonNumber] == 2) ? MOUSE_MIDDLE : 0; break;
1370 case NSOtherMouseUp: break;
1371 case NSMouseMoved: break;
1372 case NSLeftMouseDragged: state.mnState |= MOUSE_LEFT; break;
1373 case NSRightMouseDragged: state.mnState |= MOUSE_RIGHT; break;
1374 case NSOtherMouseDragged: state.mnState |= ([pCur buttonNumber] == 2) ? MOUSE_MIDDLE : 0; break;
1375 break;
1376 default:
1377 bMouseEvent = false;
1378 break;
1381 if( bMouseEvent )
1383 unsigned int nMask = (unsigned int)[pCur modifierFlags];
1384 if( (nMask & NSShiftKeyMask) != 0 )
1385 state.mnState |= KEY_SHIFT;
1386 if( (nMask & NSControlKeyMask) != 0 )
1387 state.mnState |= KEY_MOD3;
1388 if( (nMask & NSAlternateKeyMask) != 0 )
1389 state.mnState |= KEY_MOD2;
1390 if( (nMask & NSCommandKeyMask) != 0 )
1391 state.mnState |= KEY_MOD1;
1394 else
1396 // FIXME: replace Carbon by Cocoa
1397 // Cocoa does not have an equivalent for GetCurrentEventButtonState
1398 // and GetCurrentEventKeyModifiers.
1399 // we could try to get away with tracking all events for modifierKeys
1400 // and all mouse events for button state in VCL_NSApllication::sendEvent,
1401 // but it is unclear whether this will get us the same result.
1402 // leave in GetCurrentEventButtonState and GetCurrentEventKeyModifiers for now
1404 // fill in button state
1405 UInt32 nState = GetCurrentEventButtonState();
1406 state.mnState = 0;
1407 if( nState & 1 )
1408 state.mnState |= MOUSE_LEFT; // primary button
1409 if( nState & 2 )
1410 state.mnState |= MOUSE_RIGHT; // secondary button
1411 if( nState & 4 )
1412 state.mnState |= MOUSE_MIDDLE; // tertiary button
1414 // fill in modifier state
1415 nState = GetCurrentEventKeyModifiers();
1416 if( nState & shiftKey )
1417 state.mnState |= KEY_SHIFT;
1418 if( nState & controlKey )
1419 state.mnState |= KEY_MOD3;
1420 if( nState & optionKey )
1421 state.mnState |= KEY_MOD2;
1422 if( nState & cmdKey )
1423 state.mnState |= KEY_MOD1;
1426 return state;
1429 KeyIndicatorState AquaSalFrame::GetIndicatorState()
1431 return KeyIndicatorState::NONE;
1434 void AquaSalFrame::SimulateKeyPress( sal_uInt16 /*nKeyCode*/ )
1438 bool AquaSalFrame::SetPluginParent( SystemParentData* )
1440 // plugin parent may be killed unexpectedly by
1441 // plugging process;
1443 //TODO: implement
1444 return false;
1447 bool AquaSalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , vcl::KeyCode& )
1449 // not supported yet
1450 return FALSE;
1453 LanguageType AquaSalFrame::GetInputLanguage()
1455 //TODO: implement
1456 return LANGUAGE_DONTKNOW;
1459 void AquaSalFrame::DrawMenuBar()
1463 void AquaSalFrame::SetMenu( SalMenu* pSalMenu )
1465 // #i113170# may not be the main thread if called from UNO API
1466 SalData::ensureThreadAutoreleasePool();
1468 AquaSalMenu* pMenu = static_cast<AquaSalMenu*>(pSalMenu);
1469 DBG_ASSERT( ! pMenu || pMenu->mbMenuBar, "setting non menubar on frame" );
1470 mpMenu = pMenu;
1471 if( mpMenu )
1472 mpMenu->setMainMenu();
1475 void AquaSalFrame::SetExtendedFrameStyle( SalExtStyle nStyle )
1477 if ( mpNSWindow )
1479 // #i113170# may not be the main thread if called from UNO API
1480 SalData::ensureThreadAutoreleasePool();
1482 if( (mnExtStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) != (nStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) )
1483 [mpNSWindow setDocumentEdited: (nStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) ? YES : NO];
1486 mnExtStyle = nStyle;
1489 SalFrame* AquaSalFrame::GetParent() const
1491 return mpParent;
1494 void AquaSalFrame::SetParent( SalFrame* pNewParent )
1496 bool bShown = mbShown;
1497 // remove from child list
1498 Show( FALSE );
1499 mpParent = static_cast<AquaSalFrame*>(pNewParent);
1500 // insert to correct parent and paint
1501 Show( bShown );
1504 void AquaSalFrame::UpdateFrameGeometry()
1506 if ( !mpNSWindow )
1508 return;
1511 // keep in mind that view and window coordinates are lower left
1512 // whereas vcl's are upper left
1514 // update screen rect
1515 NSScreen * pScreen = [mpNSWindow screen];
1516 if( pScreen )
1518 maScreenRect = [pScreen frame];
1519 NSArray* pScreens = [NSScreen screens];
1520 if( pScreens )
1521 maGeometry.nDisplayScreenNumber = [pScreens indexOfObject: pScreen];
1524 NSRect aFrameRect = [mpNSWindow frame];
1525 NSRect aContentRect = [NSWindow contentRectForFrameRect: aFrameRect styleMask: mnStyleMask];
1527 // release old track rect
1528 [mpNSView removeTrackingRect: mnTrackingRectTag];
1529 // install the new track rect
1530 NSRect aTrackRect = { NSZeroPoint, aContentRect.size };
1531 mnTrackingRectTag = [mpNSView addTrackingRect: aTrackRect owner: mpNSView userData: nil assumeInside: NO];
1533 // convert to vcl convention
1534 CocoaToVCL( aFrameRect );
1535 CocoaToVCL( aContentRect );
1537 maGeometry.nX = static_cast<int>(aContentRect.origin.x);
1538 maGeometry.nY = static_cast<int>(aContentRect.origin.y);
1540 maGeometry.nLeftDecoration = static_cast<unsigned int>(aContentRect.origin.x - aFrameRect.origin.x);
1541 maGeometry.nRightDecoration = static_cast<unsigned int>((aFrameRect.origin.x + aFrameRect.size.width) -
1542 (aContentRect.origin.x + aContentRect.size.width));
1544 maGeometry.nTopDecoration = static_cast<unsigned int>(aContentRect.origin.y - aFrameRect.origin.y);
1545 maGeometry.nBottomDecoration = static_cast<unsigned int>((aFrameRect.origin.y + aFrameRect.size.height) -
1546 (aContentRect.origin.y + aContentRect.size.height));
1548 maGeometry.nWidth = static_cast<unsigned int>(aContentRect.size.width);
1549 maGeometry.nHeight = static_cast<unsigned int>(aContentRect.size.height);
1552 void AquaSalFrame::CaptureMouse( bool bCapture )
1554 /* Remark:
1555 we'll try to use a pidgin version of capture mouse
1556 on MacOSX (neither carbon nor cocoa) there is a
1557 CaptureMouse equivalent (in Carbon there is TrackMouseLocation
1558 but this is useless to use since it is blocking)
1560 However on cocoa the active frame seems to get mouse events
1561 also outside the window, so we'll try to forward mouse events
1562 to the capture frame in the hope that one of our frames
1563 gets a mouse event.
1565 This will break as soon as the user activates another app, but
1566 a mouse click will normally lead to a release of the mouse anyway.
1568 Let's see how far we get this way. Alternatively we could use one
1569 large overlay window like we did for the carbon implementation,
1570 however that is resource intensive.
1573 if( bCapture )
1574 s_pCaptureFrame = this;
1575 else if( ! bCapture && s_pCaptureFrame == this )
1576 s_pCaptureFrame = NULL;
1579 void AquaSalFrame::ResetClipRegion()
1581 if ( !mpNSWindow )
1583 return;
1586 // #i113170# may not be the main thread if called from UNO API
1587 SalData::ensureThreadAutoreleasePool();
1589 // release old path and indicate no clipping
1590 CGPathRelease( mrClippingPath );
1591 mrClippingPath = NULL;
1593 if( mpNSView && mbShown )
1594 [mpNSView setNeedsDisplay: YES];
1595 if( mpNSWindow )
1597 [mpNSWindow setOpaque: YES];
1598 [mpNSWindow invalidateShadow];
1602 void AquaSalFrame::BeginSetClipRegion( sal_uLong nRects )
1604 if ( !mpNSWindow )
1606 return;
1609 // #i113170# may not be the main thread if called from UNO API
1610 SalData::ensureThreadAutoreleasePool();
1612 // release old path
1613 if( mrClippingPath )
1615 CGPathRelease( mrClippingPath );
1616 mrClippingPath = NULL;
1619 if( maClippingRects.size() > SAL_CLIPRECT_COUNT && nRects < maClippingRects.size() )
1621 std::vector<CGRect> aEmptyVec;
1622 maClippingRects.swap( aEmptyVec );
1624 maClippingRects.clear();
1625 maClippingRects.reserve( nRects );
1628 void AquaSalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
1630 // #i113170# may not be the main thread if called from UNO API
1631 SalData::ensureThreadAutoreleasePool();
1633 if( nWidth && nHeight )
1635 NSRect aRect = { { static_cast<CGFloat>(nX), static_cast<CGFloat>(nY) }, { static_cast<CGFloat>(nWidth), static_cast<CGFloat>(nHeight) } };
1636 VCLToCocoa( aRect, false );
1637 maClippingRects.push_back( CGRectMake(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height) );
1641 void AquaSalFrame::EndSetClipRegion()
1643 if ( !mpNSWindow )
1645 return;
1648 // #i113170# may not be the main thread if called from UNO API
1649 SalData::ensureThreadAutoreleasePool();
1651 if( ! maClippingRects.empty() )
1653 mrClippingPath = CGPathCreateMutable();
1654 CGPathAddRects( mrClippingPath, NULL, &maClippingRects[0], maClippingRects.size() );
1656 if( mpNSView && mbShown )
1657 [mpNSView setNeedsDisplay: YES];
1658 if( mpNSWindow )
1660 [mpNSWindow setOpaque: (mrClippingPath != NULL) ? NO : YES];
1661 [mpNSWindow setBackgroundColor: [NSColor clearColor]];
1662 // shadow is invalidated when view gets drawn again
1666 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */