1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
22 #include <comphelper/fileurl.hxx>
23 #include <rtl/ustrbuf.hxx>
24 #include <sal/log.hxx>
25 #include <osl/diagnose.h>
29 #include <vcl/event.hxx>
30 #include <vcl/inputctx.hxx>
31 #include <vcl/svapp.hxx>
32 #include <vcl/window.hxx>
33 #include <vcl/syswin.hxx>
34 #include <vcl/settings.hxx>
36 #include <osx/saldata.hxx>
37 #include <quartz/salgdi.h>
38 #include <osx/salframe.h>
39 #include <osx/salmenu.h>
40 #include <osx/salinst.h>
41 #include <osx/salframeview.h>
42 #include <osx/a11yfactory.h>
43 #include <osx/runinmain.hxx>
44 #include <quartz/utils.h>
46 #include <salwtype.hxx>
49 #include <objc/objc-runtime.h>
51 // FIXME: move theming code to salnativewidgets.cxx
52 #include <Carbon/Carbon.h>
57 AquaSalFrame
* AquaSalFrame::s_pCaptureFrame
= nullptr;
59 AquaSalFrame::AquaSalFrame( SalFrame
* pParent
, SalFrameStyleFlags salFrameStyle
) :
70 mbFullScreen( false ),
75 mbPresentation( false ),
76 mnStyle( salFrameStyle
),
79 mnLastModifierFlags( 0 ),
82 mePointerStyle( PointerStyle::Arrow
),
83 mnTrackingRectTag( 0 ),
84 mrClippingPath( nullptr ),
85 mnICOptions( InputContextFlags::NONE
)
87 mpParent
= dynamic_cast<AquaSalFrame
*>(pParent
);
91 SalData
* pSalData
= GetSalData();
92 pSalData
->mpInstance
->insertFrame( this );
95 AquaSalFrame::~AquaSalFrame()
98 doShowFullScreen(false, maGeometry
.nDisplayScreenNumber
);
100 assert( GetSalData()->mpInstance
->IsMainThread() );
102 // if the frame is destroyed and has the current menubar
103 // set the default menubar
104 if( mpMenu
&& mpMenu
->mbMenuBar
&& AquaSalMenu::pCurrentMenuBar
== mpMenu
)
105 AquaSalMenu::setDefaultMenu();
107 // cleanup clipping stuff
110 [SalFrameView unsetMouseFrame
: this];
112 SalData
* pSalData
= GetSalData();
113 pSalData
->mpInstance
->eraseFrame( this );
114 pSalData
->maPresentationFrames
.remove( this );
116 SAL_WARN_IF( this == s_pCaptureFrame
, "vcl", "capture frame destroyed" );
117 if( this == s_pCaptureFrame
)
118 s_pCaptureFrame
= nullptr;
122 if( mpDockMenuEntry
)
124 NSMenu
* pDock
= AquaSalInstance::GetDynamicDockMenu();
125 // life cycle comment: the menu has ownership of the item, so no release
126 [pDock removeItem
: mpDockMenuEntry
];
127 if ([pDock numberOfItems
] != 0
128 && [[pDock itemAtIndex
: 0] isSeparatorItem
])
130 [pDock removeItemAtIndex
: 0];
134 [AquaA11yFactory revokeView
: mpNSView
];
138 [mpNSWindow release
];
141 void AquaSalFrame::initWindowAndView()
143 OSX_SALDATA_RUNINMAIN( initWindowAndView() )
145 // initialize mirroring parameters
146 // FIXME: screens changing
147 NSScreen
* pNSScreen
= [mpNSWindow screen
];
148 if( pNSScreen
== nil
)
149 pNSScreen
= [NSScreen mainScreen
];
150 maScreenRect
= [pNSScreen frame
];
152 // calculate some default geometry
153 NSRect aVisibleRect
= [pNSScreen visibleFrame
];
154 CocoaToVCL( aVisibleRect
);
156 maGeometry
.nX
= static_cast<int>(aVisibleRect
.origin
.x
+ aVisibleRect
.size
.width
/ 10);
157 maGeometry
.nY
= static_cast<int>(aVisibleRect
.origin
.y
+ aVisibleRect
.size
.height
/ 10);
158 maGeometry
.nWidth
= static_cast<unsigned int>(aVisibleRect
.size
.width
* 0.8);
159 maGeometry
.nHeight
= static_cast<unsigned int>(aVisibleRect
.size
.height
* 0.8);
161 // calculate style mask
162 SAL_WNODEPRECATED_DECLARATIONS_PUSH
163 // 'NSBorderlessWindowMask' is deprecated: first deprecated in macOS 10.12
164 // 'NSClosableWindowMask' is deprecated: first deprecated in macOS 10.12
165 // 'NSMiniaturizableWindowMask' is deprecated: first deprecated in macOS 10.12
166 // 'NSResizableWindowMask' is deprecated: first deprecated in macOS 10.12
167 // 'NSTitledWindowMask' is deprecated: first deprecated in macOS 10.12
168 if( (mnStyle
& SalFrameStyleFlags::FLOAT
) ||
169 (mnStyle
& SalFrameStyleFlags::OWNERDRAWDECORATION
) )
170 mnStyleMask
= NSBorderlessWindowMask
;
171 else if( mnStyle
& SalFrameStyleFlags::DEFAULT
)
173 mnStyleMask
= NSTitledWindowMask
|
174 NSMiniaturizableWindowMask
|
175 NSResizableWindowMask
|
176 NSClosableWindowMask
;
177 // make default window "maximized"
178 maGeometry
.nX
= static_cast<int>(aVisibleRect
.origin
.x
);
179 maGeometry
.nY
= static_cast<int>(aVisibleRect
.origin
.y
);
180 maGeometry
.nWidth
= static_cast<int>(aVisibleRect
.size
.width
);
181 maGeometry
.nHeight
= static_cast<int>(aVisibleRect
.size
.height
);
182 mbPositioned
= mbSized
= true;
186 if( mnStyle
& SalFrameStyleFlags::MOVEABLE
)
188 mnStyleMask
|= NSTitledWindowMask
;
189 if( mpParent
== nullptr )
190 mnStyleMask
|= NSMiniaturizableWindowMask
;
192 if( mnStyle
& SalFrameStyleFlags::SIZEABLE
)
193 mnStyleMask
|= NSResizableWindowMask
;
194 if( mnStyle
& SalFrameStyleFlags::CLOSEABLE
)
195 mnStyleMask
|= NSClosableWindowMask
;
196 // documentation says anything other than NSBorderlessWindowMask (=0)
197 // should also include NSTitledWindowMask;
198 if( mnStyleMask
!= 0 )
199 mnStyleMask
|= NSTitledWindowMask
;
201 SAL_WNODEPRECATED_DECLARATIONS_POP
203 if (Application::IsBitmapRendering())
206 // #i91990# support GUI-less (daemon) execution
209 mpNSWindow
= [[SalFrameWindow alloc
] initWithSalFrame
: this];
210 mpNSView
= [[SalFrameView alloc
] initWithSalFrame
: this];
217 if( mnStyle
& SalFrameStyleFlags::TOOLTIP
)
218 [mpNSWindow setIgnoresMouseEvents
: YES
];
220 [mpNSWindow setAcceptsMouseMovedEvents
: YES
];
221 [mpNSWindow setHasShadow
: YES
];
223 [mpNSWindow setDelegate
: static_cast<id
<NSWindowDelegate
> >(mpNSWindow
)];
225 [mpNSWindow setRestorable
:NO
];
226 const NSRect aRect
= { NSZeroPoint
, NSMakeSize( maGeometry
.nWidth
, maGeometry
.nHeight
)};
227 mnTrackingRectTag
= [mpNSView addTrackingRect
: aRect owner
: mpNSView userData
: nil assumeInside
: NO
];
229 maSysData
.mpNSView
= mpNSView
;
231 UpdateFrameGeometry();
233 [mpNSWindow setContentView
: mpNSView
];
236 void AquaSalFrame::CocoaToVCL( NSRect
& io_rRect
, bool bRelativeToScreen
)
238 if( bRelativeToScreen
)
239 io_rRect
.origin
.y
= maScreenRect
.size
.height
- (io_rRect
.origin
.y
+io_rRect
.size
.height
);
241 io_rRect
.origin
.y
= maGeometry
.nHeight
- (io_rRect
.origin
.y
+io_rRect
.size
.height
);
244 void AquaSalFrame::VCLToCocoa( NSRect
& io_rRect
, bool bRelativeToScreen
)
246 if( bRelativeToScreen
)
247 io_rRect
.origin
.y
= maScreenRect
.size
.height
- (io_rRect
.origin
.y
+io_rRect
.size
.height
);
249 io_rRect
.origin
.y
= maGeometry
.nHeight
- (io_rRect
.origin
.y
+io_rRect
.size
.height
);
252 void AquaSalFrame::CocoaToVCL( NSPoint
& io_rPoint
, bool bRelativeToScreen
)
254 if( bRelativeToScreen
)
255 io_rPoint
.y
= maScreenRect
.size
.height
- io_rPoint
.y
;
257 io_rPoint
.y
= maGeometry
.nHeight
- io_rPoint
.y
;
260 void AquaSalFrame::VCLToCocoa( NSPoint
& io_rPoint
, bool bRelativeToScreen
)
262 if( bRelativeToScreen
)
263 io_rPoint
.y
= maScreenRect
.size
.height
- io_rPoint
.y
;
265 io_rPoint
.y
= maGeometry
.nHeight
- io_rPoint
.y
;
268 void AquaSalFrame::screenParametersChanged()
270 OSX_SALDATA_RUNINMAIN( screenParametersChanged() )
272 UpdateFrameGeometry();
275 mpGraphics
->updateResolution();
277 if (!mbGeometryDidChange
)
280 CallCallback( SalEvent::DisplayChanged
, nullptr );
283 SalGraphics
* AquaSalFrame::AcquireGraphics()
290 mpGraphics
= new AquaSalGraphics
;
291 mpGraphics
->SetWindowGraphics( this );
298 void AquaSalFrame::ReleaseGraphics( SalGraphics
*pGraphics
)
300 SAL_WARN_IF( pGraphics
!= mpGraphics
, "vcl", "graphics released on wrong frame" );
304 bool AquaSalFrame::PostEvent(std::unique_ptr
<ImplSVEvent
> pData
)
306 GetSalData()->mpInstance
->PostEvent( this, pData
.release(), SalEvent::UserEvent
);
310 void AquaSalFrame::SetTitle(const OUString
& rTitle
)
315 OSX_SALDATA_RUNINMAIN( SetTitle(rTitle
) )
317 // #i113170# may not be the main thread if called from UNO API
318 SalData::ensureThreadAutoreleasePool();
320 NSString
* pTitle
= CreateNSString( rTitle
);
321 [mpNSWindow setTitle
: pTitle
];
323 // create an entry in the dock menu
324 const SalFrameStyleFlags nAppWindowStyle
= SalFrameStyleFlags::CLOSEABLE
| SalFrameStyleFlags::MOVEABLE
;
325 if( mpParent
== nullptr &&
326 (mnStyle
& nAppWindowStyle
) == nAppWindowStyle
)
328 if( mpDockMenuEntry
== nullptr )
330 NSMenu
* pDock
= AquaSalInstance::GetDynamicDockMenu();
332 if ([pDock numberOfItems
] != 0) {
333 NSMenuItem
* pTopItem
= [pDock itemAtIndex
: 0];
334 if ( [pTopItem hasSubmenu
] )
335 [pDock insertItem
: [NSMenuItem separatorItem
] atIndex
: 0];
338 mpDockMenuEntry
= [pDock insertItemWithTitle
: pTitle
339 action
: @
selector(dockMenuItemTriggered
:)
342 [mpDockMenuEntry setTarget
: mpNSWindow
];
344 // TODO: image (either the generic window image or an icon
345 // check mark (for "main" window ?)
348 [mpDockMenuEntry setTitle
: pTitle
];
355 void AquaSalFrame::SetIcon( sal_uInt16
)
359 void AquaSalFrame::SetRepresentedURL( const OUString
& i_rDocURL
)
361 OSX_SALDATA_RUNINMAIN( SetRepresentedURL( i_rDocURL
) )
363 if( comphelper::isFileUrl(i_rDocURL
) )
366 osl_getSystemPathFromFileURL( i_rDocURL
.pData
, &aSysPath
.pData
);
367 NSString
* pStr
= CreateNSString( aSysPath
);
371 [mpNSWindow setRepresentedFilename
: pStr
];
376 void AquaSalFrame::initShow()
378 OSX_SALDATA_RUNINMAIN( initShow() )
381 if( ! mbPositioned
&& ! mbFullScreen
)
383 tools::Rectangle aScreenRect
;
384 GetWorkArea( aScreenRect
);
385 if( mpParent
) // center relative to parent
388 long nNewX
= mpParent
->maGeometry
.nX
+ (static_cast<long>(mpParent
->maGeometry
.nWidth
) - static_cast<long>(maGeometry
.nWidth
))/2;
389 if( nNewX
< aScreenRect
.Left() )
390 nNewX
= aScreenRect
.Left();
391 if( long(nNewX
+ maGeometry
.nWidth
) > aScreenRect
.Right() )
392 nNewX
= aScreenRect
.Right() - maGeometry
.nWidth
-1;
393 long nNewY
= mpParent
->maGeometry
.nY
+ (static_cast<long>(mpParent
->maGeometry
.nHeight
) - static_cast<long>(maGeometry
.nHeight
))/2;
394 if( nNewY
< aScreenRect
.Top() )
395 nNewY
= aScreenRect
.Top();
396 if( nNewY
> aScreenRect
.Bottom() )
397 nNewY
= aScreenRect
.Bottom() - maGeometry
.nHeight
-1;
398 SetPosSize( nNewX
- mpParent
->maGeometry
.nX
,
399 nNewY
- mpParent
->maGeometry
.nY
,
400 0, 0, SAL_FRAME_POSSIZE_X
| SAL_FRAME_POSSIZE_Y
);
402 else if( ! (mnStyle
& SalFrameStyleFlags::SIZEABLE
) )
405 long nNewX
= (aScreenRect
.GetWidth() - maGeometry
.nWidth
)/2;
406 long nNewY
= (aScreenRect
.GetHeight() - maGeometry
.nHeight
)/2;
407 SetPosSize( nNewX
, nNewY
, 0, 0, SAL_FRAME_POSSIZE_X
| SAL_FRAME_POSSIZE_Y
);
411 // make sure the view is present in the wrapper list before any children receive focus
412 [AquaA11yFactory registerView
: mpNSView
];
415 void AquaSalFrame::SendPaintEvent( const tools::Rectangle
* pRect
)
417 OSX_SALDATA_RUNINMAIN( SendPaintEvent( pRect
) )
419 SalPaintEvent
aPaintEvt( 0, 0, maGeometry
.nWidth
, maGeometry
.nHeight
, true );
422 aPaintEvt
.mnBoundX
= pRect
->Left();
423 aPaintEvt
.mnBoundY
= pRect
->Top();
424 aPaintEvt
.mnBoundWidth
= pRect
->GetWidth();
425 aPaintEvt
.mnBoundHeight
= pRect
->GetHeight();
428 CallCallback(SalEvent::Paint
, &aPaintEvt
);
431 void AquaSalFrame::Show(bool bVisible
, bool bNoActivate
)
436 OSX_SALDATA_RUNINMAIN( Show(bVisible
, bNoActivate
) )
444 CallCallback(SalEvent::Resize
, nullptr);
445 // trigger filling our backbuffer
448 if( bNoActivate
|| [mpNSWindow canBecomeKeyWindow
] == NO
)
449 [mpNSWindow orderFront
: NSApp
];
451 [mpNSWindow makeKeyAndOrderFront
: NSApp
];
455 /* #i92674# #i96433# we do not want an invisible parent to show up (which adding a visible
456 child implicitly does). However we also do not want a parentless toolbar.
458 HACK: try to decide when we should not insert a child to its parent
459 floaters and ownerdraw windows have not yet shown up in cases where
460 we don't want the parent to become visible
462 if( mpParent
->mbShown
|| (mnStyle
& (SalFrameStyleFlags::OWNERDRAWDECORATION
| SalFrameStyleFlags::FLOAT
) ) )
464 [mpParent
->mpNSWindow addChildWindow
: mpNSWindow ordered
: NSWindowAbove
];
469 [mpNSWindow makeMainWindow
];
473 // if the frame holding the current menubar gets hidden
474 // show the default menubar
475 if( mpMenu
&& mpMenu
->mbMenuBar
&& AquaSalMenu::pCurrentMenuBar
== mpMenu
)
476 AquaSalMenu::setDefaultMenu();
478 // #i90440# #i94443# work around the focus going back to some other window
479 // if a child gets hidden for a parent window
480 if( mpParent
&& mpParent
->mbShown
&& [mpNSWindow isKeyWindow
] )
481 [mpParent
->mpNSWindow makeKeyAndOrderFront
: NSApp
];
483 [SalFrameView unsetMouseFrame
: this];
484 if( mpParent
&& [mpNSWindow parentWindow
] == mpParent
->mpNSWindow
)
485 [mpParent
->mpNSWindow removeChildWindow
: mpNSWindow
];
487 [mpNSWindow orderOut
: NSApp
];
491 void AquaSalFrame::SetMinClientSize( long nWidth
, long nHeight
)
493 OSX_SALDATA_RUNINMAIN( SetMinClientSize( nWidth
, nHeight
) )
496 mnMinHeight
= nHeight
;
500 // Always add the decoration as the dimension concerns only
501 // the content rectangle
502 nWidth
+= maGeometry
.nLeftDecoration
+ maGeometry
.nRightDecoration
;
503 nHeight
+= maGeometry
.nTopDecoration
+ maGeometry
.nBottomDecoration
;
505 NSSize aSize
= { static_cast<CGFloat
>(nWidth
), static_cast<CGFloat
>(nHeight
) };
507 // Size of full window (content+structure) although we only
508 // have the client size in arguments
509 [mpNSWindow setMinSize
: aSize
];
513 void AquaSalFrame::SetMaxClientSize( long nWidth
, long nHeight
)
515 OSX_SALDATA_RUNINMAIN( SetMaxClientSize( nWidth
, nHeight
) )
518 mnMaxHeight
= nHeight
;
522 // Always add the decoration as the dimension concerns only
523 // the content rectangle
524 nWidth
+= maGeometry
.nLeftDecoration
+ maGeometry
.nRightDecoration
;
525 nHeight
+= maGeometry
.nTopDecoration
+ maGeometry
.nBottomDecoration
;
527 // Carbon windows can't have a size greater than 32767x32767
528 if (nWidth
>32767) nWidth
=32767;
529 if (nHeight
>32767) nHeight
=32767;
531 NSSize aSize
= { static_cast<CGFloat
>(nWidth
), static_cast<CGFloat
>(nHeight
) };
533 // Size of full window (content+structure) although we only
534 // have the client size in arguments
535 [mpNSWindow setMaxSize
: aSize
];
539 void AquaSalFrame::GetClientSize( long& rWidth
, long& rHeight
)
541 if (mbShown
|| mbInitShow
|| Application::IsBitmapRendering())
543 rWidth
= maGeometry
.nWidth
;
544 rHeight
= maGeometry
.nHeight
;
553 SalEvent
AquaSalFrame::PreparePosSize(long nX
, long nY
, long nWidth
, long nHeight
, sal_uInt16 nFlags
)
555 SalEvent nEvent
= SalEvent::NONE
;
556 assert(mpNSWindow
|| Application::IsBitmapRendering());
558 if (nFlags
& (SAL_FRAME_POSSIZE_X
| SAL_FRAME_POSSIZE_Y
))
561 nEvent
= SalEvent::Move
;
564 if (nFlags
& (SAL_FRAME_POSSIZE_WIDTH
| SAL_FRAME_POSSIZE_HEIGHT
))
567 nEvent
= (nEvent
== SalEvent::Move
) ? SalEvent::MoveResize
: SalEvent::Resize
;
570 if (Application::IsBitmapRendering())
572 if (nFlags
& SAL_FRAME_POSSIZE_X
)
574 if (nFlags
& SAL_FRAME_POSSIZE_Y
)
576 if (nFlags
& SAL_FRAME_POSSIZE_WIDTH
)
578 maGeometry
.nWidth
= nWidth
;
579 if (mnMaxWidth
> 0 && maGeometry
.nWidth
> static_cast<unsigned int>(mnMaxWidth
))
580 maGeometry
.nWidth
= mnMaxWidth
;
581 if (mnMinWidth
> 0 && maGeometry
.nWidth
< static_cast<unsigned int>(mnMinWidth
))
582 maGeometry
.nWidth
= mnMinWidth
;
584 if (nFlags
& SAL_FRAME_POSSIZE_HEIGHT
)
586 maGeometry
.nHeight
= nHeight
;
587 if (mnMaxHeight
> 0 && maGeometry
.nHeight
> static_cast<unsigned int>(mnMaxHeight
))
588 maGeometry
.nHeight
= mnMaxHeight
;
589 if (mnMinHeight
> 0 && maGeometry
.nHeight
< static_cast<unsigned int>(mnMinHeight
))
590 maGeometry
.nHeight
= mnMinHeight
;
592 if (nEvent
!= SalEvent::NONE
)
593 CallCallback(nEvent
, nullptr);
599 void AquaSalFrame::SetWindowState( const SalFrameState
* pState
)
601 if (!mpNSWindow
&& !Application::IsBitmapRendering())
604 OSX_SALDATA_RUNINMAIN( SetWindowState( pState
) )
606 sal_uInt16 nFlags
= 0;
607 nFlags
|= ((pState
->mnMask
& WindowStateMask::X
) ? SAL_FRAME_POSSIZE_X
: 0);
608 nFlags
|= ((pState
->mnMask
& WindowStateMask::Y
) ? SAL_FRAME_POSSIZE_Y
: 0);
609 nFlags
|= ((pState
->mnMask
& WindowStateMask::Width
) ? SAL_FRAME_POSSIZE_WIDTH
: 0);
610 nFlags
|= ((pState
->mnMask
& WindowStateMask::Height
) ? SAL_FRAME_POSSIZE_HEIGHT
: 0);
612 SalEvent nEvent
= PreparePosSize(pState
->mnX
, pState
->mnY
, pState
->mnWidth
, pState
->mnHeight
, nFlags
);
613 if (Application::IsBitmapRendering())
617 NSRect aStateRect
= [mpNSWindow frame
];
618 aStateRect
= [NSWindow contentRectForFrameRect
: aStateRect styleMask
: mnStyleMask
];
619 CocoaToVCL(aStateRect
);
620 if (pState
->mnMask
& WindowStateMask::X
)
621 aStateRect
.origin
.x
= float(pState
->mnX
);
622 if (pState
->mnMask
& WindowStateMask::Y
)
623 aStateRect
.origin
.y
= float(pState
->mnY
);
624 if (pState
->mnMask
& WindowStateMask::Width
)
625 aStateRect
.size
.width
= float(pState
->mnWidth
);
626 if (pState
->mnMask
& WindowStateMask::Height
)
627 aStateRect
.size
.height
= float(pState
->mnHeight
);
628 VCLToCocoa(aStateRect
);
629 aStateRect
= [NSWindow frameRectForContentRect
: aStateRect styleMask
: mnStyleMask
];
630 [mpNSWindow setFrame
: aStateRect display
: NO
];
632 if (pState
->mnState
== WindowStateState::Minimized
)
633 [mpNSWindow miniaturize
: NSApp
];
634 else if ([mpNSWindow isMiniaturized
])
635 [mpNSWindow deminiaturize
: NSApp
];
637 /* ZOOMED is not really maximized (actually it toggles between a user set size and
638 the program specified one), but comes closest since the default behavior is
639 "maximized" if the user did not intervene
641 if (pState
->mnState
== WindowStateState::Maximized
)
643 if (![mpNSWindow isZoomed
])
644 [mpNSWindow zoom
: NSApp
];
648 if ([mpNSWindow isZoomed
])
649 [mpNSWindow zoom
: NSApp
];
653 UpdateFrameGeometry();
655 // send event that we were moved/sized
656 if( nEvent
!= SalEvent::NONE
)
657 CallCallback( nEvent
, nullptr );
661 // trigger filling our backbuffer
664 // tell the system the views need to be updated
665 [mpNSWindow display
];
669 bool AquaSalFrame::GetWindowState( SalFrameState
* pState
)
673 if (Application::IsBitmapRendering())
675 pState
->mnMask
= WindowStateMask::X
| WindowStateMask::Y
676 | WindowStateMask::Width
| WindowStateMask::Height
677 | WindowStateMask::State
;
678 pState
->mnX
= maGeometry
.nX
;
679 pState
->mnY
= maGeometry
.nY
;
680 pState
->mnWidth
= maGeometry
.nWidth
;
681 pState
->mnHeight
= maGeometry
.nHeight
;
682 pState
->mnState
= WindowStateState::Normal
;
688 OSX_SALDATA_RUNINMAIN_UNION( GetWindowState( pState
), boolean
)
690 pState
->mnMask
= WindowStateMask::X
|
692 WindowStateMask::Width
|
693 WindowStateMask::Height
|
694 WindowStateMask::State
;
696 NSRect aStateRect
= [mpNSWindow frame
];
697 aStateRect
= [NSWindow contentRectForFrameRect
: aStateRect styleMask
: mnStyleMask
];
698 CocoaToVCL( aStateRect
);
699 pState
->mnX
= long(aStateRect
.origin
.x
);
700 pState
->mnY
= long(aStateRect
.origin
.y
);
701 pState
->mnWidth
= long(aStateRect
.size
.width
);
702 pState
->mnHeight
= long(aStateRect
.size
.height
);
704 if( [mpNSWindow isMiniaturized
] )
705 pState
->mnState
= WindowStateState::Minimized
;
706 else if( ! [mpNSWindow isZoomed
] )
707 pState
->mnState
= WindowStateState::Normal
;
709 pState
->mnState
= WindowStateState::Maximized
;
714 void AquaSalFrame::SetScreenNumber(unsigned int nScreen
)
719 OSX_SALDATA_RUNINMAIN( SetScreenNumber( nScreen
) )
721 NSArray
* pScreens
= [NSScreen screens
];
722 NSScreen
* pScreen
= nil
;
723 if( pScreens
&& nScreen
< [pScreens count
] )
725 // get new screen frame
726 pScreen
= [pScreens objectAtIndex
: nScreen
];
727 NSRect aNewScreen
= [pScreen frame
];
729 // get current screen frame
730 pScreen
= [mpNSWindow screen
];
733 NSRect aCurScreen
= [pScreen frame
];
734 if( aCurScreen
.origin
.x
!= aNewScreen
.origin
.x
||
735 aCurScreen
.origin
.y
!= aNewScreen
.origin
.y
)
737 NSRect aFrameRect
= [mpNSWindow frame
];
738 aFrameRect
.origin
.x
+= aNewScreen
.origin
.x
- aCurScreen
.origin
.x
;
739 aFrameRect
.origin
.y
+= aNewScreen
.origin
.y
- aCurScreen
.origin
.y
;
740 [mpNSWindow setFrame
: aFrameRect display
: NO
];
741 UpdateFrameGeometry();
747 void AquaSalFrame::SetApplicationID( const OUString
&/*rApplicationID*/ )
751 void AquaSalFrame::ShowFullScreen( bool bFullScreen
, sal_Int32 nDisplay
)
753 doShowFullScreen(bFullScreen
, nDisplay
);
756 void AquaSalFrame::doShowFullScreen( bool bFullScreen
, sal_Int32 nDisplay
)
760 if (Application::IsBitmapRendering() && bFullScreen
)
761 SetPosSize(0, 0, 1024, 768, SAL_FRAME_POSSIZE_WIDTH
| SAL_FRAME_POSSIZE_HEIGHT
);
765 SAL_INFO("vcl.osx", OSL_THIS_FUNC
<< ": mbFullScreen=" << mbFullScreen
<< ", bFullScreen=" << bFullScreen
);
767 if( mbFullScreen
== bFullScreen
)
770 OSX_SALDATA_RUNINMAIN( ShowFullScreen( bFullScreen
, nDisplay
) )
772 mbFullScreen
= bFullScreen
;
776 // hide the dock and the menubar if we are on the menu screen
777 // which is always on index 0 according to documentation
778 bool bHideMenu
= (nDisplay
== 0);
780 NSRect aNewContentRect
= NSZeroRect
;
781 // get correct screen
782 NSScreen
* pScreen
= nil
;
783 NSArray
* pScreens
= [NSScreen screens
];
786 if( nDisplay
>= 0 && static_cast<unsigned int>(nDisplay
) < [pScreens count
] )
787 pScreen
= [pScreens objectAtIndex
: nDisplay
];
790 // this means span all screens
792 NSEnumerator
* pEnum
= [pScreens objectEnumerator
];
793 while( (pScreen
= [pEnum nextObject
]) != nil
)
795 NSRect aScreenRect
= [pScreen frame
];
796 if( aScreenRect
.origin
.x
< aNewContentRect
.origin
.x
)
798 aNewContentRect
.size
.width
+= aNewContentRect
.origin
.x
- aScreenRect
.origin
.x
;
799 aNewContentRect
.origin
.x
= aScreenRect
.origin
.x
;
801 if( aScreenRect
.origin
.y
< aNewContentRect
.origin
.y
)
803 aNewContentRect
.size
.height
+= aNewContentRect
.origin
.y
- aScreenRect
.origin
.y
;
804 aNewContentRect
.origin
.y
= aScreenRect
.origin
.y
;
806 if( aScreenRect
.origin
.x
+ aScreenRect
.size
.width
> aNewContentRect
.origin
.x
+ aNewContentRect
.size
.width
)
807 aNewContentRect
.size
.width
= aScreenRect
.origin
.x
+ aScreenRect
.size
.width
- aNewContentRect
.origin
.x
;
808 if( aScreenRect
.origin
.y
+ aScreenRect
.size
.height
> aNewContentRect
.origin
.y
+ aNewContentRect
.size
.height
)
809 aNewContentRect
.size
.height
= aScreenRect
.origin
.y
+ aScreenRect
.size
.height
- aNewContentRect
.origin
.y
;
813 if( aNewContentRect
.size
.width
== 0 && aNewContentRect
.size
.height
== 0 )
816 pScreen
= [mpNSWindow screen
];
818 pScreen
= [NSScreen mainScreen
];
820 aNewContentRect
= [pScreen frame
];
824 [NSMenu setMenuBarVisible
:NO
];
826 maFullScreenRect
= [mpNSWindow frame
];
828 [mpNSWindow setFrame
: [NSWindow frameRectForContentRect
: aNewContentRect styleMask
: mnStyleMask
] display
: mbShown
? YES
: NO
];
832 [mpNSWindow setFrame
: maFullScreenRect display
: mbShown
? YES
: NO
];
834 // show the dock and the menubar
835 [NSMenu setMenuBarVisible
:YES
];
838 UpdateFrameGeometry();
841 CallCallback(SalEvent::MoveResize
, nullptr);
843 // trigger filling our backbuffer
848 void AquaSalFrame::StartPresentation( bool bStart
)
853 OSX_SALDATA_RUNINMAIN( StartPresentation( bStart
) )
857 GetSalData()->maPresentationFrames
.push_back( this );
858 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep
,
859 kIOPMAssertionLevelOn
,
860 CFSTR("LibreOffice presentation running"),
862 [mpNSWindow setLevel
: NSPopUpMenuWindowLevel
];
864 [mpNSWindow makeMainWindow
];
868 GetSalData()->maPresentationFrames
.remove( this );
869 IOPMAssertionRelease(mnAssertionID
);
870 [mpNSWindow setLevel
: NSNormalWindowLevel
];
874 void AquaSalFrame::SetAlwaysOnTop( bool )
878 void AquaSalFrame::ToTop(SalFrameToTop nFlags
)
883 OSX_SALDATA_RUNINMAIN( ToTop( nFlags
) )
885 if( ! (nFlags
& SalFrameToTop::RestoreWhenMin
) )
887 if( ! [mpNSWindow isVisible
] || [mpNSWindow isMiniaturized
] )
890 if( nFlags
& SalFrameToTop::GrabFocus
)
891 [mpNSWindow makeKeyAndOrderFront
: NSApp
];
893 [mpNSWindow orderFront
: NSApp
];
896 NSCursor
* AquaSalFrame::getCurrentCursor()
898 OSX_SALDATA_RUNINMAIN_POINTER( getCurrentCursor(), NSCursor
* )
900 NSCursor
* pCursor
= nil
;
901 switch( mePointerStyle
)
903 case PointerStyle::Text
: pCursor
= [NSCursor IBeamCursor
]; break;
904 case PointerStyle::Cross
: pCursor
= [NSCursor crosshairCursor
]; break;
905 case PointerStyle::Hand
:
906 case PointerStyle::Move
: pCursor
= [NSCursor openHandCursor
]; break;
907 case PointerStyle::NSize
: pCursor
= [NSCursor resizeUpCursor
]; break;
908 case PointerStyle::SSize
: pCursor
= [NSCursor resizeDownCursor
]; break;
909 case PointerStyle::ESize
: pCursor
= [NSCursor resizeRightCursor
]; break;
910 case PointerStyle::WSize
: pCursor
= [NSCursor resizeLeftCursor
]; break;
911 case PointerStyle::Arrow
: pCursor
= [NSCursor arrowCursor
]; break;
912 case PointerStyle::VSplit
:
913 case PointerStyle::VSizeBar
:
914 case PointerStyle::WindowNSize
:
915 case PointerStyle::WindowSSize
:
916 pCursor
= [NSCursor resizeUpDownCursor
]; break;
917 case PointerStyle::HSplit
:
918 case PointerStyle::HSizeBar
:
919 case PointerStyle::WindowESize
:
920 case PointerStyle::WindowWSize
:
921 pCursor
= [NSCursor resizeLeftRightCursor
]; break;
922 case PointerStyle::RefHand
: pCursor
= [NSCursor pointingHandCursor
]; break;
925 pCursor
= GetSalData()->getCursor( mePointerStyle
);
928 assert( false && "unmapped cursor" );
929 pCursor
= [NSCursor arrowCursor
];
936 void AquaSalFrame::SetPointer( PointerStyle ePointerStyle
)
940 if( ePointerStyle
== mePointerStyle
)
943 OSX_SALDATA_RUNINMAIN( SetPointer( ePointerStyle
) )
945 mePointerStyle
= ePointerStyle
;
947 [mpNSWindow invalidateCursorRectsForView
: mpNSView
];
950 void AquaSalFrame::SetPointerPos( long nX
, long nY
)
952 OSX_SALDATA_RUNINMAIN( SetPointerPos( nX
, nY
) )
954 // FIXME: use Cocoa functions
955 // FIXME: multiscreen support
956 CGPoint aPoint
= { static_cast<CGFloat
>(nX
+ maGeometry
.nX
), static_cast<CGFloat
>(nY
+ maGeometry
.nY
) };
957 CGDirectDisplayID mainDisplayID
= CGMainDisplayID();
958 CGDisplayMoveCursorToPoint( mainDisplayID
, aPoint
);
961 void AquaSalFrame::Flush()
963 if( !(mbGraphics
&& mpGraphics
&& mpNSView
&& mbShown
) )
966 OSX_SALDATA_RUNINMAIN( Flush() )
968 [mpNSView setNeedsDisplay
: YES
];
970 // outside of the application's event loop (e.g. IntroWindow)
971 // nothing would trigger paint event handling
972 // => fall back to synchronous painting
973 if( ImplGetSVData()->maAppData
.mnDispatchLevel
<= 0 )
979 void AquaSalFrame::Flush( const tools::Rectangle
& rRect
)
981 if( !(mbGraphics
&& mpGraphics
&& mpNSView
&& mbShown
) )
984 OSX_SALDATA_RUNINMAIN( Flush( rRect
) )
986 NSRect aNSRect
= { { static_cast<CGFloat
>(rRect
.Left()), static_cast<CGFloat
>(rRect
.Top()) }, { static_cast<CGFloat
>(rRect
.GetWidth()), static_cast<CGFloat
>(rRect
.GetHeight()) } };
987 VCLToCocoa( aNSRect
, false );
988 [mpNSView setNeedsDisplayInRect
: aNSRect
];
990 // outside of the application's event loop (e.g. IntroWindow)
991 // nothing would trigger paint event handling
992 // => fall back to synchronous painting
993 if( ImplGetSVData()->maAppData
.mnDispatchLevel
<= 0 )
999 void AquaSalFrame::SetInputContext( SalInputContext
* pContext
)
1003 mnICOptions
= InputContextFlags::NONE
;
1007 mnICOptions
= pContext
->mnOptions
;
1009 if(!(pContext
->mnOptions
& InputContextFlags::Text
))
1013 void AquaSalFrame::EndExtTextInput( EndExtTextInputFlags
)
1017 OUString
AquaSalFrame::GetKeyName( sal_uInt16 nKeyCode
)
1019 static std::map
< sal_uInt16
, OUString
> aKeyMap
;
1020 if( aKeyMap
.empty() )
1023 for( i
= KEY_A
; i
<= KEY_Z
; i
++ )
1024 aKeyMap
[ i
] = OUString( sal_Unicode( 'A' + (i
- KEY_A
) ) );
1025 for( i
= KEY_0
; i
<= KEY_9
; i
++ )
1026 aKeyMap
[ i
] = OUString( sal_Unicode( '0' + (i
- KEY_0
) ) );
1027 for( i
= KEY_F1
; i
<= KEY_F26
; i
++ )
1029 aKeyMap
[ i
] = "F" + OUString::number(i
- KEY_F1
+ 1);
1032 aKeyMap
[ KEY_DOWN
] = OUString( u
'\x21e3' );
1033 aKeyMap
[ KEY_UP
] = OUString( u
'\x21e1' );
1034 aKeyMap
[ KEY_LEFT
] = OUString( u
'\x21e0' );
1035 aKeyMap
[ KEY_RIGHT
] = OUString( u
'\x21e2' );
1036 aKeyMap
[ KEY_HOME
] = OUString( u
'\x2196' );
1037 aKeyMap
[ KEY_END
] = OUString( u
'\x2198' );
1038 aKeyMap
[ KEY_PAGEUP
] = OUString( u
'\x21de' );
1039 aKeyMap
[ KEY_PAGEDOWN
] = OUString( u
'\x21df' );
1040 aKeyMap
[ KEY_RETURN
] = OUString( u
'\x21a9' );
1041 aKeyMap
[ KEY_ESCAPE
] = "esc";
1042 aKeyMap
[ KEY_TAB
] = OUString( u
'\x21e5' );
1043 aKeyMap
[ KEY_BACKSPACE
]= OUString( u
'\x232b' );
1044 aKeyMap
[ KEY_SPACE
] = OUString( u
'\x2423' );
1045 aKeyMap
[ KEY_DELETE
] = OUString( u
'\x2326' );
1046 aKeyMap
[ KEY_ADD
] = "+";
1047 aKeyMap
[ KEY_SUBTRACT
] = "-";
1048 aKeyMap
[ KEY_DIVIDE
] = "/";
1049 aKeyMap
[ KEY_MULTIPLY
] = "*";
1050 aKeyMap
[ KEY_POINT
] = ".";
1051 aKeyMap
[ KEY_COMMA
] = ",";
1052 aKeyMap
[ KEY_LESS
] = "<";
1053 aKeyMap
[ KEY_GREATER
] = ">";
1054 aKeyMap
[ KEY_EQUAL
] = "=";
1055 aKeyMap
[ KEY_OPEN
] = OUString( u
'\x23cf' );
1056 aKeyMap
[ KEY_TILDE
] = "~";
1057 aKeyMap
[ KEY_BRACKETLEFT
] = "[";
1058 aKeyMap
[ KEY_BRACKETRIGHT
] = "]";
1059 aKeyMap
[ KEY_SEMICOLON
] = ";";
1060 aKeyMap
[ KEY_QUOTERIGHT
] = "'";
1062 /* yet unmapped KEYCODES:
1063 aKeyMap[ KEY_INSERT ] = OUString( sal_Unicode( ) );
1064 aKeyMap[ KEY_CUT ] = OUString( sal_Unicode( ) );
1065 aKeyMap[ KEY_COPY ] = OUString( sal_Unicode( ) );
1066 aKeyMap[ KEY_PASTE ] = OUString( sal_Unicode( ) );
1067 aKeyMap[ KEY_UNDO ] = OUString( sal_Unicode( ) );
1068 aKeyMap[ KEY_REPEAT ] = OUString( sal_Unicode( ) );
1069 aKeyMap[ KEY_FIND ] = OUString( sal_Unicode( ) );
1070 aKeyMap[ KEY_PROPERTIES ] = OUString( sal_Unicode( ) );
1071 aKeyMap[ KEY_FRONT ] = OUString( sal_Unicode( ) );
1072 aKeyMap[ KEY_CONTEXTMENU ] = OUString( sal_Unicode( ) );
1073 aKeyMap[ KEY_MENU ] = OUString( sal_Unicode( ) );
1074 aKeyMap[ KEY_HELP ] = OUString( sal_Unicode( ) );
1075 aKeyMap[ KEY_HANGUL_HANJA ] = OUString( sal_Unicode( ) );
1076 aKeyMap[ KEY_DECIMAL ] = OUString( sal_Unicode( ) );
1077 aKeyMap[ KEY_QUOTELEFT ]= OUString( sal_Unicode( ) );
1078 aKeyMap[ KEY_CAPSLOCK ]= OUString( sal_Unicode( ) );
1079 aKeyMap[ KEY_NUMLOCK ]= OUString( sal_Unicode( ) );
1080 aKeyMap[ KEY_SCROLLLOCK ]= OUString( sal_Unicode( ) );
1085 OUStringBuffer
aResult( 16 );
1087 sal_uInt16 nUnmodifiedCode
= (nKeyCode
& KEY_CODE_MASK
);
1088 std::map
< sal_uInt16
, OUString
>::const_iterator it
= aKeyMap
.find( nUnmodifiedCode
);
1089 if( it
!= aKeyMap
.end() )
1091 if( (nKeyCode
& KEY_SHIFT
) != 0 )
1092 aResult
.append( u
'\x21e7' ); //⇧
1093 if( (nKeyCode
& KEY_MOD1
) != 0 )
1094 aResult
.append( u
'\x2318' ); //⌘
1095 if( (nKeyCode
& KEY_MOD2
) != 0 )
1096 aResult
.append( u
'\x2325' ); //⌥
1097 if( (nKeyCode
& KEY_MOD3
) != 0 )
1098 aResult
.append( u
'\x2303' ); //⌃
1100 aResult
.append( it
->second
);
1103 return aResult
.makeStringAndClear();
1106 static void getAppleScrollBarVariant(StyleSettings
&rSettings
)
1108 bool bIsScrollbarDoubleMax
= true; // default is DoubleMax
1110 CFStringRef AppleScrollBarType
= CFSTR("AppleScrollBarVariant");
1111 if( AppleScrollBarType
)
1113 CFStringRef ScrollBarVariant
= static_cast<CFStringRef
>(CFPreferencesCopyAppValue( AppleScrollBarType
, kCFPreferencesCurrentApplication
));
1114 if( ScrollBarVariant
)
1116 if( CFGetTypeID( ScrollBarVariant
) == CFStringGetTypeID() )
1118 // TODO: check for the less important variants "DoubleMin" and "DoubleBoth" too
1119 CFStringRef DoubleMax
= CFSTR("DoubleMax");
1122 if ( !CFStringCompare(ScrollBarVariant
, DoubleMax
, kCFCompareCaseInsensitive
) )
1123 bIsScrollbarDoubleMax
= true;
1125 bIsScrollbarDoubleMax
= false;
1126 CFRelease(DoubleMax
);
1129 CFRelease( ScrollBarVariant
);
1131 CFRelease(AppleScrollBarType
);
1134 GetSalData()->mbIsScrollbarDoubleMax
= bIsScrollbarDoubleMax
;
1136 CFStringRef jumpScroll
= CFSTR("AppleScrollerPagingBehavior");
1139 CFBooleanRef jumpStr
= static_cast<CFBooleanRef
>(CFPreferencesCopyAppValue( jumpScroll
, kCFPreferencesCurrentApplication
));
1142 if( CFGetTypeID( jumpStr
) == CFBooleanGetTypeID() )
1143 rSettings
.SetPrimaryButtonWarpsSlider(jumpStr
== kCFBooleanTrue
);
1144 CFRelease( jumpStr
);
1146 CFRelease( jumpScroll
);
1150 static Color
getColor( NSColor
* pSysColor
, const Color
& rDefault
, NSWindow
* pWin
)
1152 Color
aRet( rDefault
);
1156 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1157 // "'colorUsingColorSpaceName:device:' is deprecated: first deprecated in macOS 10.14 -
1158 // Use -colorUsingType: or -colorUsingColorSpace: instead"
1159 NSColor
* pRBGColor
= [pSysColor colorUsingColorSpaceName
: NSDeviceRGBColorSpace device
: [pWin deviceDescription
]];
1160 SAL_WNODEPRECATED_DECLARATIONS_POP
1163 CGFloat r
= 0, g
= 0, b
= 0, a
= 0;
1164 [pRBGColor getRed
: &r green
: &g blue
: &b alpha
: &a
];
1165 aRet
= Color( int(r
*255.999), int(g
*255.999), int(b
*255.999) );
1167 do not release here; leads to duplicate free in yield
1168 it seems the converted color comes out autoreleased, although this
1170 [pRBGColor release];
1177 static vcl::Font
getFont( NSFont
* pFont
, long nDPIY
, const vcl::Font
& rDefault
)
1179 vcl::Font
aResult( rDefault
);
1182 aResult
.SetFamilyName( GetOUString( [pFont familyName
] ) );
1183 aResult
.SetFontHeight( static_cast<int>(([pFont pointSize
] * 72.0 / static_cast<float>(nDPIY
))+0.5) );
1184 aResult
.SetItalic( ([pFont italicAngle
] != 0.0) ? ITALIC_NORMAL
: ITALIC_NONE
);
1191 void AquaSalFrame::getResolution( sal_Int32
& o_rDPIX
, sal_Int32
& o_rDPIY
)
1193 OSX_SALDATA_RUNINMAIN( getResolution( o_rDPIX
, o_rDPIY
) )
1198 ReleaseGraphics( mpGraphics
);
1200 mpGraphics
->GetResolution( o_rDPIX
, o_rDPIY
);
1203 // on OSX-Aqua the style settings are independent of the frame, so it does
1204 // not really belong here. Since the connection to the Appearance_Manager
1205 // is currently done in salnativewidgets.cxx this would be a good place.
1206 // On the other hand VCL's platform independent code currently only asks
1207 // SalFrames for system settings anyway, so moving the code somewhere else
1208 // doesn't make the anything cleaner for now
1209 void AquaSalFrame::UpdateSettings( AllSettings
& rSettings
)
1214 OSX_SALDATA_RUNINMAIN( UpdateSettings( rSettings
) )
1216 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1217 // "'lockFocus' is deprecated: first deprecated in macOS 10.14 - To draw, subclass NSView
1218 // and implement -drawRect:; AppKit's automatic deferred display mechanism will call
1219 // -drawRect: as necessary to display the view."
1220 if (![mpNSView lockFocusIfCanDraw
])
1222 SAL_WNODEPRECATED_DECLARATIONS_POP
1224 StyleSettings aStyleSettings
= rSettings
.GetStyleSettings();
1227 Color
aBackgroundColor( 0xEC, 0xEC, 0xEC );
1228 aStyleSettings
.BatchSetBackgrounds( aBackgroundColor
, false );
1229 aStyleSettings
.SetLightBorderColor( aBackgroundColor
);
1231 Color
aInactiveTabColor( aBackgroundColor
);
1232 aInactiveTabColor
.DecreaseLuminance( 32 );
1233 aStyleSettings
.SetInactiveTabColor( aInactiveTabColor
);
1235 Color
aShadowColor( aStyleSettings
.GetShadowColor() );
1236 aShadowColor
.IncreaseLuminance( 32 );
1237 aStyleSettings
.SetShadowColor( aShadowColor
);
1239 // get the system font settings
1240 vcl::Font aAppFont
= aStyleSettings
.GetAppFont();
1241 sal_Int32 nDPIX
= 72, nDPIY
= 72;
1242 getResolution( nDPIX
, nDPIY
);
1243 aAppFont
= getFont( [NSFont systemFontOfSize
: 0], nDPIY
, aAppFont
);
1245 aStyleSettings
.SetToolbarIconSize( ToolbarIconSize::Large
);
1247 // TODO: better mapping of macOS<->LibreOffice font settings
1248 vcl::Font
aLabelFont( getFont( [NSFont labelFontOfSize
: 0], nDPIY
, aAppFont
) );
1249 aStyleSettings
.BatchSetFonts( aAppFont
, aLabelFont
);
1250 vcl::Font
aMenuFont( getFont( [NSFont menuFontOfSize
: 0], nDPIY
, aAppFont
) );
1251 aStyleSettings
.SetMenuFont( aMenuFont
);
1253 vcl::Font
aTitleFont( getFont( [NSFont titleBarFontOfSize
: 0], nDPIY
, aAppFont
) );
1254 aStyleSettings
.SetTitleFont( aTitleFont
);
1255 aStyleSettings
.SetFloatTitleFont( aTitleFont
);
1257 vcl::Font
aTooltipFont(getFont([NSFont toolTipsFontOfSize
: 0], nDPIY
, aAppFont
));
1258 aStyleSettings
.SetHelpFont(aTooltipFont
);
1260 Color
aHighlightColor( getColor( [NSColor selectedTextBackgroundColor
],
1261 aStyleSettings
.GetHighlightColor(), mpNSWindow
) );
1262 aStyleSettings
.SetHighlightColor( aHighlightColor
);
1263 Color
aHighlightTextColor( getColor( [NSColor selectedTextColor
],
1264 aStyleSettings
.GetHighlightTextColor(), mpNSWindow
) );
1265 aStyleSettings
.SetHighlightTextColor( aHighlightTextColor
);
1267 Color
aMenuHighlightColor( getColor( [NSColor selectedMenuItemColor
],
1268 aStyleSettings
.GetMenuHighlightColor(), mpNSWindow
) );
1269 aStyleSettings
.SetMenuHighlightColor( aMenuHighlightColor
);
1270 Color
aMenuHighlightTextColor( getColor( [NSColor selectedMenuItemTextColor
],
1271 aStyleSettings
.GetMenuHighlightTextColor(), mpNSWindow
) );
1272 aStyleSettings
.SetMenuHighlightTextColor( aMenuHighlightTextColor
);
1274 aStyleSettings
.SetMenuColor( aBackgroundColor
);
1275 Color
aMenuTextColor( getColor( [NSColor textColor
],
1276 aStyleSettings
.GetMenuTextColor(), mpNSWindow
) );
1277 aStyleSettings
.SetMenuTextColor( aMenuTextColor
);
1278 aStyleSettings
.SetMenuBarTextColor( aMenuTextColor
);
1279 aStyleSettings
.SetMenuBarRolloverTextColor( aMenuTextColor
);
1280 aStyleSettings
.SetMenuBarHighlightTextColor(aStyleSettings
.GetMenuHighlightTextColor());
1282 aStyleSettings
.SetCursorBlinkTime( 500 );
1284 // no mnemonics on macOS
1285 aStyleSettings
.SetOptions( aStyleSettings
.GetOptions() | StyleSettingsOptions::NoMnemonics
);
1287 getAppleScrollBarVariant(aStyleSettings
);
1289 // set scrollbar size
1290 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1291 // 'NSRegularControlSize' is deprecated: first deprecated in macOS 10.12
1292 aStyleSettings
.SetScrollBarSize( static_cast<long int>([NSScroller scrollerWidthForControlSize
:NSRegularControlSize scrollerStyle
:NSScrollerStyleLegacy
]) );
1293 SAL_WNODEPRECATED_DECLARATIONS_POP
1294 // images in menus false for MacOSX
1295 aStyleSettings
.SetPreferredUseImagesInMenus( false );
1296 aStyleSettings
.SetHideDisabledMenuItems( true );
1297 aStyleSettings
.SetPreferredContextMenuShortcuts( false );
1299 rSettings
.SetStyleSettings( aStyleSettings
);
1301 // don't draw frame around each and every toolbar
1302 ImplGetSVData()->maNWFData
.mbDockingAreaAvoidTBFrames
= true;
1304 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1305 // "'unlockFocus' is deprecated: first deprecated in macOS 10.14 - To draw, subclass NSView
1306 // and implement -drawRect:; AppKit's automatic deferred display mechanism will call
1307 // -drawRect: as necessary to display the view."
1308 [mpNSView unlockFocus
];
1309 SAL_WNODEPRECATED_DECLARATIONS_POP
1312 const SystemEnvData
* AquaSalFrame::GetSystemData() const
1317 void AquaSalFrame::Beep()
1319 OSX_SALDATA_RUNINMAIN( Beep() )
1323 void AquaSalFrame::SetPosSize(long nX
, long nY
, long nWidth
, long nHeight
, sal_uInt16 nFlags
)
1325 if (!mpNSWindow
&& !Application::IsBitmapRendering())
1328 OSX_SALDATA_RUNINMAIN( SetPosSize( nX
, nY
, nWidth
, nHeight
, nFlags
) )
1330 SalEvent nEvent
= PreparePosSize(nX
, nY
, nWidth
, nHeight
, nFlags
);
1331 if (Application::IsBitmapRendering())
1334 if( [mpNSWindow isMiniaturized
] )
1335 [mpNSWindow deminiaturize
: NSApp
]; // expand the window
1337 NSRect aFrameRect
= [mpNSWindow frame
];
1338 NSRect aContentRect
= [NSWindow contentRectForFrameRect
: aFrameRect styleMask
: mnStyleMask
];
1340 // position is always relative to parent frame
1341 NSRect aParentContentRect
;
1345 if( AllSettings::GetLayoutRTL() )
1347 if( (nFlags
& SAL_FRAME_POSSIZE_WIDTH
) != 0 )
1348 nX
= mpParent
->maGeometry
.nWidth
- nWidth
-1 - nX
;
1350 nX
= mpParent
->maGeometry
.nWidth
- static_cast<long int>( aContentRect
.size
.width
-1) - nX
;
1352 NSRect aParentFrameRect
= [mpParent
->mpNSWindow frame
];
1353 aParentContentRect
= [NSWindow contentRectForFrameRect
: aParentFrameRect styleMask
: mpParent
->mnStyleMask
];
1356 aParentContentRect
= maScreenRect
; // use screen if no parent
1358 CocoaToVCL( aContentRect
);
1359 CocoaToVCL( aParentContentRect
);
1361 bool bPaint
= false;
1362 if( (nFlags
& (SAL_FRAME_POSSIZE_WIDTH
| SAL_FRAME_POSSIZE_HEIGHT
)) != 0 )
1364 if( nWidth
!= aContentRect
.size
.width
|| nHeight
!= aContentRect
.size
.height
)
1368 // use old window pos if no new pos requested
1369 if( (nFlags
& SAL_FRAME_POSSIZE_X
) != 0 )
1370 aContentRect
.origin
.x
= nX
+ aParentContentRect
.origin
.x
;
1371 if( (nFlags
& SAL_FRAME_POSSIZE_Y
) != 0)
1372 aContentRect
.origin
.y
= nY
+ aParentContentRect
.origin
.y
;
1374 // use old size if no new size requested
1375 if( (nFlags
& SAL_FRAME_POSSIZE_WIDTH
) != 0 )
1376 aContentRect
.size
.width
= nWidth
;
1377 if( (nFlags
& SAL_FRAME_POSSIZE_HEIGHT
) != 0)
1378 aContentRect
.size
.height
= nHeight
;
1380 VCLToCocoa( aContentRect
);
1382 // do not display yet, we need to update our backbuffer
1384 [mpNSWindow setFrame
: [NSWindow frameRectForContentRect
: aContentRect styleMask
: mnStyleMask
] display
: NO
];
1387 UpdateFrameGeometry();
1389 if (nEvent
!= SalEvent::NONE
)
1390 CallCallback(nEvent
, nullptr);
1392 if( mbShown
&& bPaint
)
1394 // trigger filling our backbuffer
1397 // now inform the system that the views need to be drawn
1398 [mpNSWindow display
];
1402 void AquaSalFrame::GetWorkArea( tools::Rectangle
& rRect
)
1406 if (Application::IsBitmapRendering())
1407 rRect
= tools::Rectangle(Point(0, 0), Size(1024, 768));
1411 OSX_SALDATA_RUNINMAIN( GetWorkArea( rRect
) )
1413 NSScreen
* pScreen
= [mpNSWindow screen
];
1414 if( pScreen
== nil
)
1415 pScreen
= [NSScreen mainScreen
];
1416 NSRect aRect
= [pScreen visibleFrame
];
1417 CocoaToVCL( aRect
);
1418 rRect
.SetLeft( static_cast<long>(aRect
.origin
.x
) );
1419 rRect
.SetTop( static_cast<long>(aRect
.origin
.y
) );
1420 rRect
.SetRight( static_cast<long>(aRect
.origin
.x
+ aRect
.size
.width
- 1) );
1421 rRect
.SetBottom( static_cast<long>(aRect
.origin
.y
+ aRect
.size
.height
- 1) );
1424 SalFrame::SalPointerState
AquaSalFrame::GetPointerState()
1426 OSX_SALDATA_RUNINMAIN_UNION( GetPointerState(), state
)
1428 SalPointerState state
;
1432 NSPoint aPt
= [mpNSWindow mouseLocationOutsideOfEventStream
];
1433 CocoaToVCL( aPt
, false );
1434 state
.maPos
= Point(static_cast<long>(aPt
.x
), static_cast<long>(aPt
.y
));
1436 NSEvent
* pCur
= [NSApp currentEvent
];
1437 bool bMouseEvent
= false;
1441 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1442 // 'NSLeftMouseDown' is deprecated: first deprecated in macOS 10.12
1443 // 'NSLeftMouseDragged' is deprecated: first deprecated in macOS 10.12
1444 // 'NSLeftMouseUp' is deprecated: first deprecated in macOS 10.12
1445 // 'NSMouseMoved' is deprecated: first deprecated in macOS 10.12
1446 // 'NSOtherMouseDown' is deprecated: first deprecated in macOS 10.12
1447 // 'NSOtherMouseDragged' is deprecated: first deprecated in macOS 10.12
1448 // 'NSOtherMouseUp' is deprecated: first deprecated in macOS 10.12
1449 // 'NSRightMouseDown' is deprecated: first deprecated in macOS 10.12
1450 // 'NSRightMouseDragged' is deprecated: first deprecated in macOS 10.12
1451 // 'NSRightMouseUp' is deprecated: first deprecated in macOS 10.12
1452 switch( [pCur type
] )
1454 case NSLeftMouseDown
: state
.mnState
|= MOUSE_LEFT
; break;
1455 case NSLeftMouseUp
: break;
1456 case NSRightMouseDown
: state
.mnState
|= MOUSE_RIGHT
; break;
1457 case NSRightMouseUp
: break;
1458 case NSOtherMouseDown
: state
.mnState
|= ([pCur buttonNumber
] == 2) ? MOUSE_MIDDLE
: 0; break;
1459 case NSOtherMouseUp
: break;
1460 case NSMouseMoved
: break;
1461 case NSLeftMouseDragged
: state
.mnState
|= MOUSE_LEFT
; break;
1462 case NSRightMouseDragged
: state
.mnState
|= MOUSE_RIGHT
; break;
1463 case NSOtherMouseDragged
: state
.mnState
|= ([pCur buttonNumber
] == 2) ? MOUSE_MIDDLE
: 0; break;
1466 bMouseEvent
= false;
1469 SAL_WNODEPRECATED_DECLARATIONS_POP
1473 unsigned int nMask
= static_cast<unsigned int>([pCur modifierFlags
]);
1474 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1475 // 'NSAlternateKeyMask' is deprecated: first deprecated in macOS 10.12
1476 // 'NSCommandKeyMask' is deprecated: first deprecated in macOS 10.12
1477 // 'NSControlKeyMask' is deprecated: first deprecated in macOS 10.12
1478 // 'NSShiftKeyMask' is deprecated: first deprecated in macOS 10.12
1479 if( (nMask
& NSShiftKeyMask
) != 0 )
1480 state
.mnState
|= KEY_SHIFT
;
1481 if( (nMask
& NSControlKeyMask
) != 0 )
1482 state
.mnState
|= KEY_MOD3
;
1483 if( (nMask
& NSAlternateKeyMask
) != 0 )
1484 state
.mnState
|= KEY_MOD2
;
1485 if( (nMask
& NSCommandKeyMask
) != 0 )
1486 state
.mnState
|= KEY_MOD1
;
1487 SAL_WNODEPRECATED_DECLARATIONS_POP
1492 // FIXME: replace Carbon by Cocoa
1493 // Cocoa does not have an equivalent for GetCurrentEventButtonState
1494 // and GetCurrentEventKeyModifiers.
1495 // we could try to get away with tracking all events for modifierKeys
1496 // and all mouse events for button state in VCL_NSApplication::sendEvent,
1497 // but it is unclear whether this will get us the same result.
1498 // leave in GetCurrentEventButtonState and GetCurrentEventKeyModifiers for now
1500 // fill in button state
1501 UInt32 nState
= GetCurrentEventButtonState();
1504 state
.mnState
|= MOUSE_LEFT
; // primary button
1506 state
.mnState
|= MOUSE_RIGHT
; // secondary button
1508 state
.mnState
|= MOUSE_MIDDLE
; // tertiary button
1510 // fill in modifier state
1511 nState
= GetCurrentEventKeyModifiers();
1512 if( nState
& shiftKey
)
1513 state
.mnState
|= KEY_SHIFT
;
1514 if( nState
& controlKey
)
1515 state
.mnState
|= KEY_MOD3
;
1516 if( nState
& optionKey
)
1517 state
.mnState
|= KEY_MOD2
;
1518 if( nState
& cmdKey
)
1519 state
.mnState
|= KEY_MOD1
;
1525 KeyIndicatorState
AquaSalFrame::GetIndicatorState()
1527 return KeyIndicatorState::NONE
;
1530 void AquaSalFrame::SimulateKeyPress( sal_uInt16
/*nKeyCode*/ )
1534 bool AquaSalFrame::SetPluginParent( SystemParentData
* )
1536 // plugin parent may be killed unexpectedly by
1537 // plugging process;
1543 bool AquaSalFrame::MapUnicodeToKeyCode( sal_Unicode
, LanguageType
, vcl::KeyCode
& )
1545 // not supported yet
1549 LanguageType
AquaSalFrame::GetInputLanguage()
1552 return LANGUAGE_DONTKNOW
;
1555 void AquaSalFrame::DrawMenuBar()
1559 void AquaSalFrame::SetMenu( SalMenu
* pSalMenu
)
1561 OSX_SALDATA_RUNINMAIN( SetMenu( pSalMenu
) )
1563 AquaSalMenu
* pMenu
= static_cast<AquaSalMenu
*>(pSalMenu
);
1564 SAL_WARN_IF( pMenu
&& !pMenu
->mbMenuBar
, "vcl", "setting non menubar on frame" );
1567 mpMenu
->setMainMenu();
1570 void AquaSalFrame::SetExtendedFrameStyle( SalExtStyle nStyle
)
1574 mnExtStyle
= nStyle
;
1578 OSX_SALDATA_RUNINMAIN( SetExtendedFrameStyle( nStyle
) )
1580 if( (mnExtStyle
& SAL_FRAME_EXT_STYLE_DOCMODIFIED
) != (nStyle
& SAL_FRAME_EXT_STYLE_DOCMODIFIED
) )
1581 [mpNSWindow setDocumentEdited
: (nStyle
& SAL_FRAME_EXT_STYLE_DOCMODIFIED
) ? YES
: NO
];
1583 mnExtStyle
= nStyle
;
1586 SalFrame
* AquaSalFrame::GetParent() const
1591 void AquaSalFrame::SetParent( SalFrame
* pNewParent
)
1593 bool bShown
= mbShown
;
1594 // remove from child list
1597 mpParent
= static_cast<AquaSalFrame
*>(pNewParent
);
1598 // insert to correct parent and paint
1602 void AquaSalFrame::UpdateFrameGeometry()
1604 bool bFirstTime
= (mnTrackingRectTag
== 0);
1605 mbGeometryDidChange
= false;
1610 OSX_SALDATA_RUNINMAIN( UpdateFrameGeometry() )
1612 // keep in mind that view and window coordinates are lower left
1613 // whereas vcl's are upper left
1615 // update screen rect
1616 NSScreen
* pScreen
= [mpNSWindow screen
];
1619 NSRect aNewScreenRect
= [pScreen frame
];
1620 if (bFirstTime
|| !NSEqualRects(maScreenRect
, aNewScreenRect
))
1622 mbGeometryDidChange
= true;
1623 maScreenRect
= aNewScreenRect
;
1625 NSArray
* pScreens
= [NSScreen screens
];
1628 unsigned int nNewDisplayScreenNumber
= [pScreens indexOfObject
: pScreen
];
1629 if (bFirstTime
|| maGeometry
.nDisplayScreenNumber
!= nNewDisplayScreenNumber
)
1631 mbGeometryDidChange
= true;
1632 maGeometry
.nDisplayScreenNumber
= nNewDisplayScreenNumber
;
1637 NSRect aFrameRect
= [mpNSWindow frame
];
1638 NSRect aContentRect
= [NSWindow contentRectForFrameRect
: aFrameRect styleMask
: mnStyleMask
];
1640 NSRect aTrackRect
= { NSZeroPoint
, aContentRect
.size
};
1642 if (bFirstTime
|| !NSEqualRects(maTrackingRect
, aTrackRect
))
1644 mbGeometryDidChange
= true;
1645 maTrackingRect
= aTrackRect
;
1647 // release old track rect
1648 [mpNSView removeTrackingRect
: mnTrackingRectTag
];
1649 // install the new track rect
1650 mnTrackingRectTag
= [mpNSView addTrackingRect
: aTrackRect owner
: mpNSView userData
: nil assumeInside
: NO
];
1653 // convert to vcl convention
1654 CocoaToVCL( aFrameRect
);
1655 CocoaToVCL( aContentRect
);
1657 if (bFirstTime
|| !NSEqualRects(maContentRect
, aContentRect
) || !NSEqualRects(maFrameRect
, aFrameRect
))
1659 mbGeometryDidChange
= true;
1661 maContentRect
= aContentRect
;
1662 maFrameRect
= aFrameRect
;
1664 maGeometry
.nX
= static_cast<int>(aContentRect
.origin
.x
);
1665 maGeometry
.nY
= static_cast<int>(aContentRect
.origin
.y
);
1667 maGeometry
.nLeftDecoration
= static_cast<unsigned int>(aContentRect
.origin
.x
- aFrameRect
.origin
.x
);
1668 maGeometry
.nRightDecoration
= static_cast<unsigned int>((aFrameRect
.origin
.x
+ aFrameRect
.size
.width
) -
1669 (aContentRect
.origin
.x
+ aContentRect
.size
.width
));
1671 maGeometry
.nTopDecoration
= static_cast<unsigned int>(aContentRect
.origin
.y
- aFrameRect
.origin
.y
);
1672 maGeometry
.nBottomDecoration
= static_cast<unsigned int>((aFrameRect
.origin
.y
+ aFrameRect
.size
.height
) -
1673 (aContentRect
.origin
.y
+ aContentRect
.size
.height
));
1675 maGeometry
.nWidth
= static_cast<unsigned int>(aContentRect
.size
.width
);
1676 maGeometry
.nHeight
= static_cast<unsigned int>(aContentRect
.size
.height
);
1680 void AquaSalFrame::CaptureMouse( bool bCapture
)
1683 we'll try to use a pidgin version of capture mouse
1684 on MacOSX (neither carbon nor cocoa) there is a
1685 CaptureMouse equivalent (in Carbon there is TrackMouseLocation
1686 but this is useless to use since it is blocking)
1688 However on cocoa the active frame seems to get mouse events
1689 also outside the window, so we'll try to forward mouse events
1690 to the capture frame in the hope that one of our frames
1693 This will break as soon as the user activates another app, but
1694 a mouse click will normally lead to a release of the mouse anyway.
1696 Let's see how far we get this way. Alternatively we could use one
1697 large overlay window like we did for the carbon implementation,
1698 however that is resource intensive.
1702 s_pCaptureFrame
= this;
1703 else if( ! bCapture
&& s_pCaptureFrame
== this )
1704 s_pCaptureFrame
= nullptr;
1707 void AquaSalFrame::ResetClipRegion()
1709 doResetClipRegion();
1712 void AquaSalFrame::doResetClipRegion()
1717 OSX_SALDATA_RUNINMAIN( ResetClipRegion() )
1719 // release old path and indicate no clipping
1720 CGPathRelease( mrClippingPath
);
1721 mrClippingPath
= nullptr;
1723 if( mpNSView
&& mbShown
)
1724 [mpNSView setNeedsDisplay
: YES
];
1725 [mpNSWindow setOpaque
: YES
];
1726 [mpNSWindow invalidateShadow
];
1729 void AquaSalFrame::BeginSetClipRegion( sal_uInt32 nRects
)
1734 OSX_SALDATA_RUNINMAIN( BeginSetClipRegion( nRects
) )
1737 if( mrClippingPath
)
1739 CGPathRelease( mrClippingPath
);
1740 mrClippingPath
= nullptr;
1743 if( maClippingRects
.size() > SAL_CLIPRECT_COUNT
&& nRects
< maClippingRects
.size() )
1745 std::vector
<CGRect
> aEmptyVec
;
1746 maClippingRects
.swap( aEmptyVec
);
1748 maClippingRects
.clear();
1749 maClippingRects
.reserve( nRects
);
1752 void AquaSalFrame::UnionClipRegion( long nX
, long nY
, long nWidth
, long nHeight
)
1754 // #i113170# may not be the main thread if called from UNO API
1755 SalData::ensureThreadAutoreleasePool();
1757 if( nWidth
&& nHeight
)
1759 NSRect aRect
= { { static_cast<CGFloat
>(nX
), static_cast<CGFloat
>(nY
) }, { static_cast<CGFloat
>(nWidth
), static_cast<CGFloat
>(nHeight
) } };
1760 VCLToCocoa( aRect
, false );
1761 maClippingRects
.push_back( CGRectMake(aRect
.origin
.x
, aRect
.origin
.y
, aRect
.size
.width
, aRect
.size
.height
) );
1765 void AquaSalFrame::EndSetClipRegion()
1770 OSX_SALDATA_RUNINMAIN( EndSetClipRegion() )
1772 if( ! maClippingRects
.empty() )
1774 mrClippingPath
= CGPathCreateMutable();
1775 CGPathAddRects( mrClippingPath
, nullptr, maClippingRects
.data(), maClippingRects
.size() );
1777 if( mpNSView
&& mbShown
)
1778 [mpNSView setNeedsDisplay
: YES
];
1779 [mpNSWindow setOpaque
: (mrClippingPath
!= nullptr) ? NO
: YES
];
1780 [mpNSWindow setBackgroundColor
: [NSColor clearColor
]];
1781 // shadow is invalidated when view gets drawn again
1784 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */