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 <tools/long.hxx>
26 #include <o3tl/safeint.hxx>
27 #include <osl/diagnose.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>
51 #include <objc/objc-runtime.h>
53 // FIXME: move theming code to salnativewidgets.cxx
54 #include <Carbon/Carbon.h>
55 #include <quartz/CGHelpers.hxx>
59 const int nMinBlinkCursorDelay
= 500;
61 AquaSalFrame
* AquaSalFrame::s_pCaptureFrame
= nullptr;
63 AquaSalFrame::AquaSalFrame( SalFrame
* pParent
, SalFrameStyleFlags salFrameStyle
) :
74 mbFullScreen( false ),
79 mbPresentation( false ),
80 mnStyle( salFrameStyle
),
83 mnLastModifierFlags( 0 ),
86 mePointerStyle( PointerStyle::Arrow
),
87 mnTrackingRectTag( 0 ),
88 mrClippingPath( nullptr ),
89 mnICOptions( InputContextFlags::NONE
),
90 mnBlinkCursorDelay( nMinBlinkCursorDelay
),
93 mpParent
= dynamic_cast<AquaSalFrame
*>(pParent
);
97 SalData
* pSalData
= GetSalData();
98 pSalData
->mpInstance
->insertFrame( this );
99 NSUserDefaults
*userDefaults
= [NSUserDefaults standardUserDefaults
];
101 // tdf#150177 Limit minimum blink cursor rate
102 // This bug occurs when the values for NSTextInsertionPointBlinkPeriodOn or
103 // NSTextInsertionPointBlinkPeriodOff are set to zero or close to zero.
104 // LibreOffice becomes very sluggish opening documents when either is set
105 // at 100 milliseconds or less so set the blink rate to the maximum of
106 // nMinBlinkCursorDelay, NSTextInsertionPointBlinkPeriodOn, and
107 // NSTextInsertionPointBlinkPeriodOff.
108 mnBlinkCursorDelay
= nMinBlinkCursorDelay
;
109 if (userDefaults
!= nil
)
111 id setting
= [userDefaults objectForKey
: @
"NSTextInsertionPointBlinkPeriodOn"];
112 if (setting
&& [setting isKindOfClass
:[NSNumber
class]])
113 mnBlinkCursorDelay
= std::max(mnBlinkCursorDelay
, [setting intValue
]);
115 setting
= [userDefaults objectForKey
: @
"NSTextInsertionPointBlinkPeriodOff"];
116 if (setting
&& [setting isKindOfClass
:[NSNumber
class]])
117 mnBlinkCursorDelay
= std::max(mnBlinkCursorDelay
, [setting intValue
]);
121 AquaSalFrame::~AquaSalFrame()
124 doShowFullScreen(false, maGeometry
.screen());
126 assert( GetSalData()->mpInstance
->IsMainThread() );
128 // if the frame is destroyed and has the current menubar
129 // set the default menubar
130 if( mpMenu
&& mpMenu
->mbMenuBar
&& AquaSalMenu::pCurrentMenuBar
== mpMenu
)
131 AquaSalMenu::setDefaultMenu();
133 // cleanup clipping stuff
136 [SalFrameView unsetMouseFrame
: this];
138 SalData
* pSalData
= GetSalData();
139 pSalData
->mpInstance
->eraseFrame( this );
140 pSalData
->maPresentationFrames
.remove( this );
142 SAL_WARN_IF( this == s_pCaptureFrame
, "vcl", "capture frame destroyed" );
143 if( this == s_pCaptureFrame
)
144 s_pCaptureFrame
= nullptr;
148 if( mpDockMenuEntry
)
150 NSMenu
* pDock
= AquaSalInstance::GetDynamicDockMenu();
151 // life cycle comment: the menu has ownership of the item, so no release
152 [pDock removeItem
: mpDockMenuEntry
];
153 if ([pDock numberOfItems
] != 0
154 && [[pDock itemAtIndex
: 0] isSeparatorItem
])
156 [pDock removeItemAtIndex
: 0];
160 [AquaA11yFactory revokeView
: mpNSView
];
164 [mpNSWindow release
];
167 void AquaSalFrame::initWindowAndView()
169 OSX_SALDATA_RUNINMAIN( initWindowAndView() )
171 // initialize mirroring parameters
172 // FIXME: screens changing
173 NSScreen
* pNSScreen
= [mpNSWindow screen
];
174 if( pNSScreen
== nil
)
175 pNSScreen
= [NSScreen mainScreen
];
176 maScreenRect
= [pNSScreen frame
];
178 // calculate some default geometry
179 NSRect aVisibleRect
= [pNSScreen visibleFrame
];
180 CocoaToVCL( aVisibleRect
);
182 maGeometry
.setX(static_cast<sal_Int32
>(aVisibleRect
.origin
.x
+ aVisibleRect
.size
.width
/ 10));
183 maGeometry
.setY(static_cast<sal_Int32
>(aVisibleRect
.origin
.y
+ aVisibleRect
.size
.height
/ 10));
184 maGeometry
.setWidth(static_cast<sal_uInt32
>(aVisibleRect
.size
.width
* 0.8));
185 maGeometry
.setHeight(static_cast<sal_uInt32
>(aVisibleRect
.size
.height
* 0.8));
187 // calculate style mask
188 if( (mnStyle
& SalFrameStyleFlags::FLOAT
) ||
189 (mnStyle
& SalFrameStyleFlags::OWNERDRAWDECORATION
) )
190 mnStyleMask
= NSWindowStyleMaskBorderless
;
191 else if( mnStyle
& SalFrameStyleFlags::DEFAULT
)
193 mnStyleMask
= NSWindowStyleMaskTitled
|
194 NSWindowStyleMaskMiniaturizable
|
195 NSWindowStyleMaskResizable
|
196 NSWindowStyleMaskClosable
;
197 // make default window "maximized"
198 maGeometry
.setX(static_cast<sal_Int32
>(aVisibleRect
.origin
.x
));
199 maGeometry
.setY(static_cast<sal_Int32
>(aVisibleRect
.origin
.y
));
200 maGeometry
.setWidth(static_cast<sal_uInt32
>(aVisibleRect
.size
.width
));
201 maGeometry
.setHeight(static_cast<sal_uInt32
>(aVisibleRect
.size
.height
));
202 mbPositioned
= mbSized
= true;
206 if( mnStyle
& SalFrameStyleFlags::MOVEABLE
)
208 mnStyleMask
|= NSWindowStyleMaskTitled
;
209 if( mpParent
== nullptr )
210 mnStyleMask
|= NSWindowStyleMaskMiniaturizable
;
212 if( mnStyle
& SalFrameStyleFlags::SIZEABLE
)
213 mnStyleMask
|= NSWindowStyleMaskResizable
;
214 if( mnStyle
& SalFrameStyleFlags::CLOSEABLE
)
215 mnStyleMask
|= NSWindowStyleMaskClosable
;
216 // documentation says anything other than NSWindowStyleMaskBorderless (=0)
217 // should also include NSWindowStyleMaskTitled;
218 if( mnStyleMask
!= 0 )
219 mnStyleMask
|= NSWindowStyleMaskTitled
;
222 if (Application::IsBitmapRendering())
225 // #i91990# support GUI-less (daemon) execution
228 mpNSWindow
= [[SalFrameWindow alloc
] initWithSalFrame
: this];
229 mpNSView
= [[SalFrameView alloc
] initWithSalFrame
: this];
236 if( mnStyle
& SalFrameStyleFlags::TOOLTIP
)
237 [mpNSWindow setIgnoresMouseEvents
: YES
];
239 [mpNSWindow setAcceptsMouseMovedEvents
: YES
];
240 [mpNSWindow setHasShadow
: YES
];
242 [mpNSWindow setDelegate
: static_cast<id
<NSWindowDelegate
> >(mpNSWindow
)];
244 [mpNSWindow setRestorable
:NO
];
245 const NSRect aRect
= { NSZeroPoint
, NSMakeSize(maGeometry
.width(), maGeometry
.height()) };
246 mnTrackingRectTag
= [mpNSView addTrackingRect
: aRect owner
: mpNSView userData
: nil assumeInside
: NO
];
248 maSysData
.mpNSView
= mpNSView
;
250 UpdateFrameGeometry();
252 [mpNSWindow setContentView
: mpNSView
];
255 void AquaSalFrame::CocoaToVCL( NSRect
& io_rRect
, bool bRelativeToScreen
)
257 if( bRelativeToScreen
)
258 io_rRect
.origin
.y
= maScreenRect
.size
.height
- (io_rRect
.origin
.y
+io_rRect
.size
.height
);
260 io_rRect
.origin
.y
= maGeometry
.height() - (io_rRect
.origin
.y
+io_rRect
.size
.height
);
263 void AquaSalFrame::VCLToCocoa( NSRect
& io_rRect
, bool bRelativeToScreen
)
265 if( bRelativeToScreen
)
266 io_rRect
.origin
.y
= maScreenRect
.size
.height
- (io_rRect
.origin
.y
+io_rRect
.size
.height
);
268 io_rRect
.origin
.y
= maGeometry
.height() - (io_rRect
.origin
.y
+io_rRect
.size
.height
);
271 void AquaSalFrame::CocoaToVCL( NSPoint
& io_rPoint
, bool bRelativeToScreen
)
273 if( bRelativeToScreen
)
274 io_rPoint
.y
= maScreenRect
.size
.height
- io_rPoint
.y
;
276 io_rPoint
.y
= maGeometry
.height() - io_rPoint
.y
;
279 void AquaSalFrame::VCLToCocoa( NSPoint
& io_rPoint
, bool bRelativeToScreen
)
281 if( bRelativeToScreen
)
282 io_rPoint
.y
= maScreenRect
.size
.height
- io_rPoint
.y
;
284 io_rPoint
.y
= maGeometry
.height() - io_rPoint
.y
;
287 void AquaSalFrame::screenParametersChanged()
289 OSX_SALDATA_RUNINMAIN( screenParametersChanged() )
291 sal::aqua::resetWindowScaling();
293 UpdateFrameGeometry();
296 mpGraphics
->updateResolution();
298 if (!mbGeometryDidChange
)
301 CallCallback( SalEvent::DisplayChanged
, nullptr );
304 SalGraphics
* AquaSalFrame::AcquireGraphics()
311 mpGraphics
= new AquaSalGraphics
;
312 mpGraphics
->SetWindowGraphics( this );
319 void AquaSalFrame::ReleaseGraphics( SalGraphics
*pGraphics
)
321 SAL_WARN_IF( pGraphics
!= mpGraphics
, "vcl", "graphics released on wrong frame" );
325 bool AquaSalFrame::PostEvent(std::unique_ptr
<ImplSVEvent
> pData
)
327 GetSalData()->mpInstance
->PostEvent( this, pData
.release(), SalEvent::UserEvent
);
331 void AquaSalFrame::SetTitle(const OUString
& rTitle
)
336 OSX_SALDATA_RUNINMAIN( SetTitle(rTitle
) )
338 // #i113170# may not be the main thread if called from UNO API
339 SalData::ensureThreadAutoreleasePool();
341 NSString
* pTitle
= CreateNSString( rTitle
);
342 [mpNSWindow setTitle
: pTitle
];
344 // create an entry in the dock menu
345 const SalFrameStyleFlags nAppWindowStyle
= SalFrameStyleFlags::CLOSEABLE
| SalFrameStyleFlags::MOVEABLE
;
346 if( mpParent
== nullptr &&
347 (mnStyle
& nAppWindowStyle
) == nAppWindowStyle
)
349 if( mpDockMenuEntry
== nullptr )
351 NSMenu
* pDock
= AquaSalInstance::GetDynamicDockMenu();
353 if ([pDock numberOfItems
] != 0) {
354 NSMenuItem
* pTopItem
= [pDock itemAtIndex
: 0];
355 if ( [pTopItem hasSubmenu
] )
356 [pDock insertItem
: [NSMenuItem separatorItem
] atIndex
: 0];
359 mpDockMenuEntry
= [pDock insertItemWithTitle
: pTitle
360 action
: @
selector(dockMenuItemTriggered
:)
363 [mpDockMenuEntry setTarget
: mpNSWindow
];
365 // TODO: image (either the generic window image or an icon
366 // check mark (for "main" window ?)
369 [mpDockMenuEntry setTitle
: pTitle
];
376 void AquaSalFrame::SetIcon( sal_uInt16
)
380 void AquaSalFrame::SetRepresentedURL( const OUString
& i_rDocURL
)
382 OSX_SALDATA_RUNINMAIN( SetRepresentedURL( i_rDocURL
) )
384 if( comphelper::isFileUrl(i_rDocURL
) )
387 osl_getSystemPathFromFileURL( i_rDocURL
.pData
, &aSysPath
.pData
);
388 NSString
* pStr
= CreateNSString( aSysPath
);
392 [mpNSWindow setRepresentedFilename
: pStr
];
397 void AquaSalFrame::initShow()
399 OSX_SALDATA_RUNINMAIN( initShow() )
402 if( ! mbPositioned
&& ! mbFullScreen
)
404 tools::Rectangle aScreenRect
;
405 GetWorkArea( aScreenRect
);
406 if( mpParent
) // center relative to parent
409 tools::Long nNewX
= mpParent
->maGeometry
.x() + (static_cast<tools::Long
>(mpParent
->maGeometry
.width()) - static_cast<tools::Long
>(maGeometry
.width())) / 2;
410 if( nNewX
< aScreenRect
.Left() )
411 nNewX
= aScreenRect
.Left();
412 if (static_cast<tools::Long
>(nNewX
+ maGeometry
.width()) > aScreenRect
.Right())
413 nNewX
= aScreenRect
.Right() - maGeometry
.width() - 1;
414 tools::Long nNewY
= mpParent
->maGeometry
.y() + (static_cast<tools::Long
>(mpParent
->maGeometry
.height()) - static_cast<tools::Long
>(maGeometry
.height())) / 2;
415 if( nNewY
< aScreenRect
.Top() )
416 nNewY
= aScreenRect
.Top();
417 if( nNewY
> aScreenRect
.Bottom() )
418 nNewY
= aScreenRect
.Bottom() - maGeometry
.height() - 1;
419 SetPosSize( nNewX
- mpParent
->maGeometry
.x(),
420 nNewY
- mpParent
->maGeometry
.y(),
421 0, 0, SAL_FRAME_POSSIZE_X
| SAL_FRAME_POSSIZE_Y
);
423 else if( ! (mnStyle
& SalFrameStyleFlags::SIZEABLE
) )
426 tools::Long nNewX
= (aScreenRect
.GetWidth() - maGeometry
.width()) / 2;
427 tools::Long nNewY
= (aScreenRect
.GetHeight() - maGeometry
.height()) / 2;
428 SetPosSize( nNewX
, nNewY
, 0, 0, SAL_FRAME_POSSIZE_X
| SAL_FRAME_POSSIZE_Y
);
432 // make sure the view is present in the wrapper list before any children receive focus
433 [AquaA11yFactory registerView
: mpNSView
];
436 void AquaSalFrame::SendPaintEvent( const tools::Rectangle
* pRect
)
438 OSX_SALDATA_RUNINMAIN( SendPaintEvent( pRect
) )
440 SalPaintEvent
aPaintEvt(0, 0, maGeometry
.width(), maGeometry
.height(), true);
443 aPaintEvt
.mnBoundX
= pRect
->Left();
444 aPaintEvt
.mnBoundY
= pRect
->Top();
445 aPaintEvt
.mnBoundWidth
= pRect
->GetWidth();
446 aPaintEvt
.mnBoundHeight
= pRect
->GetHeight();
449 CallCallback(SalEvent::Paint
, &aPaintEvt
);
452 void AquaSalFrame::Show(bool bVisible
, bool bNoActivate
)
457 OSX_SALDATA_RUNINMAIN( Show(bVisible
, bNoActivate
) )
459 // tdf#152173 Don't display tooltip windows when application is inactive
460 // Starting with macOS 13 Ventura, inactive applications receive mouse
461 // move events so when LibreOffice is inactive, a mouse move event causes
462 // a tooltip to be displayed. Since the tooltip window is attached to its
463 // parent window (to ensure that the tooltip is above the parent window),
464 // displaying a tooltip pulls the parent window in front of the windows
465 // of all other inactive applications.
466 // Also, don't display tooltips when mousing over non-key windows even if
467 // the application is active as the tooltip window will pull the non-key
468 // window in front of the key window.
469 if (bVisible
&& (mnStyle
& SalFrameStyleFlags::TOOLTIP
))
471 if (![NSApp isActive
])
476 // tdf#157565 show tooltip if any parent window is the key window
477 bool bKeyWindowFound
= false;
478 NSWindow
*pParent
= mpParent
->mpNSWindow
;
481 if ([pParent isKeyWindow
])
483 bKeyWindowFound
= true;
486 pParent
= [pParent parentWindow
];
488 if (!bKeyWindowFound
)
499 CallCallback(SalEvent::Resize
, nullptr);
500 // trigger filling our backbuffer
503 if( bNoActivate
|| [mpNSWindow canBecomeKeyWindow
] == NO
)
504 [mpNSWindow orderFront
: NSApp
];
506 [mpNSWindow makeKeyAndOrderFront
: NSApp
];
510 /* #i92674# #i96433# we do not want an invisible parent to show up (which adding a visible
511 child implicitly does). However we also do not want a parentless toolbar.
513 HACK: try to decide when we should not insert a child to its parent
514 floaters and ownerdraw windows have not yet shown up in cases where
515 we don't want the parent to become visible
517 if( mpParent
->mbShown
|| (mnStyle
& (SalFrameStyleFlags::OWNERDRAWDECORATION
| SalFrameStyleFlags::FLOAT
) ) )
519 [mpParent
->mpNSWindow addChildWindow
: mpNSWindow ordered
: NSWindowAbove
];
524 [mpNSWindow makeMainWindow
];
528 // if the frame holding the current menubar gets hidden
529 // show the default menubar
530 if( mpMenu
&& mpMenu
->mbMenuBar
&& AquaSalMenu::pCurrentMenuBar
== mpMenu
)
531 AquaSalMenu::setDefaultMenu();
533 // #i90440# #i94443# work around the focus going back to some other window
534 // if a child gets hidden for a parent window
535 if( mpParent
&& mpParent
->mbShown
&& [mpNSWindow isKeyWindow
] )
536 [mpParent
->mpNSWindow makeKeyAndOrderFront
: NSApp
];
538 [SalFrameView unsetMouseFrame
: this];
539 if( mpParent
&& [mpNSWindow parentWindow
] == mpParent
->mpNSWindow
)
540 [mpParent
->mpNSWindow removeChildWindow
: mpNSWindow
];
542 [mpNSWindow orderOut
: NSApp
];
546 void AquaSalFrame::SetMinClientSize( tools::Long nWidth
, tools::Long nHeight
)
548 OSX_SALDATA_RUNINMAIN( SetMinClientSize( nWidth
, nHeight
) )
551 mnMinHeight
= nHeight
;
555 // Always add the decoration as the dimension concerns only
556 // the content rectangle
557 nWidth
+= maGeometry
.leftDecoration() + maGeometry
.rightDecoration();
558 nHeight
+= maGeometry
.topDecoration() + maGeometry
.bottomDecoration();
560 NSSize aSize
= { static_cast<CGFloat
>(nWidth
), static_cast<CGFloat
>(nHeight
) };
562 // Size of full window (content+structure) although we only
563 // have the client size in arguments
564 [mpNSWindow setMinSize
: aSize
];
568 void AquaSalFrame::SetMaxClientSize( tools::Long nWidth
, tools::Long nHeight
)
570 OSX_SALDATA_RUNINMAIN( SetMaxClientSize( nWidth
, nHeight
) )
573 mnMaxHeight
= nHeight
;
577 // Always add the decoration as the dimension concerns only
578 // the content rectangle
579 nWidth
+= maGeometry
.leftDecoration() + maGeometry
.rightDecoration();
580 nHeight
+= maGeometry
.topDecoration() + maGeometry
.bottomDecoration();
582 // Carbon windows can't have a size greater than 32767x32767
583 if (nWidth
>32767) nWidth
=32767;
584 if (nHeight
>32767) nHeight
=32767;
586 NSSize aSize
= { static_cast<CGFloat
>(nWidth
), static_cast<CGFloat
>(nHeight
) };
588 // Size of full window (content+structure) although we only
589 // have the client size in arguments
590 [mpNSWindow setMaxSize
: aSize
];
594 void AquaSalFrame::GetClientSize( tools::Long
& rWidth
, tools::Long
& rHeight
)
596 if (mbShown
|| mbInitShow
|| Application::IsBitmapRendering())
598 rWidth
= maGeometry
.width();
599 rHeight
= maGeometry
.height();
608 SalEvent
AquaSalFrame::PreparePosSize(tools::Long nX
, tools::Long nY
, tools::Long nWidth
, tools::Long nHeight
, sal_uInt16 nFlags
)
610 SalEvent nEvent
= SalEvent::NONE
;
611 assert(mpNSWindow
|| Application::IsBitmapRendering());
613 if (nFlags
& (SAL_FRAME_POSSIZE_X
| SAL_FRAME_POSSIZE_Y
))
616 nEvent
= SalEvent::Move
;
619 if (nFlags
& (SAL_FRAME_POSSIZE_WIDTH
| SAL_FRAME_POSSIZE_HEIGHT
))
622 nEvent
= (nEvent
== SalEvent::Move
) ? SalEvent::MoveResize
: SalEvent::Resize
;
625 if (Application::IsBitmapRendering())
627 if (nFlags
& SAL_FRAME_POSSIZE_X
)
629 if (nFlags
& SAL_FRAME_POSSIZE_Y
)
631 if (nFlags
& SAL_FRAME_POSSIZE_WIDTH
)
633 maGeometry
.setWidth(nWidth
);
634 if (mnMaxWidth
> 0 && maGeometry
.width() > mnMaxWidth
)
635 maGeometry
.setWidth(mnMaxWidth
);
636 if (mnMinWidth
> 0 && maGeometry
.width() < mnMinWidth
)
637 maGeometry
.setWidth(mnMinWidth
);
639 if (nFlags
& SAL_FRAME_POSSIZE_HEIGHT
)
641 maGeometry
.setHeight(nHeight
);
642 if (mnMaxHeight
> 0 && maGeometry
.height() > mnMaxHeight
)
643 maGeometry
.setHeight(mnMaxHeight
);
644 if (mnMinHeight
> 0 && maGeometry
.height() < mnMinHeight
)
645 maGeometry
.setHeight(mnMinHeight
);
647 if (nEvent
!= SalEvent::NONE
)
648 CallCallback(nEvent
, nullptr);
654 void AquaSalFrame::SetWindowState(const vcl::WindowData
* pState
)
656 if (!mpNSWindow
&& !Application::IsBitmapRendering())
659 OSX_SALDATA_RUNINMAIN( SetWindowState( pState
) )
661 sal_uInt16 nFlags
= 0;
662 nFlags
|= ((pState
->mask() & vcl::WindowDataMask::X
) ? SAL_FRAME_POSSIZE_X
: 0);
663 nFlags
|= ((pState
->mask() & vcl::WindowDataMask::Y
) ? SAL_FRAME_POSSIZE_Y
: 0);
664 nFlags
|= ((pState
->mask() & vcl::WindowDataMask::Width
) ? SAL_FRAME_POSSIZE_WIDTH
: 0);
665 nFlags
|= ((pState
->mask() & vcl::WindowDataMask::Height
) ? SAL_FRAME_POSSIZE_HEIGHT
: 0);
667 SalEvent nEvent
= PreparePosSize(pState
->x(), pState
->y(), pState
->width(), pState
->height(), nFlags
);
668 if (Application::IsBitmapRendering())
672 NSRect aStateRect
= [mpNSWindow frame
];
673 aStateRect
= [NSWindow contentRectForFrameRect
: aStateRect styleMask
: mnStyleMask
];
674 CocoaToVCL(aStateRect
);
675 if (pState
->mask() & vcl::WindowDataMask::X
)
676 aStateRect
.origin
.x
= float(pState
->x());
677 if (pState
->mask() & vcl::WindowDataMask::Y
)
678 aStateRect
.origin
.y
= float(pState
->y());
679 if (pState
->mask() & vcl::WindowDataMask::Width
)
680 aStateRect
.size
.width
= float(pState
->width());
681 if (pState
->mask() & vcl::WindowDataMask::Height
)
682 aStateRect
.size
.height
= float(pState
->height());
683 VCLToCocoa(aStateRect
);
684 aStateRect
= [NSWindow frameRectForContentRect
: aStateRect styleMask
: mnStyleMask
];
685 [mpNSWindow setFrame
: aStateRect display
: NO
];
687 if (pState
->state() == vcl::WindowState::Minimized
)
688 [mpNSWindow miniaturize
: NSApp
];
689 else if ([mpNSWindow isMiniaturized
])
690 [mpNSWindow deminiaturize
: NSApp
];
692 /* ZOOMED is not really maximized (actually it toggles between a user set size and
693 the program specified one), but comes closest since the default behavior is
694 "maximized" if the user did not intervene
696 if (pState
->state() == vcl::WindowState::Maximized
)
698 if (![mpNSWindow isZoomed
])
699 [mpNSWindow zoom
: NSApp
];
703 if ([mpNSWindow isZoomed
])
704 [mpNSWindow zoom
: NSApp
];
708 UpdateFrameGeometry();
710 // send event that we were moved/sized
711 if( nEvent
!= SalEvent::NONE
)
712 CallCallback( nEvent
, nullptr );
716 // trigger filling our backbuffer
719 // tell the system the views need to be updated
720 [mpNSWindow display
];
724 bool AquaSalFrame::GetWindowState(vcl::WindowData
* pState
)
728 if (Application::IsBitmapRendering())
730 pState
->setMask(vcl::WindowDataMask::PosSizeState
);
731 pState
->setPosSize(maGeometry
.posSize());
732 pState
->setState(vcl::WindowState::Normal
);
738 OSX_SALDATA_RUNINMAIN_UNION( GetWindowState( pState
), boolean
)
740 pState
->setMask(vcl::WindowDataMask::PosSizeState
);
742 NSRect aStateRect
= [mpNSWindow frame
];
743 aStateRect
= [NSWindow contentRectForFrameRect
: aStateRect styleMask
: mnStyleMask
];
744 CocoaToVCL( aStateRect
);
745 pState
->setX(static_cast<sal_Int32
>(aStateRect
.origin
.x
));
746 pState
->setY(static_cast<sal_Int32
>(aStateRect
.origin
.y
));
747 pState
->setWidth(static_cast<sal_uInt32
>(aStateRect
.size
.width
));
748 pState
->setHeight(static_cast<sal_uInt32
>(aStateRect
.size
.height
));
750 if( [mpNSWindow isMiniaturized
] )
751 pState
->setState(vcl::WindowState::Minimized
);
752 else if( ! [mpNSWindow isZoomed
] )
753 pState
->setState(vcl::WindowState::Normal
);
755 pState
->setState(vcl::WindowState::Maximized
);
760 void AquaSalFrame::SetScreenNumber(unsigned int nScreen
)
765 OSX_SALDATA_RUNINMAIN( SetScreenNumber( nScreen
) )
767 NSArray
* pScreens
= [NSScreen screens
];
768 NSScreen
* pScreen
= nil
;
769 if( pScreens
&& nScreen
< [pScreens count
] )
771 // get new screen frame
772 pScreen
= [pScreens objectAtIndex
: nScreen
];
773 NSRect aNewScreen
= [pScreen frame
];
775 // get current screen frame
776 pScreen
= [mpNSWindow screen
];
779 NSRect aCurScreen
= [pScreen frame
];
780 if( aCurScreen
.origin
.x
!= aNewScreen
.origin
.x
||
781 aCurScreen
.origin
.y
!= aNewScreen
.origin
.y
)
783 NSRect aFrameRect
= [mpNSWindow frame
];
784 aFrameRect
.origin
.x
+= aNewScreen
.origin
.x
- aCurScreen
.origin
.x
;
785 aFrameRect
.origin
.y
+= aNewScreen
.origin
.y
- aCurScreen
.origin
.y
;
786 [mpNSWindow setFrame
: aFrameRect display
: NO
];
787 UpdateFrameGeometry();
793 void AquaSalFrame::SetApplicationID( const OUString
&/*rApplicationID*/ )
797 void AquaSalFrame::ShowFullScreen( bool bFullScreen
, sal_Int32 nDisplay
)
799 doShowFullScreen(bFullScreen
, nDisplay
);
802 void AquaSalFrame::doShowFullScreen( bool bFullScreen
, sal_Int32 nDisplay
)
806 if (Application::IsBitmapRendering() && bFullScreen
)
807 SetPosSize(0, 0, 1024, 768, SAL_FRAME_POSSIZE_WIDTH
| SAL_FRAME_POSSIZE_HEIGHT
);
811 SAL_INFO("vcl.osx", __func__
<< ": mbFullScreen=" << mbFullScreen
<< ", bFullScreen=" << bFullScreen
);
813 if( mbFullScreen
== bFullScreen
)
816 OSX_SALDATA_RUNINMAIN( ShowFullScreen( bFullScreen
, nDisplay
) )
818 mbFullScreen
= bFullScreen
;
822 // hide the dock and the menubar if we are on the menu screen
823 // which is always on index 0 according to documentation
824 bool bHideMenu
= (nDisplay
== 0);
826 NSRect aNewContentRect
= NSZeroRect
;
827 // get correct screen
828 NSScreen
* pScreen
= nil
;
829 NSArray
* pScreens
= [NSScreen screens
];
832 if( nDisplay
>= 0 && o3tl::make_unsigned(nDisplay
) < [pScreens count
] )
833 pScreen
= [pScreens objectAtIndex
: nDisplay
];
836 // this means span all screens
838 NSEnumerator
* pEnum
= [pScreens objectEnumerator
];
839 while( (pScreen
= [pEnum nextObject
]) != nil
)
841 NSRect aScreenRect
= [pScreen frame
];
842 if( aScreenRect
.origin
.x
< aNewContentRect
.origin
.x
)
844 aNewContentRect
.size
.width
+= aNewContentRect
.origin
.x
- aScreenRect
.origin
.x
;
845 aNewContentRect
.origin
.x
= aScreenRect
.origin
.x
;
847 if( aScreenRect
.origin
.y
< aNewContentRect
.origin
.y
)
849 aNewContentRect
.size
.height
+= aNewContentRect
.origin
.y
- aScreenRect
.origin
.y
;
850 aNewContentRect
.origin
.y
= aScreenRect
.origin
.y
;
852 if( aScreenRect
.origin
.x
+ aScreenRect
.size
.width
> aNewContentRect
.origin
.x
+ aNewContentRect
.size
.width
)
853 aNewContentRect
.size
.width
= aScreenRect
.origin
.x
+ aScreenRect
.size
.width
- aNewContentRect
.origin
.x
;
854 if( aScreenRect
.origin
.y
+ aScreenRect
.size
.height
> aNewContentRect
.origin
.y
+ aNewContentRect
.size
.height
)
855 aNewContentRect
.size
.height
= aScreenRect
.origin
.y
+ aScreenRect
.size
.height
- aNewContentRect
.origin
.y
;
859 if( aNewContentRect
.size
.width
== 0 && aNewContentRect
.size
.height
== 0 )
862 pScreen
= [mpNSWindow screen
];
864 pScreen
= [NSScreen mainScreen
];
866 aNewContentRect
= [pScreen frame
];
870 [NSMenu setMenuBarVisible
:NO
];
872 maFullScreenRect
= [mpNSWindow frame
];
874 [mpNSWindow setFrame
: [NSWindow frameRectForContentRect
: aNewContentRect styleMask
: mnStyleMask
] display
: mbShown
? YES
: NO
];
878 [mpNSWindow setFrame
: maFullScreenRect display
: mbShown
? YES
: NO
];
880 // show the dock and the menubar
881 [NSMenu setMenuBarVisible
:YES
];
884 UpdateFrameGeometry();
887 CallCallback(SalEvent::MoveResize
, nullptr);
889 // trigger filling our backbuffer
894 void AquaSalFrame::StartPresentation( bool bStart
)
899 OSX_SALDATA_RUNINMAIN( StartPresentation( bStart
) )
903 GetSalData()->maPresentationFrames
.push_back( this );
904 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep
,
905 kIOPMAssertionLevelOn
,
906 CFSTR("LibreOffice presentation running"),
908 [mpNSWindow setLevel
: NSPopUpMenuWindowLevel
];
910 [mpNSWindow makeMainWindow
];
914 GetSalData()->maPresentationFrames
.remove( this );
915 IOPMAssertionRelease(mnAssertionID
);
916 [mpNSWindow setLevel
: NSNormalWindowLevel
];
920 void AquaSalFrame::SetAlwaysOnTop( bool )
924 void AquaSalFrame::ToTop(SalFrameToTop nFlags
)
929 OSX_SALDATA_RUNINMAIN( ToTop( nFlags
) )
931 if( ! (nFlags
& SalFrameToTop::RestoreWhenMin
) )
933 if( ! [mpNSWindow isVisible
] || [mpNSWindow isMiniaturized
] )
936 if( nFlags
& SalFrameToTop::GrabFocus
)
937 [mpNSWindow makeKeyAndOrderFront
: NSApp
];
939 [mpNSWindow orderFront
: NSApp
];
942 NSCursor
* AquaSalFrame::getCurrentCursor()
944 OSX_SALDATA_RUNINMAIN_POINTER( getCurrentCursor(), NSCursor
* )
946 NSCursor
* pCursor
= nil
;
947 switch( mePointerStyle
)
949 case PointerStyle::Text
: pCursor
= [NSCursor IBeamCursor
]; break;
950 case PointerStyle::Cross
: pCursor
= [NSCursor crosshairCursor
]; break;
951 case PointerStyle::Hand
:
952 case PointerStyle::Move
: pCursor
= [NSCursor openHandCursor
]; break;
953 case PointerStyle::NSize
: pCursor
= [NSCursor resizeUpCursor
]; break;
954 case PointerStyle::SSize
: pCursor
= [NSCursor resizeDownCursor
]; break;
955 case PointerStyle::ESize
: pCursor
= [NSCursor resizeRightCursor
]; break;
956 case PointerStyle::WSize
: pCursor
= [NSCursor resizeLeftCursor
]; break;
957 case PointerStyle::Arrow
: pCursor
= [NSCursor arrowCursor
]; break;
958 case PointerStyle::VSplit
:
959 case PointerStyle::VSizeBar
:
960 case PointerStyle::WindowNSize
:
961 case PointerStyle::WindowSSize
:
962 pCursor
= [NSCursor resizeUpDownCursor
]; break;
963 case PointerStyle::HSplit
:
964 case PointerStyle::HSizeBar
:
965 case PointerStyle::WindowESize
:
966 case PointerStyle::WindowWSize
:
967 pCursor
= [NSCursor resizeLeftRightCursor
]; break;
968 case PointerStyle::RefHand
: pCursor
= [NSCursor pointingHandCursor
]; break;
971 pCursor
= GetSalData()->getCursor( mePointerStyle
);
974 assert( false && "unmapped cursor" );
975 pCursor
= [NSCursor arrowCursor
];
982 void AquaSalFrame::SetPointer( PointerStyle ePointerStyle
)
986 if( ePointerStyle
== mePointerStyle
)
989 OSX_SALDATA_RUNINMAIN( SetPointer( ePointerStyle
) )
991 mePointerStyle
= ePointerStyle
;
993 [mpNSWindow invalidateCursorRectsForView
: mpNSView
];
996 void AquaSalFrame::SetPointerPos( tools::Long nX
, tools::Long nY
)
998 OSX_SALDATA_RUNINMAIN( SetPointerPos( nX
, nY
) )
1000 // FIXME: use Cocoa functions
1001 // FIXME: multiscreen support
1002 CGPoint aPoint
= { static_cast<CGFloat
>(nX
+ maGeometry
.x()), static_cast<CGFloat
>(nY
+ maGeometry
.y()) };
1003 CGDirectDisplayID mainDisplayID
= CGMainDisplayID();
1004 CGDisplayMoveCursorToPoint( mainDisplayID
, aPoint
);
1007 void AquaSalFrame::Flush()
1009 if( !(mbGraphics
&& mpGraphics
&& mpNSView
&& mbShown
) )
1012 OSX_SALDATA_RUNINMAIN( Flush() )
1014 [mpNSView setNeedsDisplay
: YES
];
1016 // outside of the application's event loop (e.g. IntroWindow)
1017 // nothing would trigger paint event handling
1018 // => fall back to synchronous painting
1019 if( mbForceFlush
|| ImplGetSVData()->maAppData
.mnDispatchLevel
<= 0 )
1021 mbForceFlush
= false;
1022 mpGraphics
->Flush();
1027 void AquaSalFrame::Flush( const tools::Rectangle
& rRect
)
1029 if( !(mbGraphics
&& mpGraphics
&& mpNSView
&& mbShown
) )
1032 OSX_SALDATA_RUNINMAIN( Flush( rRect
) )
1034 NSRect aNSRect
= { { static_cast<CGFloat
>(rRect
.Left()), static_cast<CGFloat
>(rRect
.Top()) }, { static_cast<CGFloat
>(rRect
.GetWidth()), static_cast<CGFloat
>(rRect
.GetHeight()) } };
1035 VCLToCocoa( aNSRect
, false );
1036 [mpNSView setNeedsDisplayInRect
: aNSRect
];
1038 // outside of the application's event loop (e.g. IntroWindow)
1039 // nothing would trigger paint event handling
1040 // => fall back to synchronous painting
1041 if( mbForceFlush
|| ImplGetSVData()->maAppData
.mnDispatchLevel
<= 0 )
1043 mbForceFlush
= false;
1044 mpGraphics
->Flush( rRect
);
1049 void AquaSalFrame::SetInputContext( SalInputContext
* pContext
)
1053 mnICOptions
= InputContextFlags::NONE
;
1057 mnICOptions
= pContext
->mnOptions
;
1059 if(!(pContext
->mnOptions
& InputContextFlags::Text
))
1063 void AquaSalFrame::EndExtTextInput( EndExtTextInputFlags nFlags
)
1065 // tdf#82115 Commit uncommitted text when a popup menu is opened
1066 // The Windows implementation of this method commits or discards the native
1067 // input method session. It appears that very few, if any, macOS
1068 // applications discard the uncommitted text when cancelling a session so
1069 // always commit the uncommitted text.
1070 SalFrameWindow
*pWindow
= static_cast<SalFrameWindow
*>(mpNSWindow
);
1071 if (pWindow
&& [pWindow isKindOfClass
:[SalFrameWindow
class]])
1072 [pWindow endExtTextInput
:nFlags
];
1075 OUString
AquaSalFrame::GetKeyName( sal_uInt16 nKeyCode
)
1077 static std::map
< sal_uInt16
, OUString
> aKeyMap
;
1078 if( aKeyMap
.empty() )
1081 for( i
= KEY_A
; i
<= KEY_Z
; i
++ )
1082 aKeyMap
[ i
] = OUString( sal_Unicode( 'A' + (i
- KEY_A
) ) );
1083 for( i
= KEY_0
; i
<= KEY_9
; i
++ )
1084 aKeyMap
[ i
] = OUString( sal_Unicode( '0' + (i
- KEY_0
) ) );
1085 for( i
= KEY_F1
; i
<= KEY_F26
; i
++ )
1087 aKeyMap
[ i
] = "F" + OUString::number(i
- KEY_F1
+ 1);
1090 aKeyMap
[ KEY_DOWN
] = OUString( u
'\x21e3' );
1091 aKeyMap
[ KEY_UP
] = OUString( u
'\x21e1' );
1092 aKeyMap
[ KEY_LEFT
] = OUString( u
'\x21e0' );
1093 aKeyMap
[ KEY_RIGHT
] = OUString( u
'\x21e2' );
1094 aKeyMap
[ KEY_HOME
] = OUString( u
'\x2196' );
1095 aKeyMap
[ KEY_END
] = OUString( u
'\x2198' );
1096 aKeyMap
[ KEY_PAGEUP
] = OUString( u
'\x21de' );
1097 aKeyMap
[ KEY_PAGEDOWN
] = OUString( u
'\x21df' );
1098 aKeyMap
[ KEY_RETURN
] = OUString( u
'\x21a9' );
1099 aKeyMap
[ KEY_ESCAPE
] = "esc";
1100 aKeyMap
[ KEY_TAB
] = OUString( u
'\x21e5' );
1101 aKeyMap
[ KEY_BACKSPACE
]= OUString( u
'\x232b' );
1102 aKeyMap
[ KEY_SPACE
] = OUString( u
'\x2423' );
1103 aKeyMap
[ KEY_DELETE
] = OUString( u
'\x2326' );
1104 aKeyMap
[ KEY_ADD
] = "+";
1105 aKeyMap
[ KEY_SUBTRACT
] = "-";
1106 aKeyMap
[ KEY_DIVIDE
] = "/";
1107 aKeyMap
[ KEY_MULTIPLY
] = "*";
1108 aKeyMap
[ KEY_POINT
] = ".";
1109 aKeyMap
[ KEY_COMMA
] = ",";
1110 aKeyMap
[ KEY_LESS
] = "<";
1111 aKeyMap
[ KEY_GREATER
] = ">";
1112 aKeyMap
[ KEY_EQUAL
] = "=";
1113 aKeyMap
[ KEY_OPEN
] = OUString( u
'\x23cf' );
1114 aKeyMap
[ KEY_TILDE
] = "~";
1115 aKeyMap
[ KEY_BRACKETLEFT
] = "[";
1116 aKeyMap
[ KEY_BRACKETRIGHT
] = "]";
1117 aKeyMap
[ KEY_SEMICOLON
] = ";";
1118 aKeyMap
[ KEY_QUOTERIGHT
] = "'";
1119 aKeyMap
[ KEY_RIGHTCURLYBRACKET
] = "}";
1120 aKeyMap
[ KEY_NUMBERSIGN
] = "#";
1121 aKeyMap
[ KEY_COLON
] = ":";
1123 /* yet unmapped KEYCODES:
1124 aKeyMap[ KEY_INSERT ] = OUString( sal_Unicode( ) );
1125 aKeyMap[ KEY_CUT ] = OUString( sal_Unicode( ) );
1126 aKeyMap[ KEY_COPY ] = OUString( sal_Unicode( ) );
1127 aKeyMap[ KEY_PASTE ] = OUString( sal_Unicode( ) );
1128 aKeyMap[ KEY_UNDO ] = OUString( sal_Unicode( ) );
1129 aKeyMap[ KEY_REPEAT ] = OUString( sal_Unicode( ) );
1130 aKeyMap[ KEY_FIND ] = OUString( sal_Unicode( ) );
1131 aKeyMap[ KEY_PROPERTIES ] = OUString( sal_Unicode( ) );
1132 aKeyMap[ KEY_FRONT ] = OUString( sal_Unicode( ) );
1133 aKeyMap[ KEY_CONTEXTMENU ] = OUString( sal_Unicode( ) );
1134 aKeyMap[ KEY_MENU ] = OUString( sal_Unicode( ) );
1135 aKeyMap[ KEY_HELP ] = OUString( sal_Unicode( ) );
1136 aKeyMap[ KEY_HANGUL_HANJA ] = OUString( sal_Unicode( ) );
1137 aKeyMap[ KEY_DECIMAL ] = OUString( sal_Unicode( ) );
1138 aKeyMap[ KEY_QUOTELEFT ]= OUString( sal_Unicode( ) );
1139 aKeyMap[ KEY_CAPSLOCK ]= OUString( sal_Unicode( ) );
1140 aKeyMap[ KEY_NUMLOCK ]= OUString( sal_Unicode( ) );
1141 aKeyMap[ KEY_SCROLLLOCK ]= OUString( sal_Unicode( ) );
1146 OUStringBuffer
aResult( 16 );
1148 sal_uInt16 nUnmodifiedCode
= (nKeyCode
& KEY_CODE_MASK
);
1149 std::map
< sal_uInt16
, OUString
>::const_iterator it
= aKeyMap
.find( nUnmodifiedCode
);
1150 if( it
!= aKeyMap
.end() )
1152 if( (nKeyCode
& KEY_SHIFT
) != 0 )
1153 aResult
.append( u
'\x21e7' ); // shift
1154 if( (nKeyCode
& KEY_MOD1
) != 0 )
1155 aResult
.append( u
'\x2318' ); // command
1156 if( (nKeyCode
& KEY_MOD2
) != 0 )
1157 aResult
.append( u
'\x2325' ); // alternate
1158 if( (nKeyCode
& KEY_MOD3
) != 0 )
1159 aResult
.append( u
'\x2303' ); // control
1161 aResult
.append( it
->second
);
1164 return aResult
.makeStringAndClear();
1167 static void getAppleScrollBarVariant(StyleSettings
&rSettings
)
1169 bool bIsScrollbarDoubleMax
= true; // default is DoubleMax
1171 CFStringRef AppleScrollBarType
= CFSTR("AppleScrollBarVariant");
1172 if( AppleScrollBarType
)
1174 CFStringRef ScrollBarVariant
= static_cast<CFStringRef
>(CFPreferencesCopyAppValue( AppleScrollBarType
, kCFPreferencesCurrentApplication
));
1175 if( ScrollBarVariant
)
1177 if( CFGetTypeID( ScrollBarVariant
) == CFStringGetTypeID() )
1179 // TODO: check for the less important variants "DoubleMin" and "DoubleBoth" too
1180 CFStringRef DoubleMax
= CFSTR("DoubleMax");
1183 if ( !CFStringCompare(ScrollBarVariant
, DoubleMax
, kCFCompareCaseInsensitive
) )
1184 bIsScrollbarDoubleMax
= true;
1186 bIsScrollbarDoubleMax
= false;
1187 CFRelease(DoubleMax
);
1190 CFRelease( ScrollBarVariant
);
1192 CFRelease(AppleScrollBarType
);
1195 GetSalData()->mbIsScrollbarDoubleMax
= bIsScrollbarDoubleMax
;
1197 CFStringRef jumpScroll
= CFSTR("AppleScrollerPagingBehavior");
1200 CFBooleanRef jumpStr
= static_cast<CFBooleanRef
>(CFPreferencesCopyAppValue( jumpScroll
, kCFPreferencesCurrentApplication
));
1203 if( CFGetTypeID( jumpStr
) == CFBooleanGetTypeID() )
1204 rSettings
.SetPrimaryButtonWarpsSlider(jumpStr
== kCFBooleanTrue
);
1205 CFRelease( jumpStr
);
1207 CFRelease( jumpScroll
);
1211 static Color
getNSBoxBackgroundColor(NSColor
* pSysColor
)
1213 // Figuring out what a NSBox will draw for windowBackground, etc. seems very difficult.
1214 // So just draw to a 1x1 surface and read what actually gets drawn
1215 // This is similar to getPixel
1216 #if defined OSL_BIGENDIAN
1219 unsigned char b
, g
, r
, a
;
1224 unsigned char a
, r
, g
, b
;
1228 // create a one-pixel bitmap context
1229 CGContextRef xOnePixelContext
= CGBitmapContextCreate(
1230 &aPixel
, 1, 1, 8, 32, GetSalData()->mxRGBSpace
,
1231 uint32_t(kCGImageAlphaNoneSkipFirst
) | uint32_t(kCGBitmapByteOrder32Big
));
1233 NSGraphicsContext
* graphicsContext
= [NSGraphicsContext graphicsContextWithCGContext
:xOnePixelContext flipped
:NO
];
1235 NSRect rect
= { NSZeroPoint
, NSMakeSize(1, 1) };
1236 NSBox
* pBox
= [[NSBox alloc
] initWithFrame
: rect
];
1238 [pBox setBoxType
: NSBoxCustom
];
1239 [pBox setFillColor
: pSysColor
];
1240 SAL_WNODEPRECATED_DECLARATIONS_PUSH
// setBorderType first deprecated in macOS 10.15
1241 [pBox setBorderType
: NSNoBorder
];
1242 SAL_WNODEPRECATED_DECLARATIONS_POP
1244 [pBox displayRectIgnoringOpacity
: rect inContext
: graphicsContext
];
1248 CGContextRelease(xOnePixelContext
);
1250 return Color(aPixel
.r
, aPixel
.g
, aPixel
.b
);
1253 static Color
getColor( NSColor
* pSysColor
, const Color
& rDefault
, NSWindow
* pWin
)
1255 Color
aRet( rDefault
);
1259 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1260 // "'colorUsingColorSpaceName:device:' is deprecated: first deprecated in macOS 10.14 -
1261 // Use -colorUsingType: or -colorUsingColorSpace: instead"
1262 NSColor
* pRBGColor
= [pSysColor colorUsingColorSpaceName
: NSDeviceRGBColorSpace device
: [pWin deviceDescription
]];
1263 SAL_WNODEPRECATED_DECLARATIONS_POP
1266 CGFloat r
= 0, g
= 0, b
= 0, a
= 0;
1267 [pRBGColor getRed
: &r green
: &g blue
: &b alpha
: &a
];
1268 aRet
= Color( int(r
*255.999), int(g
*255.999), int(b
*255.999) );
1274 static vcl::Font
getFont( NSFont
* pFont
, sal_Int32 nDPIY
, const vcl::Font
& rDefault
)
1276 vcl::Font
aResult( rDefault
);
1279 aResult
.SetFamilyName( GetOUString( [pFont familyName
] ) );
1280 aResult
.SetFontHeight( static_cast<int>(ceil([pFont pointSize
] * 72.0 / static_cast<float>(nDPIY
))) );
1281 aResult
.SetItalic( ([pFont italicAngle
] != 0.0) ? ITALIC_NORMAL
: ITALIC_NONE
);
1288 void AquaSalFrame::getResolution( sal_Int32
& o_rDPIX
, sal_Int32
& o_rDPIY
)
1290 OSX_SALDATA_RUNINMAIN( getResolution( o_rDPIX
, o_rDPIY
) )
1295 ReleaseGraphics( mpGraphics
);
1297 mpGraphics
->GetResolution( o_rDPIX
, o_rDPIY
);
1300 void AquaSalFrame::UpdateDarkMode()
1302 if (@
available(macOS
10.14, iOS
13, *))
1304 switch (MiscSettings::GetDarkMode())
1308 [NSApp setAppearance
: nil
];
1311 [NSApp setAppearance
: [NSAppearance appearanceNamed
: NSAppearanceNameAqua
]];
1314 [NSApp setAppearance
: [NSAppearance appearanceNamed
: NSAppearanceNameDarkAqua
]];
1320 // on OSX-Aqua the style settings are independent of the frame, so it does
1321 // not really belong here. Since the connection to the Appearance_Manager
1322 // is currently done in salnativewidgets.cxx this would be a good place.
1323 // On the other hand VCL's platform independent code currently only asks
1324 // SalFrames for system settings anyway, so moving the code somewhere else
1325 // doesn't make the anything cleaner for now
1326 void AquaSalFrame::UpdateSettings( AllSettings
& rSettings
)
1331 OSX_SALDATA_RUNINMAIN( UpdateSettings( rSettings
) )
1333 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1334 // "'lockFocus' is deprecated: first deprecated in macOS 10.14 - To draw, subclass NSView
1335 // and implement -drawRect:; AppKit's automatic deferred display mechanism will call
1336 // -drawRect: as necessary to display the view."
1337 if (![mpNSView lockFocusIfCanDraw
])
1339 SAL_WNODEPRECATED_DECLARATIONS_POP
1341 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1342 // "'setCurrentAppearance:' is deprecated: first deprecated in macOS 12.0 - Use
1343 // -performAsCurrentDrawingAppearance: to temporarily set the drawing appearance, or
1344 // +currentDrawingAppearance to access the currently drawing appearance."
1345 [NSAppearance setCurrentAppearance
: mpNSView
.effectiveAppearance
];
1346 SAL_WNODEPRECATED_DECLARATIONS_POP
1348 StyleSettings aStyleSettings
= rSettings
.GetStyleSettings();
1350 bool bUseDarkMode(false);
1351 if (@
available(macOS
10.14, iOS
13, *))
1353 NSAppearanceName match
= [mpNSView
.effectiveAppearance bestMatchFromAppearancesWithNames
: @
[
1354 NSAppearanceNameAqua
, NSAppearanceNameDarkAqua
]];
1355 bUseDarkMode
= [match isEqualToString
: NSAppearanceNameDarkAqua
];
1357 OUString
sThemeName(!bUseDarkMode
? u
"sukapura" : u
"sukapura_dark");
1358 aStyleSettings
.SetPreferredIconTheme(sThemeName
, bUseDarkMode
);
1360 Color
aControlBackgroundColor(getNSBoxBackgroundColor([NSColor controlBackgroundColor
]));
1361 Color
aWindowBackgroundColor(getNSBoxBackgroundColor([NSColor windowBackgroundColor
]));
1362 Color
aUnderPageBackgroundColor(getNSBoxBackgroundColor([NSColor underPageBackgroundColor
]));
1365 aStyleSettings
.BatchSetBackgrounds( aWindowBackgroundColor
, false );
1366 aStyleSettings
.SetLightBorderColor( aWindowBackgroundColor
);
1368 aStyleSettings
.SetActiveTabColor(aWindowBackgroundColor
);
1369 Color
aInactiveTabColor( aWindowBackgroundColor
);
1370 aInactiveTabColor
.DecreaseLuminance( 32 );
1371 aStyleSettings
.SetInactiveTabColor( aInactiveTabColor
);
1373 Color aShadowColor
= getColor( [NSColor systemGrayColor
],
1374 aStyleSettings
.GetShadowColor(), mpNSWindow
);
1375 aStyleSettings
.SetShadowColor( aShadowColor
);
1377 // tdf#152284 for DarkMode brighten it, while darken for BrightMode
1378 NSColor
* pDarkColor
= bUseDarkMode
? [[NSColor systemGrayColor
] highlightWithLevel
: 0.5]
1379 : [[NSColor systemGrayColor
] shadowWithLevel
: 0.5];
1380 Color aDarkShadowColor
= getColor( pDarkColor
, aStyleSettings
.GetDarkShadowColor(), mpNSWindow
);
1381 aStyleSettings
.SetDarkShadowColor(aDarkShadowColor
);
1383 // get the system font settings
1384 vcl::Font aAppFont
= aStyleSettings
.GetAppFont();
1385 sal_Int32 nDPIX
= 72, nDPIY
= 72;
1386 getResolution( nDPIX
, nDPIY
);
1387 aAppFont
= getFont( [NSFont systemFontOfSize
: 0], nDPIY
, aAppFont
);
1389 aStyleSettings
.SetToolbarIconSize( ToolbarIconSize::Large
);
1391 // TODO: better mapping of macOS<->LibreOffice font settings
1392 vcl::Font
aLabelFont( getFont( [NSFont labelFontOfSize
: 0], nDPIY
, aAppFont
) );
1393 aStyleSettings
.BatchSetFonts( aAppFont
, aLabelFont
);
1394 vcl::Font
aMenuFont( getFont( [NSFont menuFontOfSize
: 0], nDPIY
, aAppFont
) );
1395 aStyleSettings
.SetMenuFont( aMenuFont
);
1397 vcl::Font
aTitleFont( getFont( [NSFont titleBarFontOfSize
: 0], nDPIY
, aAppFont
) );
1398 aStyleSettings
.SetTitleFont( aTitleFont
);
1399 aStyleSettings
.SetFloatTitleFont( aTitleFont
);
1401 vcl::Font
aTooltipFont(getFont([NSFont toolTipsFontOfSize
: 0], nDPIY
, aAppFont
));
1402 aStyleSettings
.SetHelpFont(aTooltipFont
);
1404 Color
aHighlightColor( getColor( [NSColor selectedTextBackgroundColor
],
1405 aStyleSettings
.GetHighlightColor(), mpNSWindow
) );
1406 aStyleSettings
.SetHighlightColor( aHighlightColor
);
1407 Color
aHighlightTextColor( getColor( [NSColor selectedTextColor
],
1408 aStyleSettings
.GetHighlightTextColor(), mpNSWindow
) );
1409 aStyleSettings
.SetHighlightTextColor( aHighlightTextColor
);
1411 aStyleSettings
.SetLinkColor(getColor( [NSColor linkColor
],
1412 aStyleSettings
.GetLinkColor(), mpNSWindow
) );
1413 aStyleSettings
.SetVisitedLinkColor(getColor( [NSColor purpleColor
],
1414 aStyleSettings
.GetVisitedLinkColor(), mpNSWindow
) );
1416 #pragma clang diagnostic push
1417 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1418 Color
aMenuHighlightColor( getColor( [NSColor selectedMenuItemColor
],
1419 aStyleSettings
.GetMenuHighlightColor(), mpNSWindow
) );
1420 #pragma clang diagnostic pop
1421 aStyleSettings
.SetMenuHighlightColor( aMenuHighlightColor
);
1422 Color
aMenuHighlightTextColor( getColor( [NSColor selectedMenuItemTextColor
],
1423 aStyleSettings
.GetMenuHighlightTextColor(), mpNSWindow
) );
1424 aStyleSettings
.SetMenuHighlightTextColor( aMenuHighlightTextColor
);
1426 aStyleSettings
.SetMenuColor( aWindowBackgroundColor
);
1427 Color
aMenuTextColor( getColor( [NSColor textColor
],
1428 aStyleSettings
.GetMenuTextColor(), mpNSWindow
) );
1429 aStyleSettings
.SetMenuTextColor( aMenuTextColor
);
1430 aStyleSettings
.SetMenuBarTextColor( aMenuTextColor
);
1431 aStyleSettings
.SetMenuBarRolloverTextColor( aMenuTextColor
);
1432 aStyleSettings
.SetMenuBarHighlightTextColor(aStyleSettings
.GetMenuHighlightTextColor());
1434 aStyleSettings
.SetListBoxWindowBackgroundColor( aWindowBackgroundColor
);
1435 aStyleSettings
.SetListBoxWindowTextColor( aMenuTextColor
);
1436 aStyleSettings
.SetListBoxWindowHighlightColor( aMenuHighlightColor
);
1437 aStyleSettings
.SetListBoxWindowHighlightTextColor( aMenuHighlightTextColor
);
1439 // FIXME: Starting with macOS Big Sur, coloring has changed. Currently there is no documentation which system color should be
1440 // used for some button states and for selected tab text. As a workaround the current OS version has to be considered. This code
1441 // has to be reviewed once issue is covered by documentation.
1443 // Set text colors for buttons and their different status according to OS settings, typically white for selected buttons,
1446 NSOperatingSystemVersion aOSVersion
= { .majorVersion
= 10, .minorVersion
= 16, .patchVersion
= 0 };
1447 Color
aControlTextColor(getColor([NSColor controlTextColor
], COL_BLACK
, mpNSWindow
));
1448 Color
aSelectedControlTextColor(getColor([NSColor selectedControlTextColor
], COL_BLACK
, mpNSWindow
));
1449 Color
aAlternateSelectedControlTextColor(getColor([NSColor alternateSelectedControlTextColor
], COL_WHITE
, mpNSWindow
));
1450 aStyleSettings
.SetWindowColor(aWindowBackgroundColor
);
1451 aStyleSettings
.SetListBoxWindowBackgroundColor(aWindowBackgroundColor
);
1453 aStyleSettings
.SetDialogTextColor(aControlTextColor
);
1454 aStyleSettings
.SetButtonTextColor(aControlTextColor
);
1455 aStyleSettings
.SetActionButtonTextColor(aControlTextColor
);
1456 aStyleSettings
.SetRadioCheckTextColor(aControlTextColor
);
1457 aStyleSettings
.SetGroupTextColor(aControlTextColor
);
1458 aStyleSettings
.SetLabelTextColor(aControlTextColor
);
1459 aStyleSettings
.SetWindowTextColor(aControlTextColor
);
1460 aStyleSettings
.SetFieldTextColor(aControlTextColor
);
1462 aStyleSettings
.SetFieldRolloverTextColor(aControlTextColor
);
1463 aStyleSettings
.SetFieldColor(aControlBackgroundColor
);
1464 aStyleSettings
.SetDefaultActionButtonTextColor(aAlternateSelectedControlTextColor
);
1465 aStyleSettings
.SetFlatButtonTextColor(aControlTextColor
);
1466 aStyleSettings
.SetDefaultButtonRolloverTextColor(aAlternateSelectedControlTextColor
);
1467 aStyleSettings
.SetButtonRolloverTextColor(aControlTextColor
);
1468 aStyleSettings
.SetDefaultActionButtonRolloverTextColor(aAlternateSelectedControlTextColor
);
1469 aStyleSettings
.SetActionButtonRolloverTextColor(aControlTextColor
);
1470 aStyleSettings
.SetFlatButtonRolloverTextColor(aControlTextColor
);
1471 aStyleSettings
.SetDefaultButtonPressedRolloverTextColor(aAlternateSelectedControlTextColor
);
1472 aStyleSettings
.SetDefaultActionButtonPressedRolloverTextColor(aAlternateSelectedControlTextColor
);
1473 aStyleSettings
.SetFlatButtonPressedRolloverTextColor(aControlTextColor
);
1474 if ([NSProcessInfo
.processInfo isOperatingSystemAtLeastVersion
: aOSVersion
])
1476 aStyleSettings
.SetDefaultButtonTextColor(aAlternateSelectedControlTextColor
);
1477 aStyleSettings
.SetButtonPressedRolloverTextColor(aSelectedControlTextColor
);
1478 aStyleSettings
.SetActionButtonPressedRolloverTextColor(aSelectedControlTextColor
);
1482 aStyleSettings
.SetButtonPressedRolloverTextColor(aAlternateSelectedControlTextColor
);
1483 aStyleSettings
.SetActionButtonPressedRolloverTextColor(aAlternateSelectedControlTextColor
);
1484 aStyleSettings
.SetDefaultButtonTextColor(aSelectedControlTextColor
);
1487 aStyleSettings
.SetWorkspaceColor(aUnderPageBackgroundColor
);
1489 aStyleSettings
.SetHelpColor(aControlBackgroundColor
);
1490 aStyleSettings
.SetHelpTextColor(aControlTextColor
);
1491 aStyleSettings
.SetToolTextColor(aControlTextColor
);
1493 // Set text colors for tabs according to OS settings
1495 aStyleSettings
.SetTabTextColor(aControlTextColor
);
1496 aStyleSettings
.SetTabRolloverTextColor(aControlTextColor
);
1497 if ([NSProcessInfo
.processInfo isOperatingSystemAtLeastVersion
: aOSVersion
])
1498 aStyleSettings
.SetTabHighlightTextColor(aSelectedControlTextColor
);
1500 aStyleSettings
.SetTabHighlightTextColor(aAlternateSelectedControlTextColor
);
1502 aStyleSettings
.SetCursorBlinkTime( mnBlinkCursorDelay
);
1503 aStyleSettings
.SetCursorSize(1);
1505 // no mnemonics on macOS
1506 aStyleSettings
.SetOptions( aStyleSettings
.GetOptions() | StyleSettingsOptions::NoMnemonics
);
1508 getAppleScrollBarVariant(aStyleSettings
);
1510 // set scrollbar size
1511 aStyleSettings
.SetScrollBarSize( static_cast<tools::Long
>([NSScroller scrollerWidthForControlSize
:NSControlSizeRegular scrollerStyle
:NSScrollerStyleLegacy
]) );
1512 // images in menus false for MacOSX
1513 aStyleSettings
.SetPreferredUseImagesInMenus( false );
1514 aStyleSettings
.SetHideDisabledMenuItems( true );
1515 aStyleSettings
.SetPreferredContextMenuShortcuts( false );
1517 rSettings
.SetStyleSettings( aStyleSettings
);
1519 // don't draw frame around each and every toolbar
1520 ImplGetSVData()->maNWFData
.mbDockingAreaAvoidTBFrames
= true;
1522 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1523 // "'unlockFocus' is deprecated: first deprecated in macOS 10.14 - To draw, subclass NSView
1524 // and implement -drawRect:; AppKit's automatic deferred display mechanism will call
1525 // -drawRect: as necessary to display the view."
1526 [mpNSView unlockFocus
];
1527 SAL_WNODEPRECATED_DECLARATIONS_POP
1530 const SystemEnvData
* AquaSalFrame::GetSystemData() const
1535 void AquaSalFrame::Beep()
1537 OSX_SALDATA_RUNINMAIN( Beep() )
1541 void AquaSalFrame::SetPosSize(
1542 tools::Long nX
, tools::Long nY
, tools::Long nWidth
, tools::Long nHeight
, sal_uInt16 nFlags
)
1544 if (!mpNSWindow
&& !Application::IsBitmapRendering())
1547 OSX_SALDATA_RUNINMAIN( SetPosSize( nX
, nY
, nWidth
, nHeight
, nFlags
) )
1549 SalEvent nEvent
= PreparePosSize(nX
, nY
, nWidth
, nHeight
, nFlags
);
1550 if (Application::IsBitmapRendering())
1553 if( [mpNSWindow isMiniaturized
] )
1554 [mpNSWindow deminiaturize
: NSApp
]; // expand the window
1556 NSRect aFrameRect
= [mpNSWindow frame
];
1557 NSRect aContentRect
= [NSWindow contentRectForFrameRect
: aFrameRect styleMask
: mnStyleMask
];
1559 // position is always relative to parent frame
1560 NSRect aParentContentRect
;
1564 if( AllSettings::GetLayoutRTL() )
1566 if( (nFlags
& SAL_FRAME_POSSIZE_WIDTH
) != 0 )
1567 nX
= static_cast<tools::Long
>(mpParent
->maGeometry
.width()) - nWidth
- 1 - nX
;
1569 nX
= static_cast<tools::Long
>(mpParent
->maGeometry
.width()) - aContentRect
.size
.width
- 1 - nX
;
1571 NSRect aParentFrameRect
= [mpParent
->mpNSWindow frame
];
1572 aParentContentRect
= [NSWindow contentRectForFrameRect
: aParentFrameRect styleMask
: mpParent
->mnStyleMask
];
1575 aParentContentRect
= maScreenRect
; // use screen if no parent
1577 CocoaToVCL( aContentRect
);
1578 CocoaToVCL( aParentContentRect
);
1580 bool bPaint
= false;
1581 if( (nFlags
& (SAL_FRAME_POSSIZE_WIDTH
| SAL_FRAME_POSSIZE_HEIGHT
)) != 0 )
1583 if( nWidth
!= aContentRect
.size
.width
|| nHeight
!= aContentRect
.size
.height
)
1587 // use old window pos if no new pos requested
1588 if( (nFlags
& SAL_FRAME_POSSIZE_X
) != 0 )
1589 aContentRect
.origin
.x
= nX
+ aParentContentRect
.origin
.x
;
1590 if( (nFlags
& SAL_FRAME_POSSIZE_Y
) != 0)
1591 aContentRect
.origin
.y
= nY
+ aParentContentRect
.origin
.y
;
1593 // use old size if no new size requested
1594 if( (nFlags
& SAL_FRAME_POSSIZE_WIDTH
) != 0 )
1595 aContentRect
.size
.width
= nWidth
;
1596 if( (nFlags
& SAL_FRAME_POSSIZE_HEIGHT
) != 0)
1597 aContentRect
.size
.height
= nHeight
;
1599 VCLToCocoa( aContentRect
);
1601 // do not display yet, we need to update our backbuffer
1603 [mpNSWindow setFrame
: [NSWindow frameRectForContentRect
: aContentRect styleMask
: mnStyleMask
] display
: NO
];
1606 UpdateFrameGeometry();
1608 if (nEvent
!= SalEvent::NONE
)
1609 CallCallback(nEvent
, nullptr);
1611 if( mbShown
&& bPaint
)
1613 // trigger filling our backbuffer
1616 // now inform the system that the views need to be drawn
1617 [mpNSWindow display
];
1621 void AquaSalFrame::GetWorkArea( tools::Rectangle
& rRect
)
1625 if (Application::IsBitmapRendering())
1626 rRect
= tools::Rectangle(Point(0, 0), Size(1024, 768));
1630 OSX_SALDATA_RUNINMAIN( GetWorkArea( rRect
) )
1632 NSScreen
* pScreen
= [mpNSWindow screen
];
1633 if( pScreen
== nil
)
1634 pScreen
= [NSScreen mainScreen
];
1635 NSRect aRect
= [pScreen visibleFrame
];
1636 CocoaToVCL( aRect
);
1637 rRect
.SetLeft( static_cast<tools::Long
>(aRect
.origin
.x
) );
1638 rRect
.SetTop( static_cast<tools::Long
>(aRect
.origin
.y
) );
1639 rRect
.SetRight( static_cast<tools::Long
>(aRect
.origin
.x
+ aRect
.size
.width
- 1) );
1640 rRect
.SetBottom( static_cast<tools::Long
>(aRect
.origin
.y
+ aRect
.size
.height
- 1) );
1643 SalFrame::SalPointerState
AquaSalFrame::GetPointerState()
1645 OSX_SALDATA_RUNINMAIN_UNION( GetPointerState(), state
)
1647 SalPointerState state
;
1651 NSPoint aPt
= [mpNSWindow mouseLocationOutsideOfEventStream
];
1652 CocoaToVCL( aPt
, false );
1653 state
.maPos
= Point(static_cast<tools::Long
>(aPt
.x
), static_cast<tools::Long
>(aPt
.y
));
1655 NSEvent
* pCur
= [NSApp currentEvent
];
1656 bool bMouseEvent
= false;
1660 switch( [pCur type
] )
1662 case NSEventTypeLeftMouseDown
:
1663 state
.mnState
|= MOUSE_LEFT
;
1665 case NSEventTypeLeftMouseUp
:
1667 case NSEventTypeRightMouseDown
:
1668 state
.mnState
|= MOUSE_RIGHT
;
1670 case NSEventTypeRightMouseUp
:
1672 case NSEventTypeOtherMouseDown
:
1673 state
.mnState
|= ([pCur buttonNumber
] == 2) ? MOUSE_MIDDLE
: 0;
1675 case NSEventTypeOtherMouseUp
:
1677 case NSEventTypeMouseMoved
:
1679 case NSEventTypeLeftMouseDragged
:
1680 state
.mnState
|= MOUSE_LEFT
;
1682 case NSEventTypeRightMouseDragged
:
1683 state
.mnState
|= MOUSE_RIGHT
;
1685 case NSEventTypeOtherMouseDragged
:
1686 state
.mnState
|= ([pCur buttonNumber
] == 2) ? MOUSE_MIDDLE
: 0;
1689 bMouseEvent
= false;
1695 unsigned int nMask
= static_cast<unsigned int>([pCur modifierFlags
]);
1696 if( (nMask
& NSEventModifierFlagShift
) != 0 )
1697 state
.mnState
|= KEY_SHIFT
;
1698 if( (nMask
& NSEventModifierFlagControl
) != 0 )
1699 state
.mnState
|= KEY_MOD3
;
1700 if( (nMask
& NSEventModifierFlagOption
) != 0 )
1701 state
.mnState
|= KEY_MOD2
;
1702 if( (nMask
& NSEventModifierFlagCommand
) != 0 )
1703 state
.mnState
|= KEY_MOD1
;
1708 // FIXME: replace Carbon by Cocoa
1709 // Cocoa does not have an equivalent for GetCurrentEventButtonState
1710 // and GetCurrentEventKeyModifiers.
1711 // we could try to get away with tracking all events for modifierKeys
1712 // and all mouse events for button state in VCL_NSApplication::sendEvent,
1713 // but it is unclear whether this will get us the same result.
1714 // leave in GetCurrentEventButtonState and GetCurrentEventKeyModifiers for now
1716 // fill in button state
1717 UInt32 nState
= GetCurrentEventButtonState();
1720 state
.mnState
|= MOUSE_LEFT
; // primary button
1722 state
.mnState
|= MOUSE_RIGHT
; // secondary button
1724 state
.mnState
|= MOUSE_MIDDLE
; // tertiary button
1726 // fill in modifier state
1727 nState
= GetCurrentEventKeyModifiers();
1728 if( nState
& shiftKey
)
1729 state
.mnState
|= KEY_SHIFT
;
1730 if( nState
& controlKey
)
1731 state
.mnState
|= KEY_MOD3
;
1732 if( nState
& optionKey
)
1733 state
.mnState
|= KEY_MOD2
;
1734 if( nState
& cmdKey
)
1735 state
.mnState
|= KEY_MOD1
;
1741 KeyIndicatorState
AquaSalFrame::GetIndicatorState()
1743 return KeyIndicatorState::NONE
;
1746 void AquaSalFrame::SimulateKeyPress( sal_uInt16
/*nKeyCode*/ )
1750 void AquaSalFrame::SetPluginParent( SystemParentData
* )
1752 // plugin parent may be killed unexpectedly by
1753 // plugging process;
1758 bool AquaSalFrame::MapUnicodeToKeyCode( sal_Unicode
, LanguageType
, vcl::KeyCode
& )
1760 // not supported yet
1764 LanguageType
AquaSalFrame::GetInputLanguage()
1767 return LANGUAGE_DONTKNOW
;
1770 void AquaSalFrame::SetMenu( SalMenu
* pSalMenu
)
1772 OSX_SALDATA_RUNINMAIN( SetMenu( pSalMenu
) )
1774 AquaSalMenu
* pMenu
= static_cast<AquaSalMenu
*>(pSalMenu
);
1775 SAL_WARN_IF( pMenu
&& !pMenu
->mbMenuBar
, "vcl", "setting non menubar on frame" );
1778 mpMenu
->setMainMenu();
1781 void AquaSalFrame::SetExtendedFrameStyle( SalExtStyle nStyle
)
1785 mnExtStyle
= nStyle
;
1789 OSX_SALDATA_RUNINMAIN( SetExtendedFrameStyle( nStyle
) )
1791 if( (mnExtStyle
& SAL_FRAME_EXT_STYLE_DOCMODIFIED
) != (nStyle
& SAL_FRAME_EXT_STYLE_DOCMODIFIED
) )
1792 [mpNSWindow setDocumentEdited
: (nStyle
& SAL_FRAME_EXT_STYLE_DOCMODIFIED
) ? YES
: NO
];
1794 mnExtStyle
= nStyle
;
1797 SalFrame
* AquaSalFrame::GetParent() const
1802 void AquaSalFrame::SetParent( SalFrame
* pNewParent
)
1804 bool bShown
= mbShown
;
1805 // remove from child list
1808 mpParent
= static_cast<AquaSalFrame
*>(pNewParent
);
1809 // insert to correct parent and paint
1813 void AquaSalFrame::UpdateFrameGeometry()
1815 bool bFirstTime
= (mnTrackingRectTag
== 0);
1816 mbGeometryDidChange
= false;
1821 OSX_SALDATA_RUNINMAIN( UpdateFrameGeometry() )
1823 // keep in mind that view and window coordinates are lower left
1824 // whereas vcl's are upper left
1826 // update screen rect
1827 NSScreen
* pScreen
= [mpNSWindow screen
];
1830 NSRect aNewScreenRect
= [pScreen frame
];
1831 if (bFirstTime
|| !NSEqualRects(maScreenRect
, aNewScreenRect
))
1833 mbGeometryDidChange
= true;
1834 maScreenRect
= aNewScreenRect
;
1836 NSArray
* pScreens
= [NSScreen screens
];
1839 unsigned int nNewDisplayScreenNumber
= [pScreens indexOfObject
: pScreen
];
1840 if (bFirstTime
|| maGeometry
.screen() != nNewDisplayScreenNumber
)
1842 mbGeometryDidChange
= true;
1843 maGeometry
.setScreen(nNewDisplayScreenNumber
);
1848 NSRect aFrameRect
= [mpNSWindow frame
];
1849 NSRect aContentRect
= [NSWindow contentRectForFrameRect
: aFrameRect styleMask
: mnStyleMask
];
1851 NSRect aTrackRect
= { NSZeroPoint
, aContentRect
.size
};
1853 if (bFirstTime
|| !NSEqualRects(maTrackingRect
, aTrackRect
))
1855 mbGeometryDidChange
= true;
1856 maTrackingRect
= aTrackRect
;
1858 // release old track rect
1859 [mpNSView removeTrackingRect
: mnTrackingRectTag
];
1860 // install the new track rect
1861 mnTrackingRectTag
= [mpNSView addTrackingRect
: aTrackRect owner
: mpNSView userData
: nil assumeInside
: NO
];
1864 // convert to vcl convention
1865 CocoaToVCL( aFrameRect
);
1866 CocoaToVCL( aContentRect
);
1868 if (bFirstTime
|| !NSEqualRects(maContentRect
, aContentRect
) || !NSEqualRects(maFrameRect
, aFrameRect
))
1870 mbGeometryDidChange
= true;
1872 maContentRect
= aContentRect
;
1873 maFrameRect
= aFrameRect
;
1875 maGeometry
.setX(static_cast<sal_Int32
>(aContentRect
.origin
.x
));
1876 maGeometry
.setY(static_cast<sal_Int32
>(aContentRect
.origin
.y
));
1877 maGeometry
.setWidth(static_cast<sal_uInt32
>(aContentRect
.size
.width
));
1878 maGeometry
.setHeight(static_cast<sal_uInt32
>(aContentRect
.size
.height
));
1880 maGeometry
.setLeftDecoration(static_cast<sal_uInt32
>(aContentRect
.origin
.x
- aFrameRect
.origin
.x
));
1881 maGeometry
.setRightDecoration(static_cast<sal_uInt32
>((aFrameRect
.origin
.x
+ aFrameRect
.size
.width
) -
1882 (aContentRect
.origin
.x
+ aContentRect
.size
.width
)));
1883 maGeometry
.setTopDecoration(static_cast<sal_uInt32
>(aContentRect
.origin
.y
- aFrameRect
.origin
.y
));
1884 maGeometry
.setBottomDecoration(static_cast<sal_uInt32
>((aFrameRect
.origin
.y
+ aFrameRect
.size
.height
) -
1885 (aContentRect
.origin
.y
+ aContentRect
.size
.height
)));
1889 void AquaSalFrame::CaptureMouse( bool bCapture
)
1892 we'll try to use a pidgin version of capture mouse
1893 on MacOSX (neither carbon nor cocoa) there is a
1894 CaptureMouse equivalent (in Carbon there is TrackMouseLocation
1895 but this is useless to use since it is blocking)
1897 However on cocoa the active frame seems to get mouse events
1898 also outside the window, so we'll try to forward mouse events
1899 to the capture frame in the hope that one of our frames
1902 This will break as soon as the user activates another app, but
1903 a mouse click will normally lead to a release of the mouse anyway.
1905 Let's see how far we get this way. Alternatively we could use one
1906 large overlay window like we did for the carbon implementation,
1907 however that is resource intensive.
1911 s_pCaptureFrame
= this;
1912 else if( ! bCapture
&& s_pCaptureFrame
== this )
1913 s_pCaptureFrame
= nullptr;
1916 void AquaSalFrame::ResetClipRegion()
1918 doResetClipRegion();
1921 void AquaSalFrame::doResetClipRegion()
1926 OSX_SALDATA_RUNINMAIN( ResetClipRegion() )
1928 // release old path and indicate no clipping
1929 CGPathRelease( mrClippingPath
);
1930 mrClippingPath
= nullptr;
1932 if( mpNSView
&& mbShown
)
1933 [mpNSView setNeedsDisplay
: YES
];
1934 [mpNSWindow setOpaque
: YES
];
1935 [mpNSWindow invalidateShadow
];
1938 void AquaSalFrame::BeginSetClipRegion( sal_uInt32 nRects
)
1943 OSX_SALDATA_RUNINMAIN( BeginSetClipRegion( nRects
) )
1946 if( mrClippingPath
)
1948 CGPathRelease( mrClippingPath
);
1949 mrClippingPath
= nullptr;
1952 if( maClippingRects
.size() > SAL_CLIPRECT_COUNT
&& nRects
< maClippingRects
.size() )
1954 std::vector
<CGRect
>().swap(maClippingRects
);
1956 maClippingRects
.clear();
1957 maClippingRects
.reserve( nRects
);
1960 void AquaSalFrame::UnionClipRegion(
1961 tools::Long nX
, tools::Long nY
, tools::Long nWidth
, tools::Long nHeight
)
1963 // #i113170# may not be the main thread if called from UNO API
1964 SalData::ensureThreadAutoreleasePool();
1966 if( nWidth
&& nHeight
)
1968 NSRect aRect
= { { static_cast<CGFloat
>(nX
), static_cast<CGFloat
>(nY
) }, { static_cast<CGFloat
>(nWidth
), static_cast<CGFloat
>(nHeight
) } };
1969 VCLToCocoa( aRect
, false );
1970 maClippingRects
.push_back( CGRectMake(aRect
.origin
.x
, aRect
.origin
.y
, aRect
.size
.width
, aRect
.size
.height
) );
1974 void AquaSalFrame::EndSetClipRegion()
1979 OSX_SALDATA_RUNINMAIN( EndSetClipRegion() )
1981 if( ! maClippingRects
.empty() )
1983 mrClippingPath
= CGPathCreateMutable();
1984 CGPathAddRects( mrClippingPath
, nullptr, maClippingRects
.data(), maClippingRects
.size() );
1986 if( mpNSView
&& mbShown
)
1987 [mpNSView setNeedsDisplay
: YES
];
1988 [mpNSWindow setOpaque
: (mrClippingPath
!= nullptr) ? NO
: YES
];
1989 [mpNSWindow setBackgroundColor
: [NSColor clearColor
]];
1990 // shadow is invalidated when view gets drawn again
1993 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */