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
)
92 mpParent
= dynamic_cast<AquaSalFrame
*>(pParent
);
96 SalData
* pSalData
= GetSalData();
97 pSalData
->mpInstance
->insertFrame( this );
98 NSUserDefaults
*userDefaults
= [NSUserDefaults standardUserDefaults
];
100 // tdf#150177 Limit minimum blink cursor rate
101 // This bug occurs when the values for NSTextInsertionPointBlinkPeriodOn or
102 // NSTextInsertionPointBlinkPeriodOff are set to zero or close to zero.
103 // LibreOffice becomes very sluggish opening documents when either is set
104 // at 100 milliseconds or less so set the blink rate to the maximum of
105 // nMinBlinkCursorDelay, NSTextInsertionPointBlinkPeriodOn, and
106 // NSTextInsertionPointBlinkPeriodOff.
107 mnBlinkCursorDelay
= nMinBlinkCursorDelay
;
108 if (userDefaults
!= nil
)
110 id setting
= [userDefaults objectForKey
: @
"NSTextInsertionPointBlinkPeriodOn"];
111 if (setting
&& [setting isKindOfClass
:[NSNumber
class]])
112 mnBlinkCursorDelay
= std::max(mnBlinkCursorDelay
, [setting intValue
]);
114 setting
= [userDefaults objectForKey
: @
"NSTextInsertionPointBlinkPeriodOff"];
115 if (setting
&& [setting isKindOfClass
:[NSNumber
class]])
116 mnBlinkCursorDelay
= std::max(mnBlinkCursorDelay
, [setting intValue
]);
120 AquaSalFrame::~AquaSalFrame()
123 doShowFullScreen(false, maGeometry
.screen());
125 assert( GetSalData()->mpInstance
->IsMainThread() );
127 // if the frame is destroyed and has the current menubar
128 // set the default menubar
129 if( mpMenu
&& mpMenu
->mbMenuBar
&& AquaSalMenu::pCurrentMenuBar
== mpMenu
)
130 AquaSalMenu::setDefaultMenu();
132 // cleanup clipping stuff
135 [SalFrameView unsetMouseFrame
: this];
137 SalData
* pSalData
= GetSalData();
138 pSalData
->mpInstance
->eraseFrame( this );
139 pSalData
->maPresentationFrames
.remove( this );
141 SAL_WARN_IF( this == s_pCaptureFrame
, "vcl", "capture frame destroyed" );
142 if( this == s_pCaptureFrame
)
143 s_pCaptureFrame
= nullptr;
147 if( mpDockMenuEntry
)
149 NSMenu
* pDock
= AquaSalInstance::GetDynamicDockMenu();
150 // life cycle comment: the menu has ownership of the item, so no release
151 [pDock removeItem
: mpDockMenuEntry
];
152 if ([pDock numberOfItems
] != 0
153 && [[pDock itemAtIndex
: 0] isSeparatorItem
])
155 [pDock removeItemAtIndex
: 0];
159 if ([mpNSView isKindOfClass
:[SalFrameView
class]])
160 [static_cast<SalFrameView
*>(mpNSView
) revokeWrapper
];
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::resetTotalScreenBounds();
292 sal::aqua::resetWindowScaling();
294 UpdateFrameGeometry();
297 mpGraphics
->updateResolution();
299 if (!mbGeometryDidChange
)
302 CallCallback( SalEvent::DisplayChanged
, nullptr );
305 SalGraphics
* AquaSalFrame::AcquireGraphics()
312 mpGraphics
= new AquaSalGraphics
;
313 mpGraphics
->SetWindowGraphics( this );
320 void AquaSalFrame::ReleaseGraphics( SalGraphics
*pGraphics
)
322 SAL_WARN_IF( pGraphics
!= mpGraphics
, "vcl", "graphics released on wrong frame" );
326 bool AquaSalFrame::PostEvent(std::unique_ptr
<ImplSVEvent
> pData
)
328 GetSalData()->mpInstance
->PostEvent( this, pData
.release(), SalEvent::UserEvent
);
332 void AquaSalFrame::SetTitle(const OUString
& rTitle
)
337 OSX_SALDATA_RUNINMAIN( SetTitle(rTitle
) )
339 // #i113170# may not be the main thread if called from UNO API
340 SalData::ensureThreadAutoreleasePool();
342 NSString
* pTitle
= CreateNSString( rTitle
);
343 [mpNSWindow setTitle
: pTitle
];
345 // create an entry in the dock menu
346 const SalFrameStyleFlags nAppWindowStyle
= SalFrameStyleFlags::CLOSEABLE
| SalFrameStyleFlags::MOVEABLE
;
347 if( mpParent
== nullptr &&
348 (mnStyle
& nAppWindowStyle
) == nAppWindowStyle
)
350 if( mpDockMenuEntry
== nullptr )
352 NSMenu
* pDock
= AquaSalInstance::GetDynamicDockMenu();
354 if ([pDock numberOfItems
] != 0) {
355 NSMenuItem
* pTopItem
= [pDock itemAtIndex
: 0];
356 if ( [pTopItem hasSubmenu
] )
357 [pDock insertItem
: [NSMenuItem separatorItem
] atIndex
: 0];
360 mpDockMenuEntry
= [pDock insertItemWithTitle
: pTitle
361 action
: @
selector(dockMenuItemTriggered
:)
364 [mpDockMenuEntry setTarget
: mpNSWindow
];
366 // TODO: image (either the generic window image or an icon
367 // check mark (for "main" window ?)
370 [mpDockMenuEntry setTitle
: pTitle
];
377 void AquaSalFrame::SetIcon( sal_uInt16
)
381 void AquaSalFrame::SetRepresentedURL( const OUString
& i_rDocURL
)
383 OSX_SALDATA_RUNINMAIN( SetRepresentedURL( i_rDocURL
) )
385 if( comphelper::isFileUrl(i_rDocURL
) )
388 osl_getSystemPathFromFileURL( i_rDocURL
.pData
, &aSysPath
.pData
);
389 NSString
* pStr
= CreateNSString( aSysPath
);
393 [mpNSWindow setRepresentedFilename
: pStr
];
398 void AquaSalFrame::initShow()
400 OSX_SALDATA_RUNINMAIN( initShow() )
403 if( ! mbPositioned
&& ! mbFullScreen
)
405 tools::Rectangle aScreenRect
;
406 GetWorkArea( aScreenRect
);
407 if( mpParent
) // center relative to parent
410 tools::Long nNewX
= mpParent
->maGeometry
.x() + (static_cast<tools::Long
>(mpParent
->maGeometry
.width()) - static_cast<tools::Long
>(maGeometry
.width())) / 2;
411 if( nNewX
< aScreenRect
.Left() )
412 nNewX
= aScreenRect
.Left();
413 if (static_cast<tools::Long
>(nNewX
+ maGeometry
.width()) > aScreenRect
.Right())
414 nNewX
= aScreenRect
.Right() - maGeometry
.width() - 1;
415 tools::Long nNewY
= mpParent
->maGeometry
.y() + (static_cast<tools::Long
>(mpParent
->maGeometry
.height()) - static_cast<tools::Long
>(maGeometry
.height())) / 2;
416 if( nNewY
< aScreenRect
.Top() )
417 nNewY
= aScreenRect
.Top();
418 if( nNewY
> aScreenRect
.Bottom() )
419 nNewY
= aScreenRect
.Bottom() - maGeometry
.height() - 1;
420 SetPosSize( nNewX
- mpParent
->maGeometry
.x(),
421 nNewY
- mpParent
->maGeometry
.y(),
422 0, 0, SAL_FRAME_POSSIZE_X
| SAL_FRAME_POSSIZE_Y
);
424 else if( ! (mnStyle
& SalFrameStyleFlags::SIZEABLE
) )
427 tools::Long nNewX
= (aScreenRect
.GetWidth() - maGeometry
.width()) / 2;
428 tools::Long nNewY
= (aScreenRect
.GetHeight() - maGeometry
.height()) / 2;
429 SetPosSize( nNewX
, nNewY
, 0, 0, SAL_FRAME_POSSIZE_X
| SAL_FRAME_POSSIZE_Y
);
433 // make sure the view is present in the wrapper list before any children receive focus
434 if (mpNSView
&& [mpNSView isKindOfClass
:[SalFrameView
class]])
435 [static_cast<SalFrameView
*>(mpNSView
) registerWrapper
];
438 void AquaSalFrame::SendPaintEvent( const tools::Rectangle
* pRect
)
440 OSX_SALDATA_RUNINMAIN( SendPaintEvent( pRect
) )
442 SalPaintEvent
aPaintEvt(0, 0, maGeometry
.width(), maGeometry
.height(), true);
445 aPaintEvt
.mnBoundX
= pRect
->Left();
446 aPaintEvt
.mnBoundY
= pRect
->Top();
447 aPaintEvt
.mnBoundWidth
= pRect
->GetWidth();
448 aPaintEvt
.mnBoundHeight
= pRect
->GetHeight();
451 CallCallback(SalEvent::Paint
, &aPaintEvt
);
454 void AquaSalFrame::Show(bool bVisible
, bool bNoActivate
)
459 OSX_SALDATA_RUNINMAIN( Show(bVisible
, bNoActivate
) )
461 // tdf#152173 Don't display tooltip windows when application is inactive
462 // Starting with macOS 13 Ventura, inactive applications receive mouse
463 // move events so when LibreOffice is inactive, a mouse move event causes
464 // a tooltip to be displayed. Since the tooltip window is attached to its
465 // parent window (to ensure that the tooltip is above the parent window),
466 // displaying a tooltip pulls the parent window in front of the windows
467 // of all other inactive applications.
468 // Also, don't display tooltips when mousing over non-key windows even if
469 // the application is active as the tooltip window will pull the non-key
470 // window in front of the key window.
471 if (bVisible
&& (mnStyle
& SalFrameStyleFlags::TOOLTIP
))
473 if (![NSApp isActive
])
478 // tdf#157565 show tooltip if any parent window is the key window
479 bool bKeyWindowFound
= false;
480 NSWindow
*pParent
= mpParent
->mpNSWindow
;
483 if ([pParent isKeyWindow
])
485 bKeyWindowFound
= true;
488 pParent
= [pParent parentWindow
];
490 if (!bKeyWindowFound
)
501 CallCallback(SalEvent::Resize
, nullptr);
502 // trigger filling our backbuffer
505 if( bNoActivate
|| [mpNSWindow canBecomeKeyWindow
] == NO
)
506 [mpNSWindow orderFront
: NSApp
];
508 [mpNSWindow makeKeyAndOrderFront
: NSApp
];
512 /* #i92674# #i96433# we do not want an invisible parent to show up (which adding a visible
513 child implicitly does). However we also do not want a parentless toolbar.
515 HACK: try to decide when we should not insert a child to its parent
516 floaters and ownerdraw windows have not yet shown up in cases where
517 we don't want the parent to become visible
519 if( mpParent
->mbShown
|| (mnStyle
& (SalFrameStyleFlags::OWNERDRAWDECORATION
| SalFrameStyleFlags::FLOAT
) ) )
521 [mpParent
->mpNSWindow addChildWindow
: mpNSWindow ordered
: NSWindowAbove
];
526 [mpNSWindow makeMainWindow
];
530 // if the frame holding the current menubar gets hidden
531 // show the default menubar
532 if( mpMenu
&& mpMenu
->mbMenuBar
&& AquaSalMenu::pCurrentMenuBar
== mpMenu
)
533 AquaSalMenu::setDefaultMenu();
535 // #i90440# #i94443# work around the focus going back to some other window
536 // if a child gets hidden for a parent window
537 if( mpParent
&& mpParent
->mbShown
&& [mpNSWindow isKeyWindow
] )
538 [mpParent
->mpNSWindow makeKeyAndOrderFront
: NSApp
];
540 [SalFrameView unsetMouseFrame
: this];
541 if( mpParent
&& [mpNSWindow parentWindow
] == mpParent
->mpNSWindow
)
542 [mpParent
->mpNSWindow removeChildWindow
: mpNSWindow
];
544 [mpNSWindow orderOut
: NSApp
];
548 void AquaSalFrame::SetMinClientSize( tools::Long nWidth
, tools::Long nHeight
)
550 OSX_SALDATA_RUNINMAIN( SetMinClientSize( nWidth
, nHeight
) )
553 mnMinHeight
= nHeight
;
557 // Always add the decoration as the dimension concerns only
558 // the content rectangle
559 nWidth
+= maGeometry
.leftDecoration() + maGeometry
.rightDecoration();
560 nHeight
+= maGeometry
.topDecoration() + maGeometry
.bottomDecoration();
562 NSSize aSize
= { static_cast<CGFloat
>(nWidth
), static_cast<CGFloat
>(nHeight
) };
564 // Size of full window (content+structure) although we only
565 // have the client size in arguments
566 [mpNSWindow setMinSize
: aSize
];
570 void AquaSalFrame::SetMaxClientSize( tools::Long nWidth
, tools::Long nHeight
)
572 OSX_SALDATA_RUNINMAIN( SetMaxClientSize( nWidth
, nHeight
) )
575 mnMaxHeight
= nHeight
;
579 // Always add the decoration as the dimension concerns only
580 // the content rectangle
581 nWidth
+= maGeometry
.leftDecoration() + maGeometry
.rightDecoration();
582 nHeight
+= maGeometry
.topDecoration() + maGeometry
.bottomDecoration();
584 // Carbon windows can't have a size greater than 32767x32767
585 if (nWidth
>32767) nWidth
=32767;
586 if (nHeight
>32767) nHeight
=32767;
588 NSSize aSize
= { static_cast<CGFloat
>(nWidth
), static_cast<CGFloat
>(nHeight
) };
590 // Size of full window (content+structure) although we only
591 // have the client size in arguments
592 [mpNSWindow setMaxSize
: aSize
];
596 void AquaSalFrame::GetClientSize( tools::Long
& rWidth
, tools::Long
& rHeight
)
598 if (mbShown
|| mbInitShow
|| Application::IsBitmapRendering())
600 rWidth
= maGeometry
.width();
601 rHeight
= maGeometry
.height();
610 SalEvent
AquaSalFrame::PreparePosSize(tools::Long nX
, tools::Long nY
, tools::Long nWidth
, tools::Long nHeight
, sal_uInt16 nFlags
)
612 SalEvent nEvent
= SalEvent::NONE
;
613 assert(mpNSWindow
|| Application::IsBitmapRendering());
615 if (nFlags
& (SAL_FRAME_POSSIZE_X
| SAL_FRAME_POSSIZE_Y
))
618 nEvent
= SalEvent::Move
;
621 if (nFlags
& (SAL_FRAME_POSSIZE_WIDTH
| SAL_FRAME_POSSIZE_HEIGHT
))
624 nEvent
= (nEvent
== SalEvent::Move
) ? SalEvent::MoveResize
: SalEvent::Resize
;
627 if (Application::IsBitmapRendering())
629 if (nFlags
& SAL_FRAME_POSSIZE_X
)
631 if (nFlags
& SAL_FRAME_POSSIZE_Y
)
633 if (nFlags
& SAL_FRAME_POSSIZE_WIDTH
)
635 maGeometry
.setWidth(nWidth
);
636 if (mnMaxWidth
> 0 && maGeometry
.width() > mnMaxWidth
)
637 maGeometry
.setWidth(mnMaxWidth
);
638 if (mnMinWidth
> 0 && maGeometry
.width() < mnMinWidth
)
639 maGeometry
.setWidth(mnMinWidth
);
641 if (nFlags
& SAL_FRAME_POSSIZE_HEIGHT
)
643 maGeometry
.setHeight(nHeight
);
644 if (mnMaxHeight
> 0 && maGeometry
.height() > mnMaxHeight
)
645 maGeometry
.setHeight(mnMaxHeight
);
646 if (mnMinHeight
> 0 && maGeometry
.height() < mnMinHeight
)
647 maGeometry
.setHeight(mnMinHeight
);
649 if (nEvent
!= SalEvent::NONE
)
650 CallCallback(nEvent
, nullptr);
656 void AquaSalFrame::SetWindowState(const vcl::WindowData
* pState
)
658 if (!mpNSWindow
&& !Application::IsBitmapRendering())
661 OSX_SALDATA_RUNINMAIN( SetWindowState( pState
) )
663 sal_uInt16 nFlags
= 0;
664 nFlags
|= ((pState
->mask() & vcl::WindowDataMask::X
) ? SAL_FRAME_POSSIZE_X
: 0);
665 nFlags
|= ((pState
->mask() & vcl::WindowDataMask::Y
) ? SAL_FRAME_POSSIZE_Y
: 0);
666 nFlags
|= ((pState
->mask() & vcl::WindowDataMask::Width
) ? SAL_FRAME_POSSIZE_WIDTH
: 0);
667 nFlags
|= ((pState
->mask() & vcl::WindowDataMask::Height
) ? SAL_FRAME_POSSIZE_HEIGHT
: 0);
669 SalEvent nEvent
= PreparePosSize(pState
->x(), pState
->y(), pState
->width(), pState
->height(), nFlags
);
670 if (Application::IsBitmapRendering())
674 NSRect aStateRect
= [mpNSWindow frame
];
675 aStateRect
= [NSWindow contentRectForFrameRect
: aStateRect styleMask
: mnStyleMask
];
676 CocoaToVCL(aStateRect
);
677 if (pState
->mask() & vcl::WindowDataMask::X
)
678 aStateRect
.origin
.x
= float(pState
->x());
679 if (pState
->mask() & vcl::WindowDataMask::Y
)
680 aStateRect
.origin
.y
= float(pState
->y());
681 if (pState
->mask() & vcl::WindowDataMask::Width
)
682 aStateRect
.size
.width
= float(pState
->width());
683 if (pState
->mask() & vcl::WindowDataMask::Height
)
684 aStateRect
.size
.height
= float(pState
->height());
685 VCLToCocoa(aStateRect
);
686 aStateRect
= [NSWindow frameRectForContentRect
: aStateRect styleMask
: mnStyleMask
];
687 [mpNSWindow setFrame
: aStateRect display
: NO
];
689 if (pState
->state() == vcl::WindowState::Minimized
)
690 [mpNSWindow miniaturize
: NSApp
];
691 else if ([mpNSWindow isMiniaturized
])
692 [mpNSWindow deminiaturize
: NSApp
];
694 /* ZOOMED is not really maximized (actually it toggles between a user set size and
695 the program specified one), but comes closest since the default behavior is
696 "maximized" if the user did not intervene
698 if (pState
->state() == vcl::WindowState::Maximized
)
700 if (![mpNSWindow isZoomed
])
701 [mpNSWindow zoom
: NSApp
];
705 if ([mpNSWindow isZoomed
])
706 [mpNSWindow zoom
: NSApp
];
710 UpdateFrameGeometry();
712 // send event that we were moved/sized
713 if( nEvent
!= SalEvent::NONE
)
714 CallCallback( nEvent
, nullptr );
718 // trigger filling our backbuffer
721 // tell the system the views need to be updated
722 [mpNSWindow display
];
726 bool AquaSalFrame::GetWindowState(vcl::WindowData
* pState
)
730 if (Application::IsBitmapRendering())
732 pState
->setMask(vcl::WindowDataMask::PosSizeState
);
733 pState
->setPosSize(maGeometry
.posSize());
734 pState
->setState(vcl::WindowState::Normal
);
740 OSX_SALDATA_RUNINMAIN_UNION( GetWindowState( pState
), boolean
)
742 pState
->setMask(vcl::WindowDataMask::PosSizeState
);
744 NSRect aStateRect
= [mpNSWindow frame
];
745 aStateRect
= [NSWindow contentRectForFrameRect
: aStateRect styleMask
: mnStyleMask
];
746 CocoaToVCL( aStateRect
);
747 pState
->setX(static_cast<sal_Int32
>(aStateRect
.origin
.x
));
748 pState
->setY(static_cast<sal_Int32
>(aStateRect
.origin
.y
));
749 pState
->setWidth(static_cast<sal_uInt32
>(aStateRect
.size
.width
));
750 pState
->setHeight(static_cast<sal_uInt32
>(aStateRect
.size
.height
));
752 if( [mpNSWindow isMiniaturized
] )
753 pState
->setState(vcl::WindowState::Minimized
);
754 else if( ! [mpNSWindow isZoomed
] )
755 pState
->setState(vcl::WindowState::Normal
);
757 pState
->setState(vcl::WindowState::Maximized
);
762 void AquaSalFrame::SetScreenNumber(unsigned int nScreen
)
767 OSX_SALDATA_RUNINMAIN( SetScreenNumber( nScreen
) )
769 NSArray
* pScreens
= [NSScreen screens
];
770 NSScreen
* pScreen
= nil
;
771 if( pScreens
&& nScreen
< [pScreens count
] )
773 // get new screen frame
774 pScreen
= [pScreens objectAtIndex
: nScreen
];
775 NSRect aNewScreen
= [pScreen frame
];
777 // get current screen frame
778 pScreen
= [mpNSWindow screen
];
781 NSRect aCurScreen
= [pScreen frame
];
782 if( aCurScreen
.origin
.x
!= aNewScreen
.origin
.x
||
783 aCurScreen
.origin
.y
!= aNewScreen
.origin
.y
)
785 NSRect aFrameRect
= [mpNSWindow frame
];
786 aFrameRect
.origin
.x
+= aNewScreen
.origin
.x
- aCurScreen
.origin
.x
;
787 aFrameRect
.origin
.y
+= aNewScreen
.origin
.y
- aCurScreen
.origin
.y
;
788 [mpNSWindow setFrame
: aFrameRect display
: NO
];
789 UpdateFrameGeometry();
795 void AquaSalFrame::SetApplicationID( const OUString
&/*rApplicationID*/ )
799 void AquaSalFrame::ShowFullScreen( bool bFullScreen
, sal_Int32 nDisplay
)
801 doShowFullScreen(bFullScreen
, nDisplay
);
804 void AquaSalFrame::doShowFullScreen( bool bFullScreen
, sal_Int32 nDisplay
)
808 if (Application::IsBitmapRendering() && bFullScreen
)
809 SetPosSize(0, 0, 1024, 768, SAL_FRAME_POSSIZE_WIDTH
| SAL_FRAME_POSSIZE_HEIGHT
);
813 SAL_INFO("vcl.osx", __func__
<< ": mbFullScreen=" << mbFullScreen
<< ", bFullScreen=" << bFullScreen
);
815 if( mbFullScreen
== bFullScreen
)
818 OSX_SALDATA_RUNINMAIN( ShowFullScreen( bFullScreen
, nDisplay
) )
820 mbFullScreen
= bFullScreen
;
824 // hide the dock and the menubar if we are on the menu screen
825 // which is always on index 0 according to documentation
826 bool bHideMenu
= (nDisplay
== 0);
828 NSRect aNewContentRect
= NSZeroRect
;
829 // get correct screen
830 NSScreen
* pScreen
= nil
;
831 NSArray
* pScreens
= [NSScreen screens
];
834 if( nDisplay
>= 0 && o3tl::make_unsigned(nDisplay
) < [pScreens count
] )
835 pScreen
= [pScreens objectAtIndex
: nDisplay
];
838 // this means span all screens
840 NSEnumerator
* pEnum
= [pScreens objectEnumerator
];
841 while( (pScreen
= [pEnum nextObject
]) != nil
)
843 NSRect aScreenRect
= [pScreen frame
];
844 if( aScreenRect
.origin
.x
< aNewContentRect
.origin
.x
)
846 aNewContentRect
.size
.width
+= aNewContentRect
.origin
.x
- aScreenRect
.origin
.x
;
847 aNewContentRect
.origin
.x
= aScreenRect
.origin
.x
;
849 if( aScreenRect
.origin
.y
< aNewContentRect
.origin
.y
)
851 aNewContentRect
.size
.height
+= aNewContentRect
.origin
.y
- aScreenRect
.origin
.y
;
852 aNewContentRect
.origin
.y
= aScreenRect
.origin
.y
;
854 if( aScreenRect
.origin
.x
+ aScreenRect
.size
.width
> aNewContentRect
.origin
.x
+ aNewContentRect
.size
.width
)
855 aNewContentRect
.size
.width
= aScreenRect
.origin
.x
+ aScreenRect
.size
.width
- aNewContentRect
.origin
.x
;
856 if( aScreenRect
.origin
.y
+ aScreenRect
.size
.height
> aNewContentRect
.origin
.y
+ aNewContentRect
.size
.height
)
857 aNewContentRect
.size
.height
= aScreenRect
.origin
.y
+ aScreenRect
.size
.height
- aNewContentRect
.origin
.y
;
861 if( aNewContentRect
.size
.width
== 0 && aNewContentRect
.size
.height
== 0 )
864 pScreen
= [mpNSWindow screen
];
866 pScreen
= [NSScreen mainScreen
];
868 aNewContentRect
= [pScreen frame
];
872 [NSMenu setMenuBarVisible
:NO
];
874 maFullScreenRect
= [mpNSWindow frame
];
876 [mpNSWindow setFrame
: [NSWindow frameRectForContentRect
: aNewContentRect styleMask
: mnStyleMask
] display
: mbShown
? YES
: NO
];
880 [mpNSWindow setFrame
: maFullScreenRect display
: mbShown
? YES
: NO
];
882 // show the dock and the menubar
883 [NSMenu setMenuBarVisible
:YES
];
886 UpdateFrameGeometry();
889 CallCallback(SalEvent::MoveResize
, nullptr);
891 // trigger filling our backbuffer
896 void AquaSalFrame::StartPresentation( bool bStart
)
901 OSX_SALDATA_RUNINMAIN( StartPresentation( bStart
) )
905 GetSalData()->maPresentationFrames
.push_back( this );
906 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep
,
907 kIOPMAssertionLevelOn
,
908 CFSTR("LibreOffice presentation running"),
910 [mpNSWindow setLevel
: NSPopUpMenuWindowLevel
];
912 [mpNSWindow makeMainWindow
];
916 GetSalData()->maPresentationFrames
.remove( this );
917 IOPMAssertionRelease(mnAssertionID
);
918 [mpNSWindow setLevel
: NSNormalWindowLevel
];
922 void AquaSalFrame::SetAlwaysOnTop( bool )
926 void AquaSalFrame::ToTop(SalFrameToTop nFlags
)
931 OSX_SALDATA_RUNINMAIN( ToTop( nFlags
) )
933 if( ! (nFlags
& SalFrameToTop::RestoreWhenMin
) )
935 if( ! [mpNSWindow isVisible
] || [mpNSWindow isMiniaturized
] )
938 if( nFlags
& SalFrameToTop::GrabFocus
)
939 [mpNSWindow makeKeyAndOrderFront
: NSApp
];
941 [mpNSWindow orderFront
: NSApp
];
944 NSCursor
* AquaSalFrame::getCurrentCursor()
946 OSX_SALDATA_RUNINMAIN_POINTER( getCurrentCursor(), NSCursor
* )
948 NSCursor
* pCursor
= nil
;
949 switch( mePointerStyle
)
951 case PointerStyle::Text
: pCursor
= [NSCursor IBeamCursor
]; break;
952 case PointerStyle::Cross
: pCursor
= [NSCursor crosshairCursor
]; break;
953 case PointerStyle::Hand
:
954 case PointerStyle::Move
: pCursor
= [NSCursor openHandCursor
]; break;
955 case PointerStyle::NSize
: pCursor
= [NSCursor resizeUpCursor
]; break;
956 case PointerStyle::SSize
: pCursor
= [NSCursor resizeDownCursor
]; break;
957 case PointerStyle::ESize
: pCursor
= [NSCursor resizeRightCursor
]; break;
958 case PointerStyle::WSize
: pCursor
= [NSCursor resizeLeftCursor
]; break;
959 case PointerStyle::Arrow
: pCursor
= [NSCursor arrowCursor
]; break;
960 case PointerStyle::VSplit
:
961 case PointerStyle::VSizeBar
:
962 case PointerStyle::WindowNSize
:
963 case PointerStyle::WindowSSize
:
964 pCursor
= [NSCursor resizeUpDownCursor
]; break;
965 case PointerStyle::HSplit
:
966 case PointerStyle::HSizeBar
:
967 case PointerStyle::WindowESize
:
968 case PointerStyle::WindowWSize
:
969 pCursor
= [NSCursor resizeLeftRightCursor
]; break;
970 case PointerStyle::RefHand
: pCursor
= [NSCursor pointingHandCursor
]; break;
973 pCursor
= GetSalData()->getCursor( mePointerStyle
);
976 assert( false && "unmapped cursor" );
977 pCursor
= [NSCursor arrowCursor
];
984 void AquaSalFrame::SetPointer( PointerStyle ePointerStyle
)
988 if( ePointerStyle
== mePointerStyle
)
991 OSX_SALDATA_RUNINMAIN( SetPointer( ePointerStyle
) )
993 mePointerStyle
= ePointerStyle
;
995 [mpNSWindow invalidateCursorRectsForView
: mpNSView
];
998 void AquaSalFrame::SetPointerPos( tools::Long nX
, tools::Long nY
)
1000 OSX_SALDATA_RUNINMAIN( SetPointerPos( nX
, nY
) )
1002 // FIXME: use Cocoa functions
1003 // FIXME: multiscreen support
1004 CGPoint aPoint
= { static_cast<CGFloat
>(nX
+ maGeometry
.x()), static_cast<CGFloat
>(nY
+ maGeometry
.y()) };
1005 CGDirectDisplayID mainDisplayID
= CGMainDisplayID();
1006 CGDisplayMoveCursorToPoint( mainDisplayID
, aPoint
);
1009 void AquaSalFrame::Flush()
1011 if( !(mbGraphics
&& mpGraphics
&& mpNSView
&& mbShown
) )
1014 OSX_SALDATA_RUNINMAIN( Flush() )
1016 [mpNSView setNeedsDisplay
: YES
];
1018 // outside of the application's event loop (e.g. IntroWindow)
1019 // nothing would trigger paint event handling
1020 // => fall back to synchronous painting
1021 if( ImplGetSVData()->maAppData
.mnDispatchLevel
<= 0 )
1023 mpGraphics
->Flush();
1028 void AquaSalFrame::Flush( const tools::Rectangle
& rRect
)
1030 if( !(mbGraphics
&& mpGraphics
&& mpNSView
&& mbShown
) )
1033 OSX_SALDATA_RUNINMAIN( Flush( rRect
) )
1035 NSRect aNSRect
= { { static_cast<CGFloat
>(rRect
.Left()), static_cast<CGFloat
>(rRect
.Top()) }, { static_cast<CGFloat
>(rRect
.GetWidth()), static_cast<CGFloat
>(rRect
.GetHeight()) } };
1036 VCLToCocoa( aNSRect
, false );
1037 [mpNSView setNeedsDisplayInRect
: aNSRect
];
1039 // outside of the application's event loop (e.g. IntroWindow)
1040 // nothing would trigger paint event handling
1041 // => fall back to synchronous painting
1042 if( ImplGetSVData()->maAppData
.mnDispatchLevel
<= 0 )
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_COLON
] = ":";
1122 /* yet unmapped KEYCODES:
1123 aKeyMap[ KEY_INSERT ] = OUString( sal_Unicode( ) );
1124 aKeyMap[ KEY_CUT ] = OUString( sal_Unicode( ) );
1125 aKeyMap[ KEY_COPY ] = OUString( sal_Unicode( ) );
1126 aKeyMap[ KEY_PASTE ] = OUString( sal_Unicode( ) );
1127 aKeyMap[ KEY_UNDO ] = OUString( sal_Unicode( ) );
1128 aKeyMap[ KEY_REPEAT ] = OUString( sal_Unicode( ) );
1129 aKeyMap[ KEY_FIND ] = OUString( sal_Unicode( ) );
1130 aKeyMap[ KEY_PROPERTIES ] = OUString( sal_Unicode( ) );
1131 aKeyMap[ KEY_FRONT ] = OUString( sal_Unicode( ) );
1132 aKeyMap[ KEY_CONTEXTMENU ] = OUString( sal_Unicode( ) );
1133 aKeyMap[ KEY_MENU ] = OUString( sal_Unicode( ) );
1134 aKeyMap[ KEY_HELP ] = OUString( sal_Unicode( ) );
1135 aKeyMap[ KEY_HANGUL_HANJA ] = OUString( sal_Unicode( ) );
1136 aKeyMap[ KEY_DECIMAL ] = OUString( sal_Unicode( ) );
1137 aKeyMap[ KEY_QUOTELEFT ]= OUString( sal_Unicode( ) );
1138 aKeyMap[ KEY_CAPSLOCK ]= OUString( sal_Unicode( ) );
1139 aKeyMap[ KEY_NUMLOCK ]= OUString( sal_Unicode( ) );
1140 aKeyMap[ KEY_SCROLLLOCK ]= OUString( sal_Unicode( ) );
1145 OUStringBuffer
aResult( 16 );
1147 sal_uInt16 nUnmodifiedCode
= (nKeyCode
& KEY_CODE_MASK
);
1148 std::map
< sal_uInt16
, OUString
>::const_iterator it
= aKeyMap
.find( nUnmodifiedCode
);
1149 if( it
!= aKeyMap
.end() )
1151 if( (nKeyCode
& KEY_SHIFT
) != 0 )
1152 aResult
.append( u
'\x21e7' ); // shift
1153 if( (nKeyCode
& KEY_MOD1
) != 0 )
1154 aResult
.append( u
'\x2318' ); // command
1155 if( (nKeyCode
& KEY_MOD2
) != 0 )
1156 aResult
.append( u
'\x2325' ); // alternate
1157 if( (nKeyCode
& KEY_MOD3
) != 0 )
1158 aResult
.append( u
'\x2303' ); // control
1160 aResult
.append( it
->second
);
1163 return aResult
.makeStringAndClear();
1166 static void getAppleScrollBarVariant(StyleSettings
&rSettings
)
1168 bool bIsScrollbarDoubleMax
= true; // default is DoubleMax
1170 CFStringRef AppleScrollBarType
= CFSTR("AppleScrollBarVariant");
1171 if( AppleScrollBarType
)
1173 CFStringRef ScrollBarVariant
= static_cast<CFStringRef
>(CFPreferencesCopyAppValue( AppleScrollBarType
, kCFPreferencesCurrentApplication
));
1174 if( ScrollBarVariant
)
1176 if( CFGetTypeID( ScrollBarVariant
) == CFStringGetTypeID() )
1178 // TODO: check for the less important variants "DoubleMin" and "DoubleBoth" too
1179 CFStringRef DoubleMax
= CFSTR("DoubleMax");
1182 if ( !CFStringCompare(ScrollBarVariant
, DoubleMax
, kCFCompareCaseInsensitive
) )
1183 bIsScrollbarDoubleMax
= true;
1185 bIsScrollbarDoubleMax
= false;
1186 CFRelease(DoubleMax
);
1189 CFRelease( ScrollBarVariant
);
1191 CFRelease(AppleScrollBarType
);
1194 GetSalData()->mbIsScrollbarDoubleMax
= bIsScrollbarDoubleMax
;
1196 CFStringRef jumpScroll
= CFSTR("AppleScrollerPagingBehavior");
1199 CFBooleanRef jumpStr
= static_cast<CFBooleanRef
>(CFPreferencesCopyAppValue( jumpScroll
, kCFPreferencesCurrentApplication
));
1202 if( CFGetTypeID( jumpStr
) == CFBooleanGetTypeID() )
1203 rSettings
.SetPrimaryButtonWarpsSlider(jumpStr
== kCFBooleanTrue
);
1204 CFRelease( jumpStr
);
1206 CFRelease( jumpScroll
);
1210 static Color
getNSBoxBackgroundColor(NSColor
* pSysColor
)
1212 // Figuring out what a NSBox will draw for windowBackground, etc. seems very difficult.
1213 // So just draw to a 1x1 surface and read what actually gets drawn
1214 // This is similar to getPixel
1215 #if defined OSL_BIGENDIAN
1218 unsigned char b
, g
, r
, a
;
1223 unsigned char a
, r
, g
, b
;
1227 // create a one-pixel bitmap context
1228 CGContextRef xOnePixelContext
= CGBitmapContextCreate(
1229 &aPixel
, 1, 1, 8, 32, GetSalData()->mxRGBSpace
,
1230 uint32_t(kCGImageAlphaNoneSkipFirst
) | uint32_t(kCGBitmapByteOrder32Big
));
1232 NSGraphicsContext
* graphicsContext
= [NSGraphicsContext graphicsContextWithCGContext
:xOnePixelContext flipped
:NO
];
1234 NSRect rect
= { NSZeroPoint
, NSMakeSize(1, 1) };
1235 NSBox
* pBox
= [[NSBox alloc
] initWithFrame
: rect
];
1237 [pBox setBoxType
: NSBoxCustom
];
1238 [pBox setFillColor
: pSysColor
];
1239 SAL_WNODEPRECATED_DECLARATIONS_PUSH
// setBorderType first deprecated in macOS 10.15
1240 [pBox setBorderType
: NSNoBorder
];
1241 SAL_WNODEPRECATED_DECLARATIONS_POP
1243 [pBox displayRectIgnoringOpacity
: rect inContext
: graphicsContext
];
1247 CGContextRelease(xOnePixelContext
);
1249 return Color(aPixel
.r
, aPixel
.g
, aPixel
.b
);
1252 static Color
getColor( NSColor
* pSysColor
, const Color
& rDefault
, NSWindow
* pWin
)
1254 Color
aRet( rDefault
);
1258 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1259 // "'colorUsingColorSpaceName:device:' is deprecated: first deprecated in macOS 10.14 -
1260 // Use -colorUsingType: or -colorUsingColorSpace: instead"
1261 NSColor
* pRBGColor
= [pSysColor colorUsingColorSpaceName
: NSDeviceRGBColorSpace device
: [pWin deviceDescription
]];
1262 SAL_WNODEPRECATED_DECLARATIONS_POP
1265 CGFloat r
= 0, g
= 0, b
= 0, a
= 0;
1266 [pRBGColor getRed
: &r green
: &g blue
: &b alpha
: &a
];
1267 aRet
= Color( int(r
*255.999), int(g
*255.999), int(b
*255.999) );
1273 static vcl::Font
getFont( NSFont
* pFont
, sal_Int32 nDPIY
, const vcl::Font
& rDefault
)
1275 vcl::Font
aResult( rDefault
);
1278 aResult
.SetFamilyName( GetOUString( [pFont familyName
] ) );
1279 aResult
.SetFontHeight( static_cast<int>(ceil([pFont pointSize
] * 72.0 / static_cast<float>(nDPIY
))) );
1280 aResult
.SetItalic( ([pFont italicAngle
] != 0.0) ? ITALIC_NORMAL
: ITALIC_NONE
);
1287 void AquaSalFrame::getResolution( sal_Int32
& o_rDPIX
, sal_Int32
& o_rDPIY
)
1289 OSX_SALDATA_RUNINMAIN( getResolution( o_rDPIX
, o_rDPIY
) )
1294 ReleaseGraphics( mpGraphics
);
1296 mpGraphics
->GetResolution( o_rDPIX
, o_rDPIY
);
1299 void AquaSalFrame::UpdateDarkMode()
1301 if (@
available(macOS
10.14, iOS
13, *))
1303 switch (MiscSettings::GetDarkMode())
1307 [NSApp setAppearance
: nil
];
1310 [NSApp setAppearance
: [NSAppearance appearanceNamed
: NSAppearanceNameAqua
]];
1313 [NSApp setAppearance
: [NSAppearance appearanceNamed
: NSAppearanceNameDarkAqua
]];
1319 bool AquaSalFrame::GetUseDarkMode() const
1323 bool bUseDarkMode(false);
1324 if (@
available(macOS
10.14, iOS
13, *))
1326 NSAppearanceName match
= [mpNSView
.effectiveAppearance bestMatchFromAppearancesWithNames
: @
[
1327 NSAppearanceNameAqua
, NSAppearanceNameDarkAqua
]];
1328 bUseDarkMode
= [match isEqualToString
: NSAppearanceNameDarkAqua
];
1330 return bUseDarkMode
;
1333 bool AquaSalFrame::GetUseReducedAnimation() const
1335 return [[NSWorkspace sharedWorkspace
] accessibilityDisplayShouldReduceMotion
];
1338 // on OSX-Aqua the style settings are independent of the frame, so it does
1339 // not really belong here. Since the connection to the Appearance_Manager
1340 // is currently done in salnativewidgets.cxx this would be a good place.
1341 // On the other hand VCL's platform independent code currently only asks
1342 // SalFrames for system settings anyway, so moving the code somewhere else
1343 // doesn't make the anything cleaner for now
1344 void AquaSalFrame::UpdateSettings( AllSettings
& rSettings
)
1349 OSX_SALDATA_RUNINMAIN( UpdateSettings( rSettings
) )
1351 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1352 // "'lockFocus' is deprecated: first deprecated in macOS 10.14 - To draw, subclass NSView
1353 // and implement -drawRect:; AppKit's automatic deferred display mechanism will call
1354 // -drawRect: as necessary to display the view."
1355 if (![mpNSView lockFocusIfCanDraw
])
1357 SAL_WNODEPRECATED_DECLARATIONS_POP
1359 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1360 // "'setCurrentAppearance:' is deprecated: first deprecated in macOS 12.0 - Use
1361 // -performAsCurrentDrawingAppearance: to temporarily set the drawing appearance, or
1362 // +currentDrawingAppearance to access the currently drawing appearance."
1363 [NSAppearance setCurrentAppearance
: mpNSView
.effectiveAppearance
];
1364 SAL_WNODEPRECATED_DECLARATIONS_POP
1366 StyleSettings aStyleSettings
= rSettings
.GetStyleSettings();
1368 bool bUseDarkMode(GetUseDarkMode());
1369 OUString
sThemeName(!bUseDarkMode
? u
"sukapura" : u
"sukapura_dark");
1370 aStyleSettings
.SetPreferredIconTheme(sThemeName
, bUseDarkMode
);
1372 Color
aControlBackgroundColor(getNSBoxBackgroundColor([NSColor controlBackgroundColor
]));
1373 Color
aWindowBackgroundColor(getNSBoxBackgroundColor([NSColor windowBackgroundColor
]));
1374 Color
aUnderPageBackgroundColor(getNSBoxBackgroundColor([NSColor underPageBackgroundColor
]));
1377 aStyleSettings
.BatchSetBackgrounds( aWindowBackgroundColor
, false );
1378 aStyleSettings
.SetLightBorderColor( aWindowBackgroundColor
);
1380 aStyleSettings
.SetActiveTabColor(aWindowBackgroundColor
);
1381 Color
aInactiveTabColor( aWindowBackgroundColor
);
1382 aInactiveTabColor
.DecreaseLuminance( 32 );
1383 aStyleSettings
.SetInactiveTabColor( aInactiveTabColor
);
1385 Color aShadowColor
= getColor( [NSColor systemGrayColor
],
1386 aStyleSettings
.GetShadowColor(), mpNSWindow
);
1387 aStyleSettings
.SetShadowColor( aShadowColor
);
1389 // tdf#152284 for DarkMode brighten it, while darken for BrightMode
1390 NSColor
* pDarkColor
= bUseDarkMode
? [[NSColor systemGrayColor
] highlightWithLevel
: 0.5]
1391 : [[NSColor systemGrayColor
] shadowWithLevel
: 0.5];
1392 Color aDarkShadowColor
= getColor( pDarkColor
, aStyleSettings
.GetDarkShadowColor(), mpNSWindow
);
1393 aStyleSettings
.SetDarkShadowColor(aDarkShadowColor
);
1395 // get the system font settings
1396 vcl::Font aAppFont
= aStyleSettings
.GetAppFont();
1397 sal_Int32 nDPIX
= 72, nDPIY
= 72;
1398 getResolution( nDPIX
, nDPIY
);
1399 aAppFont
= getFont( [NSFont systemFontOfSize
: 0], nDPIY
, aAppFont
);
1401 aStyleSettings
.SetToolbarIconSize( ToolbarIconSize::Large
);
1403 // TODO: better mapping of macOS<->LibreOffice font settings
1404 vcl::Font
aLabelFont( getFont( [NSFont labelFontOfSize
: 0], nDPIY
, aAppFont
) );
1405 aStyleSettings
.BatchSetFonts( aAppFont
, aLabelFont
);
1406 vcl::Font
aMenuFont( getFont( [NSFont menuFontOfSize
: 0], nDPIY
, aAppFont
) );
1407 aStyleSettings
.SetMenuFont( aMenuFont
);
1409 vcl::Font
aTitleFont( getFont( [NSFont titleBarFontOfSize
: 0], nDPIY
, aAppFont
) );
1410 aStyleSettings
.SetTitleFont( aTitleFont
);
1411 aStyleSettings
.SetFloatTitleFont( aTitleFont
);
1413 vcl::Font
aTooltipFont(getFont([NSFont toolTipsFontOfSize
: 0], nDPIY
, aAppFont
));
1414 aStyleSettings
.SetHelpFont(aTooltipFont
);
1416 Color
aAccentColor( getColor( [NSColor controlAccentColor
],
1417 aStyleSettings
.GetAccentColor(), mpNSWindow
) );
1418 aStyleSettings
.SetAccentColor( aAccentColor
);
1420 Color
aHighlightColor( getColor( [NSColor selectedTextBackgroundColor
],
1421 aStyleSettings
.GetHighlightColor(), mpNSWindow
) );
1422 aStyleSettings
.SetHighlightColor( aHighlightColor
);
1423 Color
aHighlightTextColor( getColor( [NSColor selectedTextColor
],
1424 aStyleSettings
.GetHighlightTextColor(), mpNSWindow
) );
1425 aStyleSettings
.SetHighlightTextColor( aHighlightTextColor
);
1427 aStyleSettings
.SetLinkColor(getColor( [NSColor linkColor
],
1428 aStyleSettings
.GetLinkColor(), mpNSWindow
) );
1429 aStyleSettings
.SetVisitedLinkColor(getColor( [NSColor purpleColor
],
1430 aStyleSettings
.GetVisitedLinkColor(), mpNSWindow
) );
1432 #pragma clang diagnostic push
1433 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1434 Color
aMenuHighlightColor( getColor( [NSColor selectedMenuItemColor
],
1435 aStyleSettings
.GetMenuHighlightColor(), mpNSWindow
) );
1436 #pragma clang diagnostic pop
1437 aStyleSettings
.SetMenuHighlightColor( aMenuHighlightColor
);
1438 Color
aMenuHighlightTextColor( getColor( [NSColor selectedMenuItemTextColor
],
1439 aStyleSettings
.GetMenuHighlightTextColor(), mpNSWindow
) );
1440 aStyleSettings
.SetMenuHighlightTextColor( aMenuHighlightTextColor
);
1442 aStyleSettings
.SetMenuColor( aWindowBackgroundColor
);
1443 Color
aMenuTextColor( getColor( [NSColor textColor
],
1444 aStyleSettings
.GetMenuTextColor(), mpNSWindow
) );
1445 aStyleSettings
.SetMenuTextColor( aMenuTextColor
);
1446 aStyleSettings
.SetMenuBarTextColor( aMenuTextColor
);
1447 aStyleSettings
.SetMenuBarRolloverTextColor( aMenuTextColor
);
1448 aStyleSettings
.SetMenuBarHighlightTextColor(aStyleSettings
.GetMenuHighlightTextColor());
1450 aStyleSettings
.SetListBoxWindowBackgroundColor( aWindowBackgroundColor
);
1451 aStyleSettings
.SetListBoxWindowTextColor( aMenuTextColor
);
1452 aStyleSettings
.SetListBoxWindowHighlightColor( aMenuHighlightColor
);
1453 aStyleSettings
.SetListBoxWindowHighlightTextColor( aMenuHighlightTextColor
);
1455 // FIXME: Starting with macOS Big Sur, coloring has changed. Currently there is no documentation which system color should be
1456 // used for some button states and for selected tab text. As a workaround the current OS version has to be considered. This code
1457 // has to be reviewed once issue is covered by documentation.
1459 // Set text colors for buttons and their different status according to OS settings, typically white for selected buttons,
1462 NSOperatingSystemVersion aOSVersion
= { .majorVersion
= 10, .minorVersion
= 16, .patchVersion
= 0 };
1463 Color
aControlTextColor(getColor([NSColor controlTextColor
], COL_BLACK
, mpNSWindow
));
1464 Color
aSelectedControlTextColor(getColor([NSColor selectedControlTextColor
], COL_BLACK
, mpNSWindow
));
1465 Color
aAlternateSelectedControlTextColor(getColor([NSColor alternateSelectedControlTextColor
], COL_WHITE
, mpNSWindow
));
1466 aStyleSettings
.SetWindowColor(aWindowBackgroundColor
);
1467 aStyleSettings
.SetListBoxWindowBackgroundColor(aWindowBackgroundColor
);
1469 aStyleSettings
.SetDialogTextColor(aControlTextColor
);
1470 aStyleSettings
.SetButtonTextColor(aControlTextColor
);
1471 aStyleSettings
.SetActionButtonTextColor(aControlTextColor
);
1472 aStyleSettings
.SetRadioCheckTextColor(aControlTextColor
);
1473 aStyleSettings
.SetGroupTextColor(aControlTextColor
);
1474 aStyleSettings
.SetLabelTextColor(aControlTextColor
);
1475 aStyleSettings
.SetWindowTextColor(aControlTextColor
);
1476 aStyleSettings
.SetFieldTextColor(aControlTextColor
);
1478 aStyleSettings
.SetFieldRolloverTextColor(aControlTextColor
);
1479 aStyleSettings
.SetFieldColor(aControlBackgroundColor
);
1480 aStyleSettings
.SetDefaultActionButtonTextColor(aAlternateSelectedControlTextColor
);
1481 aStyleSettings
.SetFlatButtonTextColor(aControlTextColor
);
1482 aStyleSettings
.SetDefaultButtonRolloverTextColor(aAlternateSelectedControlTextColor
);
1483 aStyleSettings
.SetButtonRolloverTextColor(aControlTextColor
);
1484 aStyleSettings
.SetDefaultActionButtonRolloverTextColor(aAlternateSelectedControlTextColor
);
1485 aStyleSettings
.SetActionButtonRolloverTextColor(aControlTextColor
);
1486 aStyleSettings
.SetFlatButtonRolloverTextColor(aControlTextColor
);
1487 aStyleSettings
.SetDefaultButtonPressedRolloverTextColor(aAlternateSelectedControlTextColor
);
1488 aStyleSettings
.SetDefaultActionButtonPressedRolloverTextColor(aAlternateSelectedControlTextColor
);
1489 aStyleSettings
.SetFlatButtonPressedRolloverTextColor(aControlTextColor
);
1490 if ([NSProcessInfo
.processInfo isOperatingSystemAtLeastVersion
: aOSVersion
])
1492 aStyleSettings
.SetDefaultButtonTextColor(aAlternateSelectedControlTextColor
);
1493 aStyleSettings
.SetButtonPressedRolloverTextColor(aSelectedControlTextColor
);
1494 aStyleSettings
.SetActionButtonPressedRolloverTextColor(aSelectedControlTextColor
);
1498 aStyleSettings
.SetButtonPressedRolloverTextColor(aAlternateSelectedControlTextColor
);
1499 aStyleSettings
.SetActionButtonPressedRolloverTextColor(aAlternateSelectedControlTextColor
);
1500 aStyleSettings
.SetDefaultButtonTextColor(aSelectedControlTextColor
);
1503 aStyleSettings
.SetWorkspaceColor(aUnderPageBackgroundColor
);
1505 aStyleSettings
.SetHelpColor(aControlBackgroundColor
);
1506 aStyleSettings
.SetHelpTextColor(aControlTextColor
);
1507 aStyleSettings
.SetToolTextColor(aControlTextColor
);
1509 // Set text colors for tabs according to OS settings
1511 aStyleSettings
.SetTabTextColor(aControlTextColor
);
1512 aStyleSettings
.SetTabRolloverTextColor(aControlTextColor
);
1513 if ([NSProcessInfo
.processInfo isOperatingSystemAtLeastVersion
: aOSVersion
])
1514 aStyleSettings
.SetTabHighlightTextColor(aSelectedControlTextColor
);
1516 aStyleSettings
.SetTabHighlightTextColor(aAlternateSelectedControlTextColor
);
1518 aStyleSettings
.SetCursorBlinkTime( mnBlinkCursorDelay
);
1519 aStyleSettings
.SetCursorSize(1);
1521 // no mnemonics on macOS
1522 aStyleSettings
.SetOptions( aStyleSettings
.GetOptions() | StyleSettingsOptions::NoMnemonics
);
1524 getAppleScrollBarVariant(aStyleSettings
);
1526 // set scrollbar size
1527 aStyleSettings
.SetScrollBarSize( static_cast<tools::Long
>([NSScroller scrollerWidthForControlSize
:NSControlSizeRegular scrollerStyle
:NSScrollerStyleLegacy
]) );
1528 // images in menus false for MacOSX
1529 aStyleSettings
.SetPreferredUseImagesInMenus( false );
1530 aStyleSettings
.SetHideDisabledMenuItems( true );
1531 aStyleSettings
.SetPreferredContextMenuShortcuts( false );
1533 rSettings
.SetStyleSettings( aStyleSettings
);
1535 // don't draw frame around each and every toolbar
1536 ImplGetSVData()->maNWFData
.mbDockingAreaAvoidTBFrames
= true;
1538 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1539 // "'unlockFocus' is deprecated: first deprecated in macOS 10.14 - To draw, subclass NSView
1540 // and implement -drawRect:; AppKit's automatic deferred display mechanism will call
1541 // -drawRect: as necessary to display the view."
1542 [mpNSView unlockFocus
];
1543 SAL_WNODEPRECATED_DECLARATIONS_POP
1546 const SystemEnvData
* AquaSalFrame::GetSystemData() const
1551 void AquaSalFrame::Beep()
1553 OSX_SALDATA_RUNINMAIN( Beep() )
1557 void AquaSalFrame::SetPosSize(
1558 tools::Long nX
, tools::Long nY
, tools::Long nWidth
, tools::Long nHeight
, sal_uInt16 nFlags
)
1560 if (!mpNSWindow
&& !Application::IsBitmapRendering())
1563 OSX_SALDATA_RUNINMAIN( SetPosSize( nX
, nY
, nWidth
, nHeight
, nFlags
) )
1565 SalEvent nEvent
= PreparePosSize(nX
, nY
, nWidth
, nHeight
, nFlags
);
1566 if (Application::IsBitmapRendering())
1569 if( [mpNSWindow isMiniaturized
] )
1570 [mpNSWindow deminiaturize
: NSApp
]; // expand the window
1572 NSRect aFrameRect
= [mpNSWindow frame
];
1573 NSRect aContentRect
= [NSWindow contentRectForFrameRect
: aFrameRect styleMask
: mnStyleMask
];
1575 // position is always relative to parent frame
1576 NSRect aParentContentRect
;
1580 if( AllSettings::GetLayoutRTL() )
1582 if( (nFlags
& SAL_FRAME_POSSIZE_WIDTH
) != 0 )
1583 nX
= static_cast<tools::Long
>(mpParent
->maGeometry
.width()) - nWidth
- 1 - nX
;
1585 nX
= static_cast<tools::Long
>(mpParent
->maGeometry
.width()) - aContentRect
.size
.width
- 1 - nX
;
1587 NSRect aParentFrameRect
= [mpParent
->mpNSWindow frame
];
1588 aParentContentRect
= [NSWindow contentRectForFrameRect
: aParentFrameRect styleMask
: mpParent
->mnStyleMask
];
1591 aParentContentRect
= maScreenRect
; // use screen if no parent
1593 CocoaToVCL( aContentRect
);
1594 CocoaToVCL( aParentContentRect
);
1596 bool bPaint
= false;
1597 if( (nFlags
& (SAL_FRAME_POSSIZE_WIDTH
| SAL_FRAME_POSSIZE_HEIGHT
)) != 0 )
1599 if( nWidth
!= aContentRect
.size
.width
|| nHeight
!= aContentRect
.size
.height
)
1603 // use old window pos if no new pos requested
1604 if( (nFlags
& SAL_FRAME_POSSIZE_X
) != 0 )
1605 aContentRect
.origin
.x
= nX
+ aParentContentRect
.origin
.x
;
1606 if( (nFlags
& SAL_FRAME_POSSIZE_Y
) != 0)
1607 aContentRect
.origin
.y
= nY
+ aParentContentRect
.origin
.y
;
1609 // use old size if no new size requested
1610 if( (nFlags
& SAL_FRAME_POSSIZE_WIDTH
) != 0 )
1611 aContentRect
.size
.width
= nWidth
;
1612 if( (nFlags
& SAL_FRAME_POSSIZE_HEIGHT
) != 0)
1613 aContentRect
.size
.height
= nHeight
;
1615 VCLToCocoa( aContentRect
);
1617 // do not display yet, we need to update our backbuffer
1619 [mpNSWindow setFrame
: [NSWindow frameRectForContentRect
: aContentRect styleMask
: mnStyleMask
] display
: NO
];
1622 UpdateFrameGeometry();
1624 if (nEvent
!= SalEvent::NONE
)
1625 CallCallback(nEvent
, nullptr);
1627 if( mbShown
&& bPaint
)
1629 // trigger filling our backbuffer
1632 // now inform the system that the views need to be drawn
1633 [mpNSWindow display
];
1637 void AquaSalFrame::GetWorkArea( tools::Rectangle
& rRect
)
1641 if (Application::IsBitmapRendering())
1642 rRect
= tools::Rectangle(Point(0, 0), Size(1024, 768));
1646 OSX_SALDATA_RUNINMAIN( GetWorkArea( rRect
) )
1648 NSScreen
* pScreen
= [mpNSWindow screen
];
1649 if( pScreen
== nil
)
1650 pScreen
= [NSScreen mainScreen
];
1651 NSRect aRect
= [pScreen visibleFrame
];
1652 CocoaToVCL( aRect
);
1653 rRect
.SetLeft( static_cast<tools::Long
>(aRect
.origin
.x
) );
1654 rRect
.SetTop( static_cast<tools::Long
>(aRect
.origin
.y
) );
1655 rRect
.SetRight( static_cast<tools::Long
>(aRect
.origin
.x
+ aRect
.size
.width
- 1) );
1656 rRect
.SetBottom( static_cast<tools::Long
>(aRect
.origin
.y
+ aRect
.size
.height
- 1) );
1659 SalFrame::SalPointerState
AquaSalFrame::GetPointerState()
1661 OSX_SALDATA_RUNINMAIN_UNION( GetPointerState(), state
)
1663 SalPointerState state
;
1667 NSPoint aPt
= [mpNSWindow mouseLocationOutsideOfEventStream
];
1668 CocoaToVCL( aPt
, false );
1669 state
.maPos
= Point(static_cast<tools::Long
>(aPt
.x
), static_cast<tools::Long
>(aPt
.y
));
1671 NSEvent
* pCur
= [NSApp currentEvent
];
1672 bool bMouseEvent
= false;
1676 switch( [pCur type
] )
1678 case NSEventTypeLeftMouseDown
:
1679 state
.mnState
|= MOUSE_LEFT
;
1681 case NSEventTypeLeftMouseUp
:
1683 case NSEventTypeRightMouseDown
:
1684 state
.mnState
|= MOUSE_RIGHT
;
1686 case NSEventTypeRightMouseUp
:
1688 case NSEventTypeOtherMouseDown
:
1689 state
.mnState
|= ([pCur buttonNumber
] == 2) ? MOUSE_MIDDLE
: 0;
1691 case NSEventTypeOtherMouseUp
:
1693 case NSEventTypeMouseMoved
:
1695 case NSEventTypeLeftMouseDragged
:
1696 state
.mnState
|= MOUSE_LEFT
;
1698 case NSEventTypeRightMouseDragged
:
1699 state
.mnState
|= MOUSE_RIGHT
;
1701 case NSEventTypeOtherMouseDragged
:
1702 state
.mnState
|= ([pCur buttonNumber
] == 2) ? MOUSE_MIDDLE
: 0;
1705 bMouseEvent
= false;
1711 unsigned int nMask
= static_cast<unsigned int>([pCur modifierFlags
]);
1712 if( (nMask
& NSEventModifierFlagShift
) != 0 )
1713 state
.mnState
|= KEY_SHIFT
;
1714 if( (nMask
& NSEventModifierFlagControl
) != 0 )
1715 state
.mnState
|= KEY_MOD3
;
1716 if( (nMask
& NSEventModifierFlagOption
) != 0 )
1717 state
.mnState
|= KEY_MOD2
;
1718 if( (nMask
& NSEventModifierFlagCommand
) != 0 )
1719 state
.mnState
|= KEY_MOD1
;
1724 // FIXME: replace Carbon by Cocoa
1725 // Cocoa does not have an equivalent for GetCurrentEventButtonState
1726 // and GetCurrentEventKeyModifiers.
1727 // we could try to get away with tracking all events for modifierKeys
1728 // and all mouse events for button state in VCL_NSApplication::sendEvent,
1729 // but it is unclear whether this will get us the same result.
1730 // leave in GetCurrentEventButtonState and GetCurrentEventKeyModifiers for now
1732 // fill in button state
1733 UInt32 nState
= GetCurrentEventButtonState();
1736 state
.mnState
|= MOUSE_LEFT
; // primary button
1738 state
.mnState
|= MOUSE_RIGHT
; // secondary button
1740 state
.mnState
|= MOUSE_MIDDLE
; // tertiary button
1742 // fill in modifier state
1743 nState
= GetCurrentEventKeyModifiers();
1744 if( nState
& shiftKey
)
1745 state
.mnState
|= KEY_SHIFT
;
1746 if( nState
& controlKey
)
1747 state
.mnState
|= KEY_MOD3
;
1748 if( nState
& optionKey
)
1749 state
.mnState
|= KEY_MOD2
;
1750 if( nState
& cmdKey
)
1751 state
.mnState
|= KEY_MOD1
;
1757 KeyIndicatorState
AquaSalFrame::GetIndicatorState()
1759 return KeyIndicatorState::NONE
;
1762 void AquaSalFrame::SimulateKeyPress( sal_uInt16
/*nKeyCode*/ )
1766 void AquaSalFrame::SetPluginParent( SystemParentData
* )
1768 // plugin parent may be killed unexpectedly by
1769 // plugging process;
1774 bool AquaSalFrame::MapUnicodeToKeyCode( sal_Unicode
, LanguageType
, vcl::KeyCode
& )
1776 // not supported yet
1780 LanguageType
AquaSalFrame::GetInputLanguage()
1783 return LANGUAGE_DONTKNOW
;
1786 void AquaSalFrame::SetMenu( SalMenu
* pSalMenu
)
1788 OSX_SALDATA_RUNINMAIN( SetMenu( pSalMenu
) )
1790 AquaSalMenu
* pMenu
= static_cast<AquaSalMenu
*>(pSalMenu
);
1791 SAL_WARN_IF( pMenu
&& !pMenu
->mbMenuBar
, "vcl", "setting non menubar on frame" );
1794 mpMenu
->setMainMenu();
1797 void AquaSalFrame::SetExtendedFrameStyle( SalExtStyle nStyle
)
1801 mnExtStyle
= nStyle
;
1805 OSX_SALDATA_RUNINMAIN( SetExtendedFrameStyle( nStyle
) )
1807 if( (mnExtStyle
& SAL_FRAME_EXT_STYLE_DOCMODIFIED
) != (nStyle
& SAL_FRAME_EXT_STYLE_DOCMODIFIED
) )
1808 [mpNSWindow setDocumentEdited
: (nStyle
& SAL_FRAME_EXT_STYLE_DOCMODIFIED
) ? YES
: NO
];
1810 mnExtStyle
= nStyle
;
1813 SalFrame
* AquaSalFrame::GetParent() const
1818 void AquaSalFrame::SetParent( SalFrame
* pNewParent
)
1820 bool bShown
= mbShown
;
1821 // remove from child list
1824 mpParent
= static_cast<AquaSalFrame
*>(pNewParent
);
1825 // insert to correct parent and paint
1829 void AquaSalFrame::UpdateFrameGeometry()
1831 bool bFirstTime
= (mnTrackingRectTag
== 0);
1832 mbGeometryDidChange
= false;
1837 OSX_SALDATA_RUNINMAIN( UpdateFrameGeometry() )
1839 // keep in mind that view and window coordinates are lower left
1840 // whereas vcl's are upper left
1842 // update screen rect
1843 NSScreen
* pScreen
= [mpNSWindow screen
];
1846 NSRect aNewScreenRect
= [pScreen frame
];
1847 if (bFirstTime
|| !NSEqualRects(maScreenRect
, aNewScreenRect
))
1849 mbGeometryDidChange
= true;
1850 maScreenRect
= aNewScreenRect
;
1852 NSArray
* pScreens
= [NSScreen screens
];
1855 unsigned int nNewDisplayScreenNumber
= [pScreens indexOfObject
: pScreen
];
1856 if (bFirstTime
|| maGeometry
.screen() != nNewDisplayScreenNumber
)
1858 mbGeometryDidChange
= true;
1859 maGeometry
.setScreen(nNewDisplayScreenNumber
);
1864 NSRect aFrameRect
= [mpNSWindow frame
];
1865 NSRect aContentRect
= [NSWindow contentRectForFrameRect
: aFrameRect styleMask
: mnStyleMask
];
1867 NSRect aTrackRect
= { NSZeroPoint
, aContentRect
.size
};
1869 if (bFirstTime
|| !NSEqualRects(maTrackingRect
, aTrackRect
))
1871 mbGeometryDidChange
= true;
1872 maTrackingRect
= aTrackRect
;
1874 // release old track rect
1875 [mpNSView removeTrackingRect
: mnTrackingRectTag
];
1876 // install the new track rect
1877 mnTrackingRectTag
= [mpNSView addTrackingRect
: aTrackRect owner
: mpNSView userData
: nil assumeInside
: NO
];
1880 // convert to vcl convention
1881 CocoaToVCL( aFrameRect
);
1882 CocoaToVCL( aContentRect
);
1884 if (bFirstTime
|| !NSEqualRects(maContentRect
, aContentRect
) || !NSEqualRects(maFrameRect
, aFrameRect
))
1886 mbGeometryDidChange
= true;
1888 maContentRect
= aContentRect
;
1889 maFrameRect
= aFrameRect
;
1891 maGeometry
.setX(static_cast<sal_Int32
>(aContentRect
.origin
.x
));
1892 maGeometry
.setY(static_cast<sal_Int32
>(aContentRect
.origin
.y
));
1893 maGeometry
.setWidth(static_cast<sal_uInt32
>(aContentRect
.size
.width
));
1894 maGeometry
.setHeight(static_cast<sal_uInt32
>(aContentRect
.size
.height
));
1896 maGeometry
.setLeftDecoration(static_cast<sal_uInt32
>(aContentRect
.origin
.x
- aFrameRect
.origin
.x
));
1897 maGeometry
.setRightDecoration(static_cast<sal_uInt32
>((aFrameRect
.origin
.x
+ aFrameRect
.size
.width
) -
1898 (aContentRect
.origin
.x
+ aContentRect
.size
.width
)));
1899 maGeometry
.setTopDecoration(static_cast<sal_uInt32
>(aContentRect
.origin
.y
- aFrameRect
.origin
.y
));
1900 maGeometry
.setBottomDecoration(static_cast<sal_uInt32
>((aFrameRect
.origin
.y
+ aFrameRect
.size
.height
) -
1901 (aContentRect
.origin
.y
+ aContentRect
.size
.height
)));
1905 void AquaSalFrame::CaptureMouse( bool bCapture
)
1908 we'll try to use a pidgin version of capture mouse
1909 on MacOSX (neither carbon nor cocoa) there is a
1910 CaptureMouse equivalent (in Carbon there is TrackMouseLocation
1911 but this is useless to use since it is blocking)
1913 However on cocoa the active frame seems to get mouse events
1914 also outside the window, so we'll try to forward mouse events
1915 to the capture frame in the hope that one of our frames
1918 This will break as soon as the user activates another app, but
1919 a mouse click will normally lead to a release of the mouse anyway.
1921 Let's see how far we get this way. Alternatively we could use one
1922 large overlay window like we did for the carbon implementation,
1923 however that is resource intensive.
1927 s_pCaptureFrame
= this;
1928 else if( ! bCapture
&& s_pCaptureFrame
== this )
1929 s_pCaptureFrame
= nullptr;
1932 void AquaSalFrame::ResetClipRegion()
1934 doResetClipRegion();
1937 void AquaSalFrame::doResetClipRegion()
1942 OSX_SALDATA_RUNINMAIN( ResetClipRegion() )
1944 // release old path and indicate no clipping
1945 CGPathRelease( mrClippingPath
);
1946 mrClippingPath
= nullptr;
1948 if( mpNSView
&& mbShown
)
1949 [mpNSView setNeedsDisplay
: YES
];
1950 [mpNSWindow setOpaque
: YES
];
1951 [mpNSWindow invalidateShadow
];
1954 void AquaSalFrame::BeginSetClipRegion( sal_uInt32 nRects
)
1959 OSX_SALDATA_RUNINMAIN( BeginSetClipRegion( nRects
) )
1962 if( mrClippingPath
)
1964 CGPathRelease( mrClippingPath
);
1965 mrClippingPath
= nullptr;
1968 if( maClippingRects
.size() > SAL_CLIPRECT_COUNT
&& nRects
< maClippingRects
.size() )
1970 std::vector
<CGRect
>().swap(maClippingRects
);
1972 maClippingRects
.clear();
1973 maClippingRects
.reserve( nRects
);
1976 void AquaSalFrame::UnionClipRegion(
1977 tools::Long nX
, tools::Long nY
, tools::Long nWidth
, tools::Long nHeight
)
1979 // #i113170# may not be the main thread if called from UNO API
1980 SalData::ensureThreadAutoreleasePool();
1982 if( nWidth
&& nHeight
)
1984 NSRect aRect
= { { static_cast<CGFloat
>(nX
), static_cast<CGFloat
>(nY
) }, { static_cast<CGFloat
>(nWidth
), static_cast<CGFloat
>(nHeight
) } };
1985 VCLToCocoa( aRect
, false );
1986 maClippingRects
.push_back( CGRectMake(aRect
.origin
.x
, aRect
.origin
.y
, aRect
.size
.width
, aRect
.size
.height
) );
1990 void AquaSalFrame::EndSetClipRegion()
1995 OSX_SALDATA_RUNINMAIN( EndSetClipRegion() )
1997 if( ! maClippingRects
.empty() )
1999 mrClippingPath
= CGPathCreateMutable();
2000 CGPathAddRects( mrClippingPath
, nullptr, maClippingRects
.data(), maClippingRects
.size() );
2002 if( mpNSView
&& mbShown
)
2003 [mpNSView setNeedsDisplay
: YES
];
2004 [mpNSWindow setOpaque
: (mrClippingPath
!= nullptr) ? NO
: YES
];
2005 [mpNSWindow setBackgroundColor
: [NSColor clearColor
]];
2006 // shadow is invalidated when view gets drawn again
2009 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */