Branch libreoffice-7-2-5
[LibreOffice.git] / vcl / osx / salframe.cxx
blob18263fa5ea462ba8dd768b32ef4f37625809836e
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 <comphelper/fileurl.hxx>
23 #include <rtl/ustrbuf.hxx>
24 #include <sal/log.hxx>
25 #include <tools/long.hxx>
26 #include <o3tl/safeint.hxx>
27 #include <osl/diagnose.h>
29 #include <osl/file.h>
31 #include <vcl/event.hxx>
32 #include <vcl/inputctx.hxx>
33 #include <vcl/svapp.hxx>
34 #include <vcl/window.hxx>
35 #include <vcl/syswin.hxx>
36 #include <vcl/settings.hxx>
38 #include <osx/saldata.hxx>
39 #include <quartz/salgdi.h>
40 #include <osx/salframe.h>
41 #include <osx/salmenu.h>
42 #include <osx/salinst.h>
43 #include <osx/salframeview.h>
44 #include <osx/a11yfactory.h>
45 #include <osx/runinmain.hxx>
46 #include <quartz/utils.h>
48 #include <salwtype.hxx>
50 #include <premac.h>
51 #include <objc/objc-runtime.h>
52 // needed for theming
53 // FIXME: move theming code to salnativewidgets.cxx
54 #include <Carbon/Carbon.h>
55 #include <postmac.h>
57 using namespace std;
59 AquaSalFrame* AquaSalFrame::s_pCaptureFrame = nullptr;
61 AquaSalFrame::AquaSalFrame( SalFrame* pParent, SalFrameStyleFlags salFrameStyle ) :
62 mpNSWindow(nil),
63 mpNSView(nil),
64 mpDockMenuEntry(nil),
65 mpGraphics(nullptr),
66 mpParent(nullptr),
67 mnMinWidth(0),
68 mnMinHeight(0),
69 mnMaxWidth(0),
70 mnMaxHeight(0),
71 mbGraphics(false),
72 mbFullScreen( false ),
73 mbShown(false),
74 mbInitShow(true),
75 mbPositioned(false),
76 mbSized(false),
77 mbPresentation( false ),
78 mnStyle( salFrameStyle ),
79 mnStyleMask( 0 ),
80 mnLastEventTime( 0 ),
81 mnLastModifierFlags( 0 ),
82 mpMenu( nullptr ),
83 mnExtStyle( 0 ),
84 mePointerStyle( PointerStyle::Arrow ),
85 mnTrackingRectTag( 0 ),
86 mrClippingPath( nullptr ),
87 mnICOptions( InputContextFlags::NONE ),
88 mnBlinkCursorDelay ( 500 )
90 mpParent = dynamic_cast<AquaSalFrame*>(pParent);
92 initWindowAndView();
94 SalData* pSalData = GetSalData();
95 pSalData->mpInstance->insertFrame( this );
96 NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
97 if (userDefaults != nil)
99 id setting = [userDefaults objectForKey: @"NSTextInsertionPointBlinkPeriodOn"];
100 if (setting)
101 mnBlinkCursorDelay = [setting intValue];
102 else
104 setting = [userDefaults objectForKey: @"NSTextInsertionPointBlinkPeriodOff"];
105 if (setting)
106 mnBlinkCursorDelay = [setting intValue];
111 AquaSalFrame::~AquaSalFrame()
113 if (mbFullScreen)
114 doShowFullScreen(false, maGeometry.nDisplayScreenNumber);
116 assert( GetSalData()->mpInstance->IsMainThread() );
118 // if the frame is destroyed and has the current menubar
119 // set the default menubar
120 if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu )
121 AquaSalMenu::setDefaultMenu();
123 // cleanup clipping stuff
124 doResetClipRegion();
126 [SalFrameView unsetMouseFrame: this];
128 SalData* pSalData = GetSalData();
129 pSalData->mpInstance->eraseFrame( this );
130 pSalData->maPresentationFrames.remove( this );
132 SAL_WARN_IF( this == s_pCaptureFrame, "vcl", "capture frame destroyed" );
133 if( this == s_pCaptureFrame )
134 s_pCaptureFrame = nullptr;
136 delete mpGraphics;
138 if( mpDockMenuEntry )
140 NSMenu* pDock = AquaSalInstance::GetDynamicDockMenu();
141 // life cycle comment: the menu has ownership of the item, so no release
142 [pDock removeItem: mpDockMenuEntry];
143 if ([pDock numberOfItems] != 0
144 && [[pDock itemAtIndex: 0] isSeparatorItem])
146 [pDock removeItemAtIndex: 0];
149 if ( mpNSView ) {
150 [AquaA11yFactory revokeView: mpNSView];
151 [mpNSView release];
153 if ( mpNSWindow )
154 [mpNSWindow release];
157 void AquaSalFrame::initWindowAndView()
159 OSX_SALDATA_RUNINMAIN( initWindowAndView() )
161 // initialize mirroring parameters
162 // FIXME: screens changing
163 NSScreen* pNSScreen = [mpNSWindow screen];
164 if( pNSScreen == nil )
165 pNSScreen = [NSScreen mainScreen];
166 maScreenRect = [pNSScreen frame];
168 // calculate some default geometry
169 NSRect aVisibleRect = [pNSScreen visibleFrame];
170 CocoaToVCL( aVisibleRect );
172 maGeometry.nX = static_cast<int>(aVisibleRect.origin.x + aVisibleRect.size.width / 10);
173 maGeometry.nY = static_cast<int>(aVisibleRect.origin.y + aVisibleRect.size.height / 10);
174 maGeometry.nWidth = static_cast<unsigned int>(aVisibleRect.size.width * 0.8);
175 maGeometry.nHeight = static_cast<unsigned int>(aVisibleRect.size.height * 0.8);
177 // calculate style mask
178 SAL_WNODEPRECATED_DECLARATIONS_PUSH
179 // 'NSBorderlessWindowMask' is deprecated: first deprecated in macOS 10.12
180 // 'NSClosableWindowMask' is deprecated: first deprecated in macOS 10.12
181 // 'NSMiniaturizableWindowMask' is deprecated: first deprecated in macOS 10.12
182 // 'NSResizableWindowMask' is deprecated: first deprecated in macOS 10.12
183 // 'NSTitledWindowMask' is deprecated: first deprecated in macOS 10.12
184 if( (mnStyle & SalFrameStyleFlags::FLOAT) ||
185 (mnStyle & SalFrameStyleFlags::OWNERDRAWDECORATION) )
186 mnStyleMask = NSBorderlessWindowMask;
187 else if( mnStyle & SalFrameStyleFlags::DEFAULT )
189 mnStyleMask = NSTitledWindowMask |
190 NSMiniaturizableWindowMask |
191 NSResizableWindowMask |
192 NSClosableWindowMask;
193 // make default window "maximized"
194 maGeometry.nX = static_cast<int>(aVisibleRect.origin.x);
195 maGeometry.nY = static_cast<int>(aVisibleRect.origin.y);
196 maGeometry.nWidth = static_cast<int>(aVisibleRect.size.width);
197 maGeometry.nHeight = static_cast<int>(aVisibleRect.size.height);
198 mbPositioned = mbSized = true;
200 else
202 if( mnStyle & SalFrameStyleFlags::MOVEABLE )
204 mnStyleMask |= NSTitledWindowMask;
205 if( mpParent == nullptr )
206 mnStyleMask |= NSMiniaturizableWindowMask;
208 if( mnStyle & SalFrameStyleFlags::SIZEABLE )
209 mnStyleMask |= NSResizableWindowMask;
210 if( mnStyle & SalFrameStyleFlags::CLOSEABLE )
211 mnStyleMask |= NSClosableWindowMask;
212 // documentation says anything other than NSBorderlessWindowMask (=0)
213 // should also include NSTitledWindowMask;
214 if( mnStyleMask != 0 )
215 mnStyleMask |= NSTitledWindowMask;
217 SAL_WNODEPRECATED_DECLARATIONS_POP
219 if (Application::IsBitmapRendering())
220 return;
222 // #i91990# support GUI-less (daemon) execution
223 @try
225 mpNSWindow = [[SalFrameWindow alloc] initWithSalFrame: this];
226 mpNSView = [[SalFrameView alloc] initWithSalFrame: this];
228 @catch ( id )
230 std::abort();
233 if( mnStyle & SalFrameStyleFlags::TOOLTIP )
234 [mpNSWindow setIgnoresMouseEvents: YES];
235 else
236 [mpNSWindow setAcceptsMouseMovedEvents: YES];
237 [mpNSWindow setHasShadow: YES];
239 [mpNSWindow setDelegate: static_cast<id<NSWindowDelegate> >(mpNSWindow)];
241 [mpNSWindow setRestorable:NO];
242 const NSRect aRect = { NSZeroPoint, NSMakeSize( maGeometry.nWidth, maGeometry.nHeight )};
243 mnTrackingRectTag = [mpNSView addTrackingRect: aRect owner: mpNSView userData: nil assumeInside: NO];
245 maSysData.mpNSView = mpNSView;
247 UpdateFrameGeometry();
249 [mpNSWindow setContentView: mpNSView];
252 void AquaSalFrame::CocoaToVCL( NSRect& io_rRect, bool bRelativeToScreen )
254 if( bRelativeToScreen )
255 io_rRect.origin.y = maScreenRect.size.height - (io_rRect.origin.y+io_rRect.size.height);
256 else
257 io_rRect.origin.y = maGeometry.nHeight - (io_rRect.origin.y+io_rRect.size.height);
260 void AquaSalFrame::VCLToCocoa( NSRect& io_rRect, bool bRelativeToScreen )
262 if( bRelativeToScreen )
263 io_rRect.origin.y = maScreenRect.size.height - (io_rRect.origin.y+io_rRect.size.height);
264 else
265 io_rRect.origin.y = maGeometry.nHeight - (io_rRect.origin.y+io_rRect.size.height);
268 void AquaSalFrame::CocoaToVCL( NSPoint& io_rPoint, bool bRelativeToScreen )
270 if( bRelativeToScreen )
271 io_rPoint.y = maScreenRect.size.height - io_rPoint.y;
272 else
273 io_rPoint.y = maGeometry.nHeight - io_rPoint.y;
276 void AquaSalFrame::VCLToCocoa( NSPoint& io_rPoint, bool bRelativeToScreen )
278 if( bRelativeToScreen )
279 io_rPoint.y = maScreenRect.size.height - io_rPoint.y;
280 else
281 io_rPoint.y = maGeometry.nHeight - io_rPoint.y;
284 void AquaSalFrame::screenParametersChanged()
286 OSX_SALDATA_RUNINMAIN( screenParametersChanged() )
288 UpdateFrameGeometry();
290 if( mpGraphics )
291 mpGraphics->updateResolution();
293 if (!mbGeometryDidChange)
294 return;
296 CallCallback( SalEvent::DisplayChanged, nullptr );
299 SalGraphics* AquaSalFrame::AcquireGraphics()
301 if ( mbGraphics )
302 return nullptr;
304 if ( !mpGraphics )
306 mpGraphics = new AquaSalGraphics;
307 mpGraphics->SetWindowGraphics( this );
310 mbGraphics = true;
311 return mpGraphics;
314 void AquaSalFrame::ReleaseGraphics( SalGraphics *pGraphics )
316 SAL_WARN_IF( pGraphics != mpGraphics, "vcl", "graphics released on wrong frame" );
317 mbGraphics = false;
320 bool AquaSalFrame::PostEvent(std::unique_ptr<ImplSVEvent> pData)
322 GetSalData()->mpInstance->PostEvent( this, pData.release(), SalEvent::UserEvent );
323 return true;
326 void AquaSalFrame::SetTitle(const OUString& rTitle)
328 if ( !mpNSWindow )
329 return;
331 OSX_SALDATA_RUNINMAIN( SetTitle(rTitle) )
333 // #i113170# may not be the main thread if called from UNO API
334 SalData::ensureThreadAutoreleasePool();
336 NSString* pTitle = CreateNSString( rTitle );
337 [mpNSWindow setTitle: pTitle];
339 // create an entry in the dock menu
340 const SalFrameStyleFlags nAppWindowStyle = SalFrameStyleFlags::CLOSEABLE | SalFrameStyleFlags::MOVEABLE;
341 if( mpParent == nullptr &&
342 (mnStyle & nAppWindowStyle) == nAppWindowStyle )
344 if( mpDockMenuEntry == nullptr )
346 NSMenu* pDock = AquaSalInstance::GetDynamicDockMenu();
348 if ([pDock numberOfItems] != 0) {
349 NSMenuItem* pTopItem = [pDock itemAtIndex: 0];
350 if ( [pTopItem hasSubmenu] )
351 [pDock insertItem: [NSMenuItem separatorItem] atIndex: 0];
354 mpDockMenuEntry = [pDock insertItemWithTitle: pTitle
355 action: @selector(dockMenuItemTriggered:)
356 keyEquivalent: @""
357 atIndex: 0];
358 [mpDockMenuEntry setTarget: mpNSWindow];
360 // TODO: image (either the generic window image or an icon
361 // check mark (for "main" window ?)
363 else
364 [mpDockMenuEntry setTitle: pTitle];
367 if (pTitle)
368 [pTitle release];
371 void AquaSalFrame::SetIcon( sal_uInt16 )
375 void AquaSalFrame::SetRepresentedURL( const OUString& i_rDocURL )
377 OSX_SALDATA_RUNINMAIN( SetRepresentedURL( i_rDocURL ) )
379 if( comphelper::isFileUrl(i_rDocURL) )
381 OUString aSysPath;
382 osl_getSystemPathFromFileURL( i_rDocURL.pData, &aSysPath.pData );
383 NSString* pStr = CreateNSString( aSysPath );
384 if( pStr )
386 [pStr autorelease];
387 [mpNSWindow setRepresentedFilename: pStr];
392 void AquaSalFrame::initShow()
394 OSX_SALDATA_RUNINMAIN( initShow() )
396 mbInitShow = false;
397 if( ! mbPositioned && ! mbFullScreen )
399 tools::Rectangle aScreenRect;
400 GetWorkArea( aScreenRect );
401 if( mpParent ) // center relative to parent
403 // center on parent
404 tools::Long nNewX = mpParent->maGeometry.nX + (static_cast<tools::Long>(mpParent->maGeometry.nWidth) - static_cast<tools::Long>(maGeometry.nWidth))/2;
405 if( nNewX < aScreenRect.Left() )
406 nNewX = aScreenRect.Left();
407 if( tools::Long(nNewX + maGeometry.nWidth) > aScreenRect.Right() )
408 nNewX = aScreenRect.Right() - maGeometry.nWidth-1;
409 tools::Long nNewY = mpParent->maGeometry.nY + (static_cast<tools::Long>(mpParent->maGeometry.nHeight) - static_cast<tools::Long>(maGeometry.nHeight))/2;
410 if( nNewY < aScreenRect.Top() )
411 nNewY = aScreenRect.Top();
412 if( nNewY > aScreenRect.Bottom() )
413 nNewY = aScreenRect.Bottom() - maGeometry.nHeight-1;
414 SetPosSize( nNewX - mpParent->maGeometry.nX,
415 nNewY - mpParent->maGeometry.nY,
416 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y );
418 else if( ! (mnStyle & SalFrameStyleFlags::SIZEABLE) )
420 // center on screen
421 tools::Long nNewX = (aScreenRect.GetWidth() - maGeometry.nWidth)/2;
422 tools::Long nNewY = (aScreenRect.GetHeight() - maGeometry.nHeight)/2;
423 SetPosSize( nNewX, nNewY, 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y );
427 // make sure the view is present in the wrapper list before any children receive focus
428 [AquaA11yFactory registerView: mpNSView];
431 void AquaSalFrame::SendPaintEvent( const tools::Rectangle* pRect )
433 OSX_SALDATA_RUNINMAIN( SendPaintEvent( pRect ) )
435 SalPaintEvent aPaintEvt( 0, 0, maGeometry.nWidth, maGeometry.nHeight, true );
436 if( pRect )
438 aPaintEvt.mnBoundX = pRect->Left();
439 aPaintEvt.mnBoundY = pRect->Top();
440 aPaintEvt.mnBoundWidth = pRect->GetWidth();
441 aPaintEvt.mnBoundHeight = pRect->GetHeight();
444 CallCallback(SalEvent::Paint, &aPaintEvt);
447 void AquaSalFrame::Show(bool bVisible, bool bNoActivate)
449 if ( !mpNSWindow )
450 return;
452 OSX_SALDATA_RUNINMAIN( Show(bVisible, bNoActivate) )
454 mbShown = bVisible;
455 if(bVisible)
457 if( mbInitShow )
458 initShow();
460 CallCallback(SalEvent::Resize, nullptr);
461 // trigger filling our backbuffer
462 SendPaintEvent();
464 if( bNoActivate || [mpNSWindow canBecomeKeyWindow] == NO )
465 [mpNSWindow orderFront: NSApp];
466 else
467 [mpNSWindow makeKeyAndOrderFront: NSApp];
469 if( mpParent )
471 /* #i92674# #i96433# we do not want an invisible parent to show up (which adding a visible
472 child implicitly does). However we also do not want a parentless toolbar.
474 HACK: try to decide when we should not insert a child to its parent
475 floaters and ownerdraw windows have not yet shown up in cases where
476 we don't want the parent to become visible
478 if( mpParent->mbShown || (mnStyle & (SalFrameStyleFlags::OWNERDRAWDECORATION | SalFrameStyleFlags::FLOAT) ) )
480 [mpParent->mpNSWindow addChildWindow: mpNSWindow ordered: NSWindowAbove];
484 if( mbPresentation )
485 [mpNSWindow makeMainWindow];
487 else
489 // if the frame holding the current menubar gets hidden
490 // show the default menubar
491 if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu )
492 AquaSalMenu::setDefaultMenu();
494 // #i90440# #i94443# work around the focus going back to some other window
495 // if a child gets hidden for a parent window
496 if( mpParent && mpParent->mbShown && [mpNSWindow isKeyWindow] )
497 [mpParent->mpNSWindow makeKeyAndOrderFront: NSApp];
499 [SalFrameView unsetMouseFrame: this];
500 if( mpParent && [mpNSWindow parentWindow] == mpParent->mpNSWindow )
501 [mpParent->mpNSWindow removeChildWindow: mpNSWindow];
503 [mpNSWindow orderOut: NSApp];
507 void AquaSalFrame::SetMinClientSize( tools::Long nWidth, tools::Long nHeight )
509 OSX_SALDATA_RUNINMAIN( SetMinClientSize( nWidth, nHeight ) )
511 mnMinWidth = nWidth;
512 mnMinHeight = nHeight;
514 if( mpNSWindow )
516 // Always add the decoration as the dimension concerns only
517 // the content rectangle
518 nWidth += maGeometry.nLeftDecoration + maGeometry.nRightDecoration;
519 nHeight += maGeometry.nTopDecoration + maGeometry.nBottomDecoration;
521 NSSize aSize = { static_cast<CGFloat>(nWidth), static_cast<CGFloat>(nHeight) };
523 // Size of full window (content+structure) although we only
524 // have the client size in arguments
525 [mpNSWindow setMinSize: aSize];
529 void AquaSalFrame::SetMaxClientSize( tools::Long nWidth, tools::Long nHeight )
531 OSX_SALDATA_RUNINMAIN( SetMaxClientSize( nWidth, nHeight ) )
533 mnMaxWidth = nWidth;
534 mnMaxHeight = nHeight;
536 if( mpNSWindow )
538 // Always add the decoration as the dimension concerns only
539 // the content rectangle
540 nWidth += maGeometry.nLeftDecoration + maGeometry.nRightDecoration;
541 nHeight += maGeometry.nTopDecoration + maGeometry.nBottomDecoration;
543 // Carbon windows can't have a size greater than 32767x32767
544 if (nWidth>32767) nWidth=32767;
545 if (nHeight>32767) nHeight=32767;
547 NSSize aSize = { static_cast<CGFloat>(nWidth), static_cast<CGFloat>(nHeight) };
549 // Size of full window (content+structure) although we only
550 // have the client size in arguments
551 [mpNSWindow setMaxSize: aSize];
555 void AquaSalFrame::GetClientSize( tools::Long& rWidth, tools::Long& rHeight )
557 if (mbShown || mbInitShow || Application::IsBitmapRendering())
559 rWidth = maGeometry.nWidth;
560 rHeight = maGeometry.nHeight;
562 else
564 rWidth = 0;
565 rHeight = 0;
569 SalEvent AquaSalFrame::PreparePosSize(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, sal_uInt16 nFlags)
571 SalEvent nEvent = SalEvent::NONE;
572 assert(mpNSWindow || Application::IsBitmapRendering());
574 if (nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y))
576 mbPositioned = true;
577 nEvent = SalEvent::Move;
580 if (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT))
582 mbSized = true;
583 nEvent = (nEvent == SalEvent::Move) ? SalEvent::MoveResize : SalEvent::Resize;
586 if (Application::IsBitmapRendering())
588 if (nFlags & SAL_FRAME_POSSIZE_X)
589 maGeometry.nX = nX;
590 if (nFlags & SAL_FRAME_POSSIZE_Y)
591 maGeometry.nY = nY;
592 if (nFlags & SAL_FRAME_POSSIZE_WIDTH)
594 maGeometry.nWidth = nWidth;
595 if (mnMaxWidth > 0 && maGeometry.nWidth > o3tl::make_unsigned(mnMaxWidth))
596 maGeometry.nWidth = mnMaxWidth;
597 if (mnMinWidth > 0 && maGeometry.nWidth < o3tl::make_unsigned(mnMinWidth))
598 maGeometry.nWidth = mnMinWidth;
600 if (nFlags & SAL_FRAME_POSSIZE_HEIGHT)
602 maGeometry.nHeight = nHeight;
603 if (mnMaxHeight > 0 && maGeometry.nHeight > o3tl::make_unsigned(mnMaxHeight))
604 maGeometry.nHeight = mnMaxHeight;
605 if (mnMinHeight > 0 && maGeometry.nHeight < o3tl::make_unsigned(mnMinHeight))
606 maGeometry.nHeight = mnMinHeight;
608 if (nEvent != SalEvent::NONE)
609 CallCallback(nEvent, nullptr);
612 return nEvent;
615 void AquaSalFrame::SetWindowState( const SalFrameState* pState )
617 if (!mpNSWindow && !Application::IsBitmapRendering())
618 return;
620 OSX_SALDATA_RUNINMAIN( SetWindowState( pState ) )
622 sal_uInt16 nFlags = 0;
623 nFlags |= ((pState->mnMask & WindowStateMask::X) ? SAL_FRAME_POSSIZE_X : 0);
624 nFlags |= ((pState->mnMask & WindowStateMask::Y) ? SAL_FRAME_POSSIZE_Y : 0);
625 nFlags |= ((pState->mnMask & WindowStateMask::Width) ? SAL_FRAME_POSSIZE_WIDTH : 0);
626 nFlags |= ((pState->mnMask & WindowStateMask::Height) ? SAL_FRAME_POSSIZE_HEIGHT : 0);
628 SalEvent nEvent = PreparePosSize(pState->mnX, pState->mnY, pState->mnWidth, pState->mnHeight, nFlags);
629 if (Application::IsBitmapRendering())
630 return;
632 // set normal state
633 NSRect aStateRect = [mpNSWindow frame];
634 aStateRect = [NSWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask];
635 CocoaToVCL(aStateRect);
636 if (pState->mnMask & WindowStateMask::X)
637 aStateRect.origin.x = float(pState->mnX);
638 if (pState->mnMask & WindowStateMask::Y)
639 aStateRect.origin.y = float(pState->mnY);
640 if (pState->mnMask & WindowStateMask::Width)
641 aStateRect.size.width = float(pState->mnWidth);
642 if (pState->mnMask & WindowStateMask::Height)
643 aStateRect.size.height = float(pState->mnHeight);
644 VCLToCocoa(aStateRect);
645 aStateRect = [NSWindow frameRectForContentRect: aStateRect styleMask: mnStyleMask];
646 [mpNSWindow setFrame: aStateRect display: NO];
648 if (pState->mnState == WindowStateState::Minimized)
649 [mpNSWindow miniaturize: NSApp];
650 else if ([mpNSWindow isMiniaturized])
651 [mpNSWindow deminiaturize: NSApp];
653 /* ZOOMED is not really maximized (actually it toggles between a user set size and
654 the program specified one), but comes closest since the default behavior is
655 "maximized" if the user did not intervene
657 if (pState->mnState == WindowStateState::Maximized)
659 if (![mpNSWindow isZoomed])
660 [mpNSWindow zoom: NSApp];
662 else
664 if ([mpNSWindow isZoomed])
665 [mpNSWindow zoom: NSApp];
668 // get new geometry
669 UpdateFrameGeometry();
671 // send event that we were moved/sized
672 if( nEvent != SalEvent::NONE )
673 CallCallback( nEvent, nullptr );
675 if (mbShown)
677 // trigger filling our backbuffer
678 SendPaintEvent();
680 // tell the system the views need to be updated
681 [mpNSWindow display];
685 bool AquaSalFrame::GetWindowState( SalFrameState* pState )
687 if (!mpNSWindow)
689 if (Application::IsBitmapRendering())
691 pState->mnMask = WindowStateMask::X | WindowStateMask::Y
692 | WindowStateMask::Width | WindowStateMask::Height
693 | WindowStateMask::State;
694 pState->mnX = maGeometry.nX;
695 pState->mnY = maGeometry.nY;
696 pState->mnWidth = maGeometry.nWidth;
697 pState->mnHeight = maGeometry.nHeight;
698 pState->mnState = WindowStateState::Normal;
699 return true;
701 return false;
704 OSX_SALDATA_RUNINMAIN_UNION( GetWindowState( pState ), boolean )
706 pState->mnMask = WindowStateMask::X |
707 WindowStateMask::Y |
708 WindowStateMask::Width |
709 WindowStateMask::Height |
710 WindowStateMask::State;
712 NSRect aStateRect = [mpNSWindow frame];
713 aStateRect = [NSWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask];
714 CocoaToVCL( aStateRect );
715 pState->mnX = tools::Long(aStateRect.origin.x);
716 pState->mnY = tools::Long(aStateRect.origin.y);
717 pState->mnWidth = tools::Long(aStateRect.size.width);
718 pState->mnHeight = tools::Long(aStateRect.size.height);
720 if( [mpNSWindow isMiniaturized] )
721 pState->mnState = WindowStateState::Minimized;
722 else if( ! [mpNSWindow isZoomed] )
723 pState->mnState = WindowStateState::Normal;
724 else
725 pState->mnState = WindowStateState::Maximized;
727 return true;
730 void AquaSalFrame::SetScreenNumber(unsigned int nScreen)
732 if ( !mpNSWindow )
733 return;
735 OSX_SALDATA_RUNINMAIN( SetScreenNumber( nScreen ) )
737 NSArray* pScreens = [NSScreen screens];
738 NSScreen* pScreen = nil;
739 if( pScreens && nScreen < [pScreens count] )
741 // get new screen frame
742 pScreen = [pScreens objectAtIndex: nScreen];
743 NSRect aNewScreen = [pScreen frame];
745 // get current screen frame
746 pScreen = [mpNSWindow screen];
747 if( pScreen )
749 NSRect aCurScreen = [pScreen frame];
750 if( aCurScreen.origin.x != aNewScreen.origin.x ||
751 aCurScreen.origin.y != aNewScreen.origin.y )
753 NSRect aFrameRect = [mpNSWindow frame];
754 aFrameRect.origin.x += aNewScreen.origin.x - aCurScreen.origin.x;
755 aFrameRect.origin.y += aNewScreen.origin.y - aCurScreen.origin.y;
756 [mpNSWindow setFrame: aFrameRect display: NO];
757 UpdateFrameGeometry();
763 void AquaSalFrame::SetApplicationID( const OUString &/*rApplicationID*/ )
767 void AquaSalFrame::ShowFullScreen( bool bFullScreen, sal_Int32 nDisplay )
769 doShowFullScreen(bFullScreen, nDisplay);
772 void AquaSalFrame::doShowFullScreen( bool bFullScreen, sal_Int32 nDisplay )
774 if (!mpNSWindow)
776 if (Application::IsBitmapRendering() && bFullScreen)
777 SetPosSize(0, 0, 1024, 768, SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT);
778 return;
781 SAL_INFO("vcl.osx", __func__ << ": mbFullScreen=" << mbFullScreen << ", bFullScreen=" << bFullScreen);
783 if( mbFullScreen == bFullScreen )
784 return;
786 OSX_SALDATA_RUNINMAIN( ShowFullScreen( bFullScreen, nDisplay ) )
788 mbFullScreen = bFullScreen;
790 if( bFullScreen )
792 // hide the dock and the menubar if we are on the menu screen
793 // which is always on index 0 according to documentation
794 bool bHideMenu = (nDisplay == 0);
796 NSRect aNewContentRect = NSZeroRect;
797 // get correct screen
798 NSScreen* pScreen = nil;
799 NSArray* pScreens = [NSScreen screens];
800 if( pScreens )
802 if( nDisplay >= 0 && o3tl::make_unsigned(nDisplay) < [pScreens count] )
803 pScreen = [pScreens objectAtIndex: nDisplay];
804 else
806 // this means span all screens
807 bHideMenu = true;
808 NSEnumerator* pEnum = [pScreens objectEnumerator];
809 while( (pScreen = [pEnum nextObject]) != nil )
811 NSRect aScreenRect = [pScreen frame];
812 if( aScreenRect.origin.x < aNewContentRect.origin.x )
814 aNewContentRect.size.width += aNewContentRect.origin.x - aScreenRect.origin.x;
815 aNewContentRect.origin.x = aScreenRect.origin.x;
817 if( aScreenRect.origin.y < aNewContentRect.origin.y )
819 aNewContentRect.size.height += aNewContentRect.origin.y - aScreenRect.origin.y;
820 aNewContentRect.origin.y = aScreenRect.origin.y;
822 if( aScreenRect.origin.x + aScreenRect.size.width > aNewContentRect.origin.x + aNewContentRect.size.width )
823 aNewContentRect.size.width = aScreenRect.origin.x + aScreenRect.size.width - aNewContentRect.origin.x;
824 if( aScreenRect.origin.y + aScreenRect.size.height > aNewContentRect.origin.y + aNewContentRect.size.height )
825 aNewContentRect.size.height = aScreenRect.origin.y + aScreenRect.size.height - aNewContentRect.origin.y;
829 if( aNewContentRect.size.width == 0 && aNewContentRect.size.height == 0 )
831 if( pScreen == nil )
832 pScreen = [mpNSWindow screen];
833 if( pScreen == nil )
834 pScreen = [NSScreen mainScreen];
836 aNewContentRect = [pScreen frame];
839 if( bHideMenu )
840 [NSMenu setMenuBarVisible:NO];
842 maFullScreenRect = [mpNSWindow frame];
844 [mpNSWindow setFrame: [NSWindow frameRectForContentRect: aNewContentRect styleMask: mnStyleMask] display: mbShown ? YES : NO];
846 else
848 [mpNSWindow setFrame: maFullScreenRect display: mbShown ? YES : NO];
850 // show the dock and the menubar
851 [NSMenu setMenuBarVisible:YES];
854 UpdateFrameGeometry();
855 if (mbShown)
857 CallCallback(SalEvent::MoveResize, nullptr);
859 // trigger filling our backbuffer
860 SendPaintEvent();
864 void AquaSalFrame::StartPresentation( bool bStart )
866 if ( !mpNSWindow )
867 return;
869 OSX_SALDATA_RUNINMAIN( StartPresentation( bStart ) )
871 if( bStart )
873 GetSalData()->maPresentationFrames.push_back( this );
874 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
875 kIOPMAssertionLevelOn,
876 CFSTR("LibreOffice presentation running"),
877 &mnAssertionID);
878 [mpNSWindow setLevel: NSPopUpMenuWindowLevel];
879 if( mbShown )
880 [mpNSWindow makeMainWindow];
882 else
884 GetSalData()->maPresentationFrames.remove( this );
885 IOPMAssertionRelease(mnAssertionID);
886 [mpNSWindow setLevel: NSNormalWindowLevel];
890 void AquaSalFrame::SetAlwaysOnTop( bool )
894 void AquaSalFrame::ToTop(SalFrameToTop nFlags)
896 if ( !mpNSWindow )
897 return;
899 OSX_SALDATA_RUNINMAIN( ToTop( nFlags ) )
901 if( ! (nFlags & SalFrameToTop::RestoreWhenMin) )
903 if( ! [mpNSWindow isVisible] || [mpNSWindow isMiniaturized] )
904 return;
906 if( nFlags & SalFrameToTop::GrabFocus )
907 [mpNSWindow makeKeyAndOrderFront: NSApp];
908 else
909 [mpNSWindow orderFront: NSApp];
912 NSCursor* AquaSalFrame::getCurrentCursor()
914 OSX_SALDATA_RUNINMAIN_POINTER( getCurrentCursor(), NSCursor* )
916 NSCursor* pCursor = nil;
917 switch( mePointerStyle )
919 case PointerStyle::Text: pCursor = [NSCursor IBeamCursor]; break;
920 case PointerStyle::Cross: pCursor = [NSCursor crosshairCursor]; break;
921 case PointerStyle::Hand:
922 case PointerStyle::Move: pCursor = [NSCursor openHandCursor]; break;
923 case PointerStyle::NSize: pCursor = [NSCursor resizeUpCursor]; break;
924 case PointerStyle::SSize: pCursor = [NSCursor resizeDownCursor]; break;
925 case PointerStyle::ESize: pCursor = [NSCursor resizeRightCursor]; break;
926 case PointerStyle::WSize: pCursor = [NSCursor resizeLeftCursor]; break;
927 case PointerStyle::Arrow: pCursor = [NSCursor arrowCursor]; break;
928 case PointerStyle::VSplit:
929 case PointerStyle::VSizeBar:
930 case PointerStyle::WindowNSize:
931 case PointerStyle::WindowSSize:
932 pCursor = [NSCursor resizeUpDownCursor]; break;
933 case PointerStyle::HSplit:
934 case PointerStyle::HSizeBar:
935 case PointerStyle::WindowESize:
936 case PointerStyle::WindowWSize:
937 pCursor = [NSCursor resizeLeftRightCursor]; break;
938 case PointerStyle::RefHand: pCursor = [NSCursor pointingHandCursor]; break;
940 default:
941 pCursor = GetSalData()->getCursor( mePointerStyle );
942 if( pCursor == nil )
944 assert( false && "unmapped cursor" );
945 pCursor = [NSCursor arrowCursor];
947 break;
949 return pCursor;
952 void AquaSalFrame::SetPointer( PointerStyle ePointerStyle )
954 if ( !mpNSWindow )
955 return;
956 if( ePointerStyle == mePointerStyle )
957 return;
959 OSX_SALDATA_RUNINMAIN( SetPointer( ePointerStyle ) )
961 mePointerStyle = ePointerStyle;
963 [mpNSWindow invalidateCursorRectsForView: mpNSView];
966 void AquaSalFrame::SetPointerPos( tools::Long nX, tools::Long nY )
968 OSX_SALDATA_RUNINMAIN( SetPointerPos( nX, nY ) )
970 // FIXME: use Cocoa functions
971 // FIXME: multiscreen support
972 CGPoint aPoint = { static_cast<CGFloat>(nX + maGeometry.nX), static_cast<CGFloat>(nY + maGeometry.nY) };
973 CGDirectDisplayID mainDisplayID = CGMainDisplayID();
974 CGDisplayMoveCursorToPoint( mainDisplayID, aPoint );
977 void AquaSalFrame::Flush()
979 if( !(mbGraphics && mpGraphics && mpNSView && mbShown) )
980 return;
982 OSX_SALDATA_RUNINMAIN( Flush() )
984 [mpNSView setNeedsDisplay: YES];
986 // outside of the application's event loop (e.g. IntroWindow)
987 // nothing would trigger paint event handling
988 // => fall back to synchronous painting
989 if( ImplGetSVData()->maAppData.mnDispatchLevel <= 0 )
991 [mpNSView display];
995 void AquaSalFrame::Flush( const tools::Rectangle& rRect )
997 if( !(mbGraphics && mpGraphics && mpNSView && mbShown) )
998 return;
1000 OSX_SALDATA_RUNINMAIN( Flush( rRect ) )
1002 NSRect aNSRect = { { static_cast<CGFloat>(rRect.Left()), static_cast<CGFloat>(rRect.Top()) }, { static_cast<CGFloat>(rRect.GetWidth()), static_cast<CGFloat>(rRect.GetHeight()) } };
1003 VCLToCocoa( aNSRect, false );
1004 [mpNSView setNeedsDisplayInRect: aNSRect];
1006 // outside of the application's event loop (e.g. IntroWindow)
1007 // nothing would trigger paint event handling
1008 // => fall back to synchronous painting
1009 if( ImplGetSVData()->maAppData.mnDispatchLevel <= 0 )
1011 [mpNSView display];
1015 void AquaSalFrame::SetInputContext( SalInputContext* pContext )
1017 if (!pContext)
1019 mnICOptions = InputContextFlags::NONE;
1020 return;
1023 mnICOptions = pContext->mnOptions;
1025 if(!(pContext->mnOptions & InputContextFlags::Text))
1026 return;
1029 void AquaSalFrame::EndExtTextInput( EndExtTextInputFlags )
1033 OUString AquaSalFrame::GetKeyName( sal_uInt16 nKeyCode )
1035 static std::map< sal_uInt16, OUString > aKeyMap;
1036 if( aKeyMap.empty() )
1038 sal_uInt16 i;
1039 for( i = KEY_A; i <= KEY_Z; i++ )
1040 aKeyMap[ i ] = OUString( sal_Unicode( 'A' + (i - KEY_A) ) );
1041 for( i = KEY_0; i <= KEY_9; i++ )
1042 aKeyMap[ i ] = OUString( sal_Unicode( '0' + (i - KEY_0) ) );
1043 for( i = KEY_F1; i <= KEY_F26; i++ )
1045 aKeyMap[ i ] = "F" + OUString::number(i - KEY_F1 + 1);
1048 aKeyMap[ KEY_DOWN ] = OUString( u'\x21e3' );
1049 aKeyMap[ KEY_UP ] = OUString( u'\x21e1' );
1050 aKeyMap[ KEY_LEFT ] = OUString( u'\x21e0' );
1051 aKeyMap[ KEY_RIGHT ] = OUString( u'\x21e2' );
1052 aKeyMap[ KEY_HOME ] = OUString( u'\x2196' );
1053 aKeyMap[ KEY_END ] = OUString( u'\x2198' );
1054 aKeyMap[ KEY_PAGEUP ] = OUString( u'\x21de' );
1055 aKeyMap[ KEY_PAGEDOWN ] = OUString( u'\x21df' );
1056 aKeyMap[ KEY_RETURN ] = OUString( u'\x21a9' );
1057 aKeyMap[ KEY_ESCAPE ] = "esc";
1058 aKeyMap[ KEY_TAB ] = OUString( u'\x21e5' );
1059 aKeyMap[ KEY_BACKSPACE ]= OUString( u'\x232b' );
1060 aKeyMap[ KEY_SPACE ] = OUString( u'\x2423' );
1061 aKeyMap[ KEY_DELETE ] = OUString( u'\x2326' );
1062 aKeyMap[ KEY_ADD ] = "+";
1063 aKeyMap[ KEY_SUBTRACT ] = "-";
1064 aKeyMap[ KEY_DIVIDE ] = "/";
1065 aKeyMap[ KEY_MULTIPLY ] = "*";
1066 aKeyMap[ KEY_POINT ] = ".";
1067 aKeyMap[ KEY_COMMA ] = ",";
1068 aKeyMap[ KEY_LESS ] = "<";
1069 aKeyMap[ KEY_GREATER ] = ">";
1070 aKeyMap[ KEY_EQUAL ] = "=";
1071 aKeyMap[ KEY_OPEN ] = OUString( u'\x23cf' );
1072 aKeyMap[ KEY_TILDE ] = "~";
1073 aKeyMap[ KEY_BRACKETLEFT ] = "[";
1074 aKeyMap[ KEY_BRACKETRIGHT ] = "]";
1075 aKeyMap[ KEY_SEMICOLON ] = ";";
1076 aKeyMap[ KEY_QUOTERIGHT ] = "'";
1078 /* yet unmapped KEYCODES:
1079 aKeyMap[ KEY_INSERT ] = OUString( sal_Unicode( ) );
1080 aKeyMap[ KEY_CUT ] = OUString( sal_Unicode( ) );
1081 aKeyMap[ KEY_COPY ] = OUString( sal_Unicode( ) );
1082 aKeyMap[ KEY_PASTE ] = OUString( sal_Unicode( ) );
1083 aKeyMap[ KEY_UNDO ] = OUString( sal_Unicode( ) );
1084 aKeyMap[ KEY_REPEAT ] = OUString( sal_Unicode( ) );
1085 aKeyMap[ KEY_FIND ] = OUString( sal_Unicode( ) );
1086 aKeyMap[ KEY_PROPERTIES ] = OUString( sal_Unicode( ) );
1087 aKeyMap[ KEY_FRONT ] = OUString( sal_Unicode( ) );
1088 aKeyMap[ KEY_CONTEXTMENU ] = OUString( sal_Unicode( ) );
1089 aKeyMap[ KEY_MENU ] = OUString( sal_Unicode( ) );
1090 aKeyMap[ KEY_HELP ] = OUString( sal_Unicode( ) );
1091 aKeyMap[ KEY_HANGUL_HANJA ] = OUString( sal_Unicode( ) );
1092 aKeyMap[ KEY_DECIMAL ] = OUString( sal_Unicode( ) );
1093 aKeyMap[ KEY_QUOTELEFT ]= OUString( sal_Unicode( ) );
1094 aKeyMap[ KEY_CAPSLOCK ]= OUString( sal_Unicode( ) );
1095 aKeyMap[ KEY_NUMLOCK ]= OUString( sal_Unicode( ) );
1096 aKeyMap[ KEY_SCROLLLOCK ]= OUString( sal_Unicode( ) );
1101 OUStringBuffer aResult( 16 );
1103 sal_uInt16 nUnmodifiedCode = (nKeyCode & KEY_CODE_MASK);
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( u'\x21e7' ); // shift
1109 if( (nKeyCode & KEY_MOD1) != 0 )
1110 aResult.append( u'\x2318' ); // command
1111 if( (nKeyCode & KEY_MOD2) != 0 )
1112 aResult.append( u'\x2325' ); // alternate
1113 if( (nKeyCode & KEY_MOD3) != 0 )
1114 aResult.append( u'\x2303' ); // control
1116 aResult.append( it->second );
1119 return aResult.makeStringAndClear();
1122 static void getAppleScrollBarVariant(StyleSettings &rSettings)
1124 bool bIsScrollbarDoubleMax = true; // default is DoubleMax
1126 CFStringRef AppleScrollBarType = CFSTR("AppleScrollBarVariant");
1127 if( AppleScrollBarType )
1129 CFStringRef ScrollBarVariant = static_cast<CFStringRef>(CFPreferencesCopyAppValue( AppleScrollBarType, kCFPreferencesCurrentApplication ));
1130 if( ScrollBarVariant )
1132 if( CFGetTypeID( ScrollBarVariant ) == CFStringGetTypeID() )
1134 // TODO: check for the less important variants "DoubleMin" and "DoubleBoth" too
1135 CFStringRef DoubleMax = CFSTR("DoubleMax");
1136 if (DoubleMax)
1138 if ( !CFStringCompare(ScrollBarVariant, DoubleMax, kCFCompareCaseInsensitive) )
1139 bIsScrollbarDoubleMax = true;
1140 else
1141 bIsScrollbarDoubleMax = false;
1142 CFRelease(DoubleMax);
1145 CFRelease( ScrollBarVariant );
1147 CFRelease(AppleScrollBarType);
1150 GetSalData()->mbIsScrollbarDoubleMax = bIsScrollbarDoubleMax;
1152 CFStringRef jumpScroll = CFSTR("AppleScrollerPagingBehavior");
1153 if( jumpScroll )
1155 CFBooleanRef jumpStr = static_cast<CFBooleanRef>(CFPreferencesCopyAppValue( jumpScroll, kCFPreferencesCurrentApplication ));
1156 if( jumpStr )
1158 if( CFGetTypeID( jumpStr ) == CFBooleanGetTypeID() )
1159 rSettings.SetPrimaryButtonWarpsSlider(jumpStr == kCFBooleanTrue);
1160 CFRelease( jumpStr );
1162 CFRelease( jumpScroll );
1166 static Color getColor( NSColor* pSysColor, const Color& rDefault, NSWindow* pWin )
1168 Color aRet( rDefault );
1169 if( pSysColor )
1171 // transform to RGB
1172 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1173 // "'colorUsingColorSpaceName:device:' is deprecated: first deprecated in macOS 10.14 -
1174 // Use -colorUsingType: or -colorUsingColorSpace: instead"
1175 NSColor* pRBGColor = [pSysColor colorUsingColorSpaceName: NSDeviceRGBColorSpace device: [pWin deviceDescription]];
1176 SAL_WNODEPRECATED_DECLARATIONS_POP
1177 if( pRBGColor )
1179 CGFloat r = 0, g = 0, b = 0, a = 0;
1180 [pRBGColor getRed: &r green: &g blue: &b alpha: &a];
1181 aRet = Color( int(r*255.999), int(g*255.999), int(b*255.999) );
1183 do not release here; leads to duplicate free in yield
1184 it seems the converted color comes out autoreleased, although this
1185 is not documented
1186 [pRBGColor release];
1190 return aRet;
1193 static vcl::Font getFont( NSFont* pFont, sal_Int32 nDPIY, const vcl::Font& rDefault )
1195 vcl::Font aResult( rDefault );
1196 if( pFont )
1198 aResult.SetFamilyName( GetOUString( [pFont familyName] ) );
1199 aResult.SetFontHeight( static_cast<int>(([pFont pointSize] * 72.0 / static_cast<float>(nDPIY))+0.5) );
1200 aResult.SetItalic( ([pFont italicAngle] != 0.0) ? ITALIC_NORMAL : ITALIC_NONE );
1201 // FIMXE: bold ?
1204 return aResult;
1207 void AquaSalFrame::getResolution( sal_Int32& o_rDPIX, sal_Int32& o_rDPIY )
1209 OSX_SALDATA_RUNINMAIN( getResolution( o_rDPIX, o_rDPIY ) )
1211 if( ! mpGraphics )
1213 AcquireGraphics();
1214 ReleaseGraphics( mpGraphics );
1216 mpGraphics->GetResolution( o_rDPIX, o_rDPIY );
1219 // on OSX-Aqua the style settings are independent of the frame, so it does
1220 // not really belong here. Since the connection to the Appearance_Manager
1221 // is currently done in salnativewidgets.cxx this would be a good place.
1222 // On the other hand VCL's platform independent code currently only asks
1223 // SalFrames for system settings anyway, so moving the code somewhere else
1224 // doesn't make the anything cleaner for now
1225 void AquaSalFrame::UpdateSettings( AllSettings& rSettings )
1227 if ( !mpNSWindow )
1228 return;
1230 OSX_SALDATA_RUNINMAIN( UpdateSettings( rSettings ) )
1232 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1233 // "'lockFocus' is deprecated: first deprecated in macOS 10.14 - To draw, subclass NSView
1234 // and implement -drawRect:; AppKit's automatic deferred display mechanism will call
1235 // -drawRect: as necessary to display the view."
1236 if (![mpNSView lockFocusIfCanDraw])
1237 return;
1238 SAL_WNODEPRECATED_DECLARATIONS_POP
1240 StyleSettings aStyleSettings = rSettings.GetStyleSettings();
1242 // Background Color
1243 Color aBackgroundColor( 0xEC, 0xEC, 0xEC );
1244 aStyleSettings.BatchSetBackgrounds( aBackgroundColor, false );
1245 aStyleSettings.SetLightBorderColor( aBackgroundColor );
1247 Color aInactiveTabColor( aBackgroundColor );
1248 aInactiveTabColor.DecreaseLuminance( 32 );
1249 aStyleSettings.SetInactiveTabColor( aInactiveTabColor );
1251 Color aShadowColor( aStyleSettings.GetShadowColor() );
1252 aShadowColor.IncreaseLuminance( 32 );
1253 aStyleSettings.SetShadowColor( aShadowColor );
1255 // get the system font settings
1256 vcl::Font aAppFont = aStyleSettings.GetAppFont();
1257 sal_Int32 nDPIX = 72, nDPIY = 72;
1258 getResolution( nDPIX, nDPIY );
1259 aAppFont = getFont( [NSFont systemFontOfSize: 0], nDPIY, aAppFont );
1261 aStyleSettings.SetToolbarIconSize( ToolbarIconSize::Large );
1263 // TODO: better mapping of macOS<->LibreOffice font settings
1264 vcl::Font aLabelFont( getFont( [NSFont labelFontOfSize: 0], nDPIY, aAppFont ) );
1265 aStyleSettings.BatchSetFonts( aAppFont, aLabelFont );
1266 vcl::Font aMenuFont( getFont( [NSFont menuFontOfSize: 0], nDPIY, aAppFont ) );
1267 aStyleSettings.SetMenuFont( aMenuFont );
1269 vcl::Font aTitleFont( getFont( [NSFont titleBarFontOfSize: 0], nDPIY, aAppFont ) );
1270 aStyleSettings.SetTitleFont( aTitleFont );
1271 aStyleSettings.SetFloatTitleFont( aTitleFont );
1273 vcl::Font aTooltipFont(getFont([NSFont toolTipsFontOfSize: 0], nDPIY, aAppFont));
1274 aStyleSettings.SetHelpFont(aTooltipFont);
1276 Color aHighlightColor( getColor( [NSColor selectedTextBackgroundColor],
1277 aStyleSettings.GetHighlightColor(), mpNSWindow ) );
1278 aStyleSettings.SetHighlightColor( aHighlightColor );
1279 Color aHighlightTextColor( getColor( [NSColor selectedTextColor],
1280 aStyleSettings.GetHighlightTextColor(), mpNSWindow ) );
1281 aStyleSettings.SetHighlightTextColor( aHighlightTextColor );
1283 #pragma clang diagnostic push
1284 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1285 Color aMenuHighlightColor( getColor( [NSColor selectedMenuItemColor],
1286 aStyleSettings.GetMenuHighlightColor(), mpNSWindow ) );
1287 #pragma clang diagnostic pop
1288 aStyleSettings.SetMenuHighlightColor( aMenuHighlightColor );
1289 Color aMenuHighlightTextColor( getColor( [NSColor selectedMenuItemTextColor],
1290 aStyleSettings.GetMenuHighlightTextColor(), mpNSWindow ) );
1291 aStyleSettings.SetMenuHighlightTextColor( aMenuHighlightTextColor );
1293 aStyleSettings.SetMenuColor( aBackgroundColor );
1294 Color aMenuTextColor( getColor( [NSColor textColor],
1295 aStyleSettings.GetMenuTextColor(), mpNSWindow ) );
1296 aStyleSettings.SetMenuTextColor( aMenuTextColor );
1297 aStyleSettings.SetMenuBarTextColor( aMenuTextColor );
1298 aStyleSettings.SetMenuBarRolloverTextColor( aMenuTextColor );
1299 aStyleSettings.SetMenuBarHighlightTextColor(aStyleSettings.GetMenuHighlightTextColor());
1301 // Set text colors for buttons and their different status according to OS settings, typically white for selected buttons,
1302 // black otherwise
1304 Color aControlTextColor(getColor([NSColor controlTextColor], COL_BLACK, mpNSWindow));
1305 Color aSelectedControlTextColor(getColor([NSColor selectedControlTextColor], COL_BLACK, mpNSWindow));
1306 Color aAlternateSelectedControlTextColor(getColor([NSColor alternateSelectedControlTextColor], COL_WHITE, mpNSWindow));
1307 aStyleSettings.SetDefaultButtonTextColor(aAlternateSelectedControlTextColor);
1308 aStyleSettings.SetButtonTextColor(aControlTextColor);
1309 aStyleSettings.SetDefaultActionButtonTextColor(aAlternateSelectedControlTextColor);
1310 aStyleSettings.SetActionButtonTextColor(aControlTextColor);
1311 aStyleSettings.SetFlatButtonTextColor(aControlTextColor);
1312 aStyleSettings.SetDefaultButtonRolloverTextColor(aAlternateSelectedControlTextColor);
1313 aStyleSettings.SetButtonRolloverTextColor(aControlTextColor);
1314 aStyleSettings.SetDefaultActionButtonRolloverTextColor(aAlternateSelectedControlTextColor);
1315 aStyleSettings.SetActionButtonRolloverTextColor(aControlTextColor);
1316 aStyleSettings.SetFlatButtonRolloverTextColor(aControlTextColor);
1317 aStyleSettings.SetDefaultButtonPressedRolloverTextColor(aAlternateSelectedControlTextColor);
1318 aStyleSettings.SetButtonPressedRolloverTextColor(aAlternateSelectedControlTextColor);
1319 aStyleSettings.SetDefaultActionButtonPressedRolloverTextColor(aAlternateSelectedControlTextColor);
1320 aStyleSettings.SetActionButtonPressedRolloverTextColor(aAlternateSelectedControlTextColor);
1321 aStyleSettings.SetFlatButtonPressedRolloverTextColor(aControlTextColor);
1323 // Set text colors for tabs according to OS settings
1325 aStyleSettings.SetTabTextColor(aControlTextColor);
1327 // FIXME: Starting with macOS Big Sur, coloring has changed. Currently there is no documentation which system color should be
1328 // used for selected tab text. As a workaround the current OS version has to be considered. This code has to be reviewed once
1329 // issue is covered by documentation.
1331 NSOperatingSystemVersion aOSVersion = { .majorVersion = 10, .minorVersion = 16, .patchVersion = 0 };
1332 if ([NSProcessInfo.processInfo isOperatingSystemAtLeastVersion: aOSVersion])
1333 aStyleSettings.SetTabHighlightTextColor(aSelectedControlTextColor);
1334 else
1335 aStyleSettings.SetTabHighlightTextColor(aAlternateSelectedControlTextColor);
1337 aStyleSettings.SetCursorBlinkTime( mnBlinkCursorDelay );
1339 // no mnemonics on macOS
1340 aStyleSettings.SetOptions( aStyleSettings.GetOptions() | StyleSettingsOptions::NoMnemonics );
1342 getAppleScrollBarVariant(aStyleSettings);
1344 // set scrollbar size
1345 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1346 // 'NSRegularControlSize' is deprecated: first deprecated in macOS 10.12
1347 aStyleSettings.SetScrollBarSize( static_cast<tools::Long>([NSScroller scrollerWidthForControlSize:NSRegularControlSize scrollerStyle:NSScrollerStyleLegacy]) );
1348 SAL_WNODEPRECATED_DECLARATIONS_POP
1349 // images in menus false for MacOSX
1350 aStyleSettings.SetPreferredUseImagesInMenus( false );
1351 aStyleSettings.SetHideDisabledMenuItems( true );
1352 aStyleSettings.SetPreferredContextMenuShortcuts( false );
1354 rSettings.SetStyleSettings( aStyleSettings );
1356 // don't draw frame around each and every toolbar
1357 ImplGetSVData()->maNWFData.mbDockingAreaAvoidTBFrames = true;
1359 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1360 // "'unlockFocus' is deprecated: first deprecated in macOS 10.14 - To draw, subclass NSView
1361 // and implement -drawRect:; AppKit's automatic deferred display mechanism will call
1362 // -drawRect: as necessary to display the view."
1363 [mpNSView unlockFocus];
1364 SAL_WNODEPRECATED_DECLARATIONS_POP
1367 const SystemEnvData* AquaSalFrame::GetSystemData() const
1369 return &maSysData;
1372 void AquaSalFrame::Beep()
1374 OSX_SALDATA_RUNINMAIN( Beep() )
1375 NSBeep();
1378 void AquaSalFrame::SetPosSize(
1379 tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, sal_uInt16 nFlags)
1381 if (!mpNSWindow && !Application::IsBitmapRendering())
1382 return;
1384 OSX_SALDATA_RUNINMAIN( SetPosSize( nX, nY, nWidth, nHeight, nFlags ) )
1386 SalEvent nEvent = PreparePosSize(nX, nY, nWidth, nHeight, nFlags);
1387 if (Application::IsBitmapRendering())
1388 return;
1390 if( [mpNSWindow isMiniaturized] )
1391 [mpNSWindow deminiaturize: NSApp]; // expand the window
1393 NSRect aFrameRect = [mpNSWindow frame];
1394 NSRect aContentRect = [NSWindow contentRectForFrameRect: aFrameRect styleMask: mnStyleMask];
1396 // position is always relative to parent frame
1397 NSRect aParentContentRect;
1399 if( mpParent )
1401 if( AllSettings::GetLayoutRTL() )
1403 if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 )
1404 nX = mpParent->maGeometry.nWidth - nWidth-1 - nX;
1405 else
1406 nX = mpParent->maGeometry.nWidth - static_cast<tools::Long>( aContentRect.size.width-1) - nX;
1408 NSRect aParentFrameRect = [mpParent->mpNSWindow frame];
1409 aParentContentRect = [NSWindow contentRectForFrameRect: aParentFrameRect styleMask: mpParent->mnStyleMask];
1411 else
1412 aParentContentRect = maScreenRect; // use screen if no parent
1414 CocoaToVCL( aContentRect );
1415 CocoaToVCL( aParentContentRect );
1417 bool bPaint = false;
1418 if( (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) != 0 )
1420 if( nWidth != aContentRect.size.width || nHeight != aContentRect.size.height )
1421 bPaint = true;
1424 // use old window pos if no new pos requested
1425 if( (nFlags & SAL_FRAME_POSSIZE_X) != 0 )
1426 aContentRect.origin.x = nX + aParentContentRect.origin.x;
1427 if( (nFlags & SAL_FRAME_POSSIZE_Y) != 0)
1428 aContentRect.origin.y = nY + aParentContentRect.origin.y;
1430 // use old size if no new size requested
1431 if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 )
1432 aContentRect.size.width = nWidth;
1433 if( (nFlags & SAL_FRAME_POSSIZE_HEIGHT) != 0)
1434 aContentRect.size.height = nHeight;
1436 VCLToCocoa( aContentRect );
1438 // do not display yet, we need to update our backbuffer
1440 [mpNSWindow setFrame: [NSWindow frameRectForContentRect: aContentRect styleMask: mnStyleMask] display: NO];
1443 UpdateFrameGeometry();
1445 if (nEvent != SalEvent::NONE)
1446 CallCallback(nEvent, nullptr);
1448 if( mbShown && bPaint )
1450 // trigger filling our backbuffer
1451 SendPaintEvent();
1453 // now inform the system that the views need to be drawn
1454 [mpNSWindow display];
1458 void AquaSalFrame::GetWorkArea( tools::Rectangle& rRect )
1460 if (!mpNSWindow)
1462 if (Application::IsBitmapRendering())
1463 rRect = tools::Rectangle(Point(0, 0), Size(1024, 768));
1464 return;
1467 OSX_SALDATA_RUNINMAIN( GetWorkArea( rRect ) )
1469 NSScreen* pScreen = [mpNSWindow screen];
1470 if( pScreen == nil )
1471 pScreen = [NSScreen mainScreen];
1472 NSRect aRect = [pScreen visibleFrame];
1473 CocoaToVCL( aRect );
1474 rRect.SetLeft( static_cast<tools::Long>(aRect.origin.x) );
1475 rRect.SetTop( static_cast<tools::Long>(aRect.origin.y) );
1476 rRect.SetRight( static_cast<tools::Long>(aRect.origin.x + aRect.size.width - 1) );
1477 rRect.SetBottom( static_cast<tools::Long>(aRect.origin.y + aRect.size.height - 1) );
1480 SalFrame::SalPointerState AquaSalFrame::GetPointerState()
1482 OSX_SALDATA_RUNINMAIN_UNION( GetPointerState(), state )
1484 SalPointerState state;
1485 state.mnState = 0;
1487 // get position
1488 NSPoint aPt = [mpNSWindow mouseLocationOutsideOfEventStream];
1489 CocoaToVCL( aPt, false );
1490 state.maPos = Point(static_cast<tools::Long>(aPt.x), static_cast<tools::Long>(aPt.y));
1492 NSEvent* pCur = [NSApp currentEvent];
1493 bool bMouseEvent = false;
1494 if( pCur )
1496 bMouseEvent = true;
1497 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1498 // 'NSLeftMouseDown' is deprecated: first deprecated in macOS 10.12
1499 // 'NSLeftMouseDragged' is deprecated: first deprecated in macOS 10.12
1500 // 'NSLeftMouseUp' is deprecated: first deprecated in macOS 10.12
1501 // 'NSMouseMoved' is deprecated: first deprecated in macOS 10.12
1502 // 'NSOtherMouseDown' is deprecated: first deprecated in macOS 10.12
1503 // 'NSOtherMouseDragged' is deprecated: first deprecated in macOS 10.12
1504 // 'NSOtherMouseUp' is deprecated: first deprecated in macOS 10.12
1505 // 'NSRightMouseDown' is deprecated: first deprecated in macOS 10.12
1506 // 'NSRightMouseDragged' is deprecated: first deprecated in macOS 10.12
1507 // 'NSRightMouseUp' is deprecated: first deprecated in macOS 10.12
1508 switch( [pCur type] )
1510 case NSLeftMouseDown: state.mnState |= MOUSE_LEFT; break;
1511 case NSLeftMouseUp: break;
1512 case NSRightMouseDown: state.mnState |= MOUSE_RIGHT; break;
1513 case NSRightMouseUp: break;
1514 case NSOtherMouseDown: state.mnState |= ([pCur buttonNumber] == 2) ? MOUSE_MIDDLE : 0; break;
1515 case NSOtherMouseUp: break;
1516 case NSMouseMoved: break;
1517 case NSLeftMouseDragged: state.mnState |= MOUSE_LEFT; break;
1518 case NSRightMouseDragged: state.mnState |= MOUSE_RIGHT; break;
1519 case NSOtherMouseDragged: state.mnState |= ([pCur buttonNumber] == 2) ? MOUSE_MIDDLE : 0; break;
1520 break;
1521 default:
1522 bMouseEvent = false;
1523 break;
1525 SAL_WNODEPRECATED_DECLARATIONS_POP
1527 if( bMouseEvent )
1529 unsigned int nMask = static_cast<unsigned int>([pCur modifierFlags]);
1530 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1531 // 'NSAlternateKeyMask' is deprecated: first deprecated in macOS 10.12
1532 // 'NSCommandKeyMask' is deprecated: first deprecated in macOS 10.12
1533 // 'NSControlKeyMask' is deprecated: first deprecated in macOS 10.12
1534 // 'NSShiftKeyMask' is deprecated: first deprecated in macOS 10.12
1535 if( (nMask & NSShiftKeyMask) != 0 )
1536 state.mnState |= KEY_SHIFT;
1537 if( (nMask & NSControlKeyMask) != 0 )
1538 state.mnState |= KEY_MOD3;
1539 if( (nMask & NSAlternateKeyMask) != 0 )
1540 state.mnState |= KEY_MOD2;
1541 if( (nMask & NSCommandKeyMask) != 0 )
1542 state.mnState |= KEY_MOD1;
1543 SAL_WNODEPRECATED_DECLARATIONS_POP
1546 else
1548 // FIXME: replace Carbon by Cocoa
1549 // Cocoa does not have an equivalent for GetCurrentEventButtonState
1550 // and GetCurrentEventKeyModifiers.
1551 // we could try to get away with tracking all events for modifierKeys
1552 // and all mouse events for button state in VCL_NSApplication::sendEvent,
1553 // but it is unclear whether this will get us the same result.
1554 // leave in GetCurrentEventButtonState and GetCurrentEventKeyModifiers for now
1556 // fill in button state
1557 UInt32 nState = GetCurrentEventButtonState();
1558 state.mnState = 0;
1559 if( nState & 1 )
1560 state.mnState |= MOUSE_LEFT; // primary button
1561 if( nState & 2 )
1562 state.mnState |= MOUSE_RIGHT; // secondary button
1563 if( nState & 4 )
1564 state.mnState |= MOUSE_MIDDLE; // tertiary button
1566 // fill in modifier state
1567 nState = GetCurrentEventKeyModifiers();
1568 if( nState & shiftKey )
1569 state.mnState |= KEY_SHIFT;
1570 if( nState & controlKey )
1571 state.mnState |= KEY_MOD3;
1572 if( nState & optionKey )
1573 state.mnState |= KEY_MOD2;
1574 if( nState & cmdKey )
1575 state.mnState |= KEY_MOD1;
1578 return state;
1581 KeyIndicatorState AquaSalFrame::GetIndicatorState()
1583 return KeyIndicatorState::NONE;
1586 void AquaSalFrame::SimulateKeyPress( sal_uInt16 /*nKeyCode*/ )
1590 void AquaSalFrame::SetPluginParent( SystemParentData* )
1592 // plugin parent may be killed unexpectedly by
1593 // plugging process;
1595 //TODO: implement
1598 bool AquaSalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , vcl::KeyCode& )
1600 // not supported yet
1601 return false;
1604 LanguageType AquaSalFrame::GetInputLanguage()
1606 //TODO: implement
1607 return LANGUAGE_DONTKNOW;
1610 void AquaSalFrame::DrawMenuBar()
1614 void AquaSalFrame::SetMenu( SalMenu* pSalMenu )
1616 OSX_SALDATA_RUNINMAIN( SetMenu( pSalMenu ) )
1618 AquaSalMenu* pMenu = static_cast<AquaSalMenu*>(pSalMenu);
1619 SAL_WARN_IF( pMenu && !pMenu->mbMenuBar, "vcl", "setting non menubar on frame" );
1620 mpMenu = pMenu;
1621 if( mpMenu )
1622 mpMenu->setMainMenu();
1625 void AquaSalFrame::SetExtendedFrameStyle( SalExtStyle nStyle )
1627 if ( !mpNSWindow )
1629 mnExtStyle = nStyle;
1630 return;
1633 OSX_SALDATA_RUNINMAIN( SetExtendedFrameStyle( nStyle ) )
1635 if( (mnExtStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) != (nStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) )
1636 [mpNSWindow setDocumentEdited: (nStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) ? YES : NO];
1638 mnExtStyle = nStyle;
1641 SalFrame* AquaSalFrame::GetParent() const
1643 return mpParent;
1646 void AquaSalFrame::SetParent( SalFrame* pNewParent )
1648 bool bShown = mbShown;
1649 // remove from child list
1650 if (bShown)
1651 Show(false);
1652 mpParent = static_cast<AquaSalFrame*>(pNewParent);
1653 // insert to correct parent and paint
1654 Show( bShown );
1657 void AquaSalFrame::UpdateFrameGeometry()
1659 bool bFirstTime = (mnTrackingRectTag == 0);
1660 mbGeometryDidChange = false;
1662 if ( !mpNSWindow )
1663 return;
1665 OSX_SALDATA_RUNINMAIN( UpdateFrameGeometry() )
1667 // keep in mind that view and window coordinates are lower left
1668 // whereas vcl's are upper left
1670 // update screen rect
1671 NSScreen * pScreen = [mpNSWindow screen];
1672 if( pScreen )
1674 NSRect aNewScreenRect = [pScreen frame];
1675 if (bFirstTime || !NSEqualRects(maScreenRect, aNewScreenRect))
1677 mbGeometryDidChange = true;
1678 maScreenRect = aNewScreenRect;
1680 NSArray* pScreens = [NSScreen screens];
1681 if( pScreens )
1683 unsigned int nNewDisplayScreenNumber = [pScreens indexOfObject: pScreen];
1684 if (bFirstTime || maGeometry.nDisplayScreenNumber != nNewDisplayScreenNumber)
1686 mbGeometryDidChange = true;
1687 maGeometry.nDisplayScreenNumber = nNewDisplayScreenNumber;
1692 NSRect aFrameRect = [mpNSWindow frame];
1693 NSRect aContentRect = [NSWindow contentRectForFrameRect: aFrameRect styleMask: mnStyleMask];
1695 NSRect aTrackRect = { NSZeroPoint, aContentRect.size };
1697 if (bFirstTime || !NSEqualRects(maTrackingRect, aTrackRect))
1699 mbGeometryDidChange = true;
1700 maTrackingRect = aTrackRect;
1702 // release old track rect
1703 [mpNSView removeTrackingRect: mnTrackingRectTag];
1704 // install the new track rect
1705 mnTrackingRectTag = [mpNSView addTrackingRect: aTrackRect owner: mpNSView userData: nil assumeInside: NO];
1708 // convert to vcl convention
1709 CocoaToVCL( aFrameRect );
1710 CocoaToVCL( aContentRect );
1712 if (bFirstTime || !NSEqualRects(maContentRect, aContentRect) || !NSEqualRects(maFrameRect, aFrameRect))
1714 mbGeometryDidChange = true;
1716 maContentRect = aContentRect;
1717 maFrameRect = aFrameRect;
1719 maGeometry.nX = static_cast<int>(aContentRect.origin.x);
1720 maGeometry.nY = static_cast<int>(aContentRect.origin.y);
1722 maGeometry.nLeftDecoration = static_cast<unsigned int>(aContentRect.origin.x - aFrameRect.origin.x);
1723 maGeometry.nRightDecoration = static_cast<unsigned int>((aFrameRect.origin.x + aFrameRect.size.width) -
1724 (aContentRect.origin.x + aContentRect.size.width));
1726 maGeometry.nTopDecoration = static_cast<unsigned int>(aContentRect.origin.y - aFrameRect.origin.y);
1727 maGeometry.nBottomDecoration = static_cast<unsigned int>((aFrameRect.origin.y + aFrameRect.size.height) -
1728 (aContentRect.origin.y + aContentRect.size.height));
1730 maGeometry.nWidth = static_cast<unsigned int>(aContentRect.size.width);
1731 maGeometry.nHeight = static_cast<unsigned int>(aContentRect.size.height);
1735 void AquaSalFrame::CaptureMouse( bool bCapture )
1737 /* Remark:
1738 we'll try to use a pidgin version of capture mouse
1739 on MacOSX (neither carbon nor cocoa) there is a
1740 CaptureMouse equivalent (in Carbon there is TrackMouseLocation
1741 but this is useless to use since it is blocking)
1743 However on cocoa the active frame seems to get mouse events
1744 also outside the window, so we'll try to forward mouse events
1745 to the capture frame in the hope that one of our frames
1746 gets a mouse event.
1748 This will break as soon as the user activates another app, but
1749 a mouse click will normally lead to a release of the mouse anyway.
1751 Let's see how far we get this way. Alternatively we could use one
1752 large overlay window like we did for the carbon implementation,
1753 however that is resource intensive.
1756 if( bCapture )
1757 s_pCaptureFrame = this;
1758 else if( ! bCapture && s_pCaptureFrame == this )
1759 s_pCaptureFrame = nullptr;
1762 void AquaSalFrame::ResetClipRegion()
1764 doResetClipRegion();
1767 void AquaSalFrame::doResetClipRegion()
1769 if ( !mpNSWindow )
1770 return;
1772 OSX_SALDATA_RUNINMAIN( ResetClipRegion() )
1774 // release old path and indicate no clipping
1775 CGPathRelease( mrClippingPath );
1776 mrClippingPath = nullptr;
1778 if( mpNSView && mbShown )
1779 [mpNSView setNeedsDisplay: YES];
1780 [mpNSWindow setOpaque: YES];
1781 [mpNSWindow invalidateShadow];
1784 void AquaSalFrame::BeginSetClipRegion( sal_uInt32 nRects )
1786 if ( !mpNSWindow )
1787 return;
1789 OSX_SALDATA_RUNINMAIN( BeginSetClipRegion( nRects ) )
1791 // release old path
1792 if( mrClippingPath )
1794 CGPathRelease( mrClippingPath );
1795 mrClippingPath = nullptr;
1798 if( maClippingRects.size() > SAL_CLIPRECT_COUNT && nRects < maClippingRects.size() )
1800 std::vector<CGRect>().swap(maClippingRects);
1802 maClippingRects.clear();
1803 maClippingRects.reserve( nRects );
1806 void AquaSalFrame::UnionClipRegion(
1807 tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight )
1809 // #i113170# may not be the main thread if called from UNO API
1810 SalData::ensureThreadAutoreleasePool();
1812 if( nWidth && nHeight )
1814 NSRect aRect = { { static_cast<CGFloat>(nX), static_cast<CGFloat>(nY) }, { static_cast<CGFloat>(nWidth), static_cast<CGFloat>(nHeight) } };
1815 VCLToCocoa( aRect, false );
1816 maClippingRects.push_back( CGRectMake(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height) );
1820 void AquaSalFrame::EndSetClipRegion()
1822 if ( !mpNSWindow )
1823 return;
1825 OSX_SALDATA_RUNINMAIN( EndSetClipRegion() )
1827 if( ! maClippingRects.empty() )
1829 mrClippingPath = CGPathCreateMutable();
1830 CGPathAddRects( mrClippingPath, nullptr, maClippingRects.data(), maClippingRects.size() );
1832 if( mpNSView && mbShown )
1833 [mpNSView setNeedsDisplay: YES];
1834 [mpNSWindow setOpaque: (mrClippingPath != nullptr) ? NO : YES];
1835 [mpNSWindow setBackgroundColor: [NSColor clearColor]];
1836 // shadow is invalidated when view gets drawn again
1839 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */