/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
// tdf#150177 Limit minimum blink cursor rate // This bug occurs when the values for NSTextInsertionPointBlinkPeriodOn or // NSTextInsertionPointBlinkPeriodOff are set to zero or close to zero. // LibreOffice becomes very sluggish opening documents when either is set // at 100 milliseconds or less so set the blink rate to the maximum of // nMinBlinkCursorDelay, NSTextInsertionPointBlinkPeriodOn, and // NSTextInsertionPointBlinkPeriodOff.
mnBlinkCursorDelay = nMinBlinkCursorDelay; if (userDefaults != nil)
{
id setting = [userDefaults objectForKey: @"NSTextInsertionPointBlinkPeriodOn"]; if (setting && [setting isKindOfClass:[NSNumber class]])
mnBlinkCursorDelay = std::max(mnBlinkCursorDelay, [setting intValue]);
// if the frame is destroyed and has the current menubar // set the default menubar if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu )
AquaSalMenu::setDefaultMenu();
// cleanup clipping stuff
doResetClipRegion();
[SalFrameView unsetMouseFrame: this];
SalData* pSalData = GetSalData();
pSalData->mpInstance->eraseFrame( this );
pSalData->maPresentationFrames.remove( this );
SAL_WARN_IF( this == s_pCaptureFrame, "vcl", "capture frame destroyed" ); if( this == s_pCaptureFrame )
s_pCaptureFrame = nullptr;
delete mpGraphics;
if( mpDockMenuEntry )
{
NSMenu* pDock = AquaSalInstance::GetDynamicDockMenu(); // life cycle comment: the menu has ownership of the item, so no release
[pDock removeItem: mpDockMenuEntry]; if ([pDock numberOfItems] != 0
&& [[pDock itemAtIndex: 0] isSeparatorItem])
{
[pDock removeItemAtIndex: 0];
}
} if ( mpNSView ) { if ([mpNSView isKindOfClass:[SalFrameView class]])
[static_cast<SalFrameView*>(mpNSView) revokeWrapper];
[mpNSView release];
} if ( mpNSWindow )
[mpNSWindow release];
}
// make sure the view is present in the wrapper list before any children receive focus if (mpNSView && [mpNSView isKindOfClass:[SalFrameView class]])
[static_cast<SalFrameView*>(mpNSView) registerWrapper];
}
// tdf#152173 Don't display tooltip windows when application is inactive // Starting with macOS 13 Ventura, inactive applications receive mouse // move events so when LibreOffice is inactive, a mouse move event causes // a tooltip to be displayed. Since the tooltip window is attached to its // parent window (to ensure that the tooltip is above the parent window), // displaying a tooltip pulls the parent window in front of the windows // of all other inactive applications. // Also, don't display tooltips when mousing over non-key windows even if // the application is active as the tooltip window will pull the non-key // window in front of the key window. if (bVisible && (mnStyle & SalFrameStyleFlags::TOOLTIP))
{ if (![NSApp isActive]) return;
if (mpParent)
{ // tdf#157565 show tooltip if any parent window is the key window bool bKeyWindowFound = false;
NSWindow *pParent = mpParent->mpNSWindow; while (pParent)
{ if ([pParent isKeyWindow])
{
bKeyWindowFound = true; break;
}
pParent = [pParent parentWindow];
} if (!bKeyWindowFound) return;
}
}
if( mpParent )
{ /* #i92674# #i96433# we do not want an invisible parent to show up (which adding a visible child implicitly does). However we also do not want a parentless toolbar.
HACK: try to decide when we should not insert a child to its parent floaters and ownerdraw windows have not yet shown up in cases where we don't want the parent to become visible
*/ if( mpParent->mbShown || (mnStyle & (SalFrameStyleFlags::OWNERDRAWDECORATION | SalFrameStyleFlags::FLOAT) ) )
{
[mpParent->mpNSWindow addChildWindow: mpNSWindow ordered: NSWindowAbove];
}
}
if( mbPresentation )
[mpNSWindow makeMainWindow];
} else
{ // if the frame holding the current menubar gets hidden // show the default menubar if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu )
AquaSalMenu::setDefaultMenu();
// #i90440# #i94443# work around the focus going back to some other window // if a child gets hidden for a parent window if( mpParent && mpParent->mbShown && [mpNSWindow isKeyWindow] )
[mpParent->mpNSWindow makeKeyAndOrderFront: NSApp];
// Related: tdf#161623 close windows, don't order them out // Ordering out a native full screen window would leave the // application in a state where there is no Desktop and both // the menubar and the Dock are hidden.
[mpNSWindow close];
// Related: tdf#165448 move parent window to front after closing window // When a floating window such as the dropdown list in the // font combobox is open when selecting any of the menu items // inserted by macOS in the windows menu, the parent window // will be hidden. So if there is a key window, force the key // window back to the front. // Previously, delaying closing of the window was used to avoid // this bug, but that caused Skia/Metal to crash when the // window was released before the delayed close occurred. This // crash was found when rapidly dragging the border between two // column headings side to side in a Calc document.
NSWindow *pKeyWin = [NSApp keyWindow]; if( pKeyWin )
[pKeyWin orderFront: NSApp];
}
}
/* ZOOMED is not really maximized (actually it toggles between a user set size and the program specified one), but comes closest since the default behavior is "maximized" if the user did not intervene
*/ if (pState->state() == vcl::WindowState::Maximized)
{ if (![mpNSWindow isZoomed])
[mpNSWindow zoom: NSApp];
} else
{ if ([mpNSWindow isZoomed])
[mpNSWindow zoom: NSApp];
}
// get new geometry
UpdateFrameGeometry();
// send event that we were moved/sized if( nEvent != SalEvent::NONE )
CallCallback( nEvent, nullptr );
if (mbShown)
{ // trigger filling our backbuffer
SendPaintEvent();
// tell the system the views need to be updated
[mpNSWindow display];
}
}
bool AquaSalFrame::GetWindowState(vcl::WindowData* pState)
{ if (!mpNSWindow)
{ if (Application::IsBitmapRendering())
{
pState->setMask(vcl::WindowDataMask::PosSizeState);
pState->setPosSize(maGeometry.posSize());
pState->setState(vcl::WindowState::Normal); returntrue;
} returnfalse;
}
// tdf#128186 use non-full screen values for native full screen windows
pState->setState(vcl::WindowState::Normal);
} else
{
pState->setX(static_cast<sal_Int32>(aStateRect.origin.x));
pState->setY(static_cast<sal_Int32>(aStateRect.origin.y));
pState->setWidth(static_cast<sal_uInt32>(aStateRect.size.width));
pState->setHeight(static_cast<sal_uInt32>(aStateRect.size.height));
// Hide the dock and the menubar if this or one of its child // windows are the key window if( AquaSalFrame::isAlive( this ) )
{ bool bNativeFullScreen = false; const AquaSalFrame *pParentFrame = this; while( pParentFrame )
{
bNativeFullScreen |= pParentFrame->mbNativeFullScreen;
pParentFrame = AquaSalFrame::isAlive( pParentFrame->mpParent ) ? pParentFrame->mpParent : nullptr;
}
// Show the menubar if application is in native full screen mode // since hiding the menubar in that mode will cause the window's // titlebar to fail to display or hide as expected.
[NSMenu setMenuBarVisible: YES];
} else
{ // Related: tdf#128186 restore rectangles are in VCL coordinates
NSRect aFrame = [mpNSWindow frame];
NSRect aContentRect = [NSWindow contentRectForFrameRect: aFrame styleMask: [mpNSWindow styleMask] & ~NSWindowStyleMaskFullScreen];
CocoaToVCL( aContentRect );
maInternalFullScreenRestoreRect = aContentRect;
}
// Related: tdf#161623 do not add the window's titlebar height // to the window's frame as that will cause the titlebar to be // pushed offscreen.
maInternalFullScreenExpectedRect = aNewFrameRect;
[mpNSWindow setFrame: maInternalFullScreenExpectedRect display: mbShown ? YES : NO];
} else
{ // Show the dock and the menubar if this or one of its children are // the key window const NSWindow *pParentWindow = [NSApp keyWindow]; while( pParentWindow && pParentWindow != mpNSWindow )
pParentWindow = [pParentWindow parentWindow]; if( pParentWindow == mpNSWindow )
{
[NSMenu setMenuBarVisible: YES];
} // Show the dock and the menubar if there is no native modal dialog // and if the key window is nil or is not a SalFrameWindow instance. // If a SalFrameWindow is the key window, it should have already set // the menubar visibility to match its LibreOffice full screen mode // state. elseif( ![NSApp modalWindow] )
{
NSWindow *pKeyWindow = [NSApp keyWindow]; if( !pKeyWindow || ![pKeyWindow isKindOfClass: [SalFrameWindow class]] )
[NSMenu setMenuBarVisible: YES];
}
if( !NSIsEmptyRect( maInternalFullScreenRestoreRect ) )
{ if( mbNativeFullScreen && !NSIsEmptyRect( maNativeFullScreenRestoreRect ) )
{ // Related: tdf#128186 force window to unzoom // If we exit LibreOffice's internal full screen mode while // the window is in native full screen mode, the window will // be zoomed after exiting native full screen mode.
[mpNSWindow setIsZoomed: NO];
} else
{
NSRect aContentRect = maInternalFullScreenRestoreRect;
VCLToCocoa( aContentRect );
NSRect aFrame = [NSWindow frameRectForContentRect: aContentRect styleMask: [mpNSWindow styleMask] & ~NSWindowStyleMaskFullScreen];
[mpNSWindow setFrame: aFrame display: mbShown ? YES : NO];
}
maInternalFullScreenRestoreRect = NSZeroRect;
}
maInternalFullScreenExpectedRect = NSZeroRect;
}
UpdateFrameGeometry(); if (mbShown)
{
CallCallback(SalEvent::MoveResize, nullptr);
// outside of the application's event loop (e.g. IntroWindow) // nothing would trigger paint event handling // => fall back to synchronous painting if( doFlush() )
[mpNSView display];
}
// outside of the application's event loop (e.g. IntroWindow) // nothing would trigger paint event handling // => fall back to synchronous painting if( doFlush() )
[mpNSView displayRect: aNSRect];
}
// Related: tdf#155266 skip redisplay of the view when forcing flush // It appears that calling -[NSView display] overwhelms some Intel Macs // so only flush the graphics and skip immediate redisplay of the view.
bRet = ImplGetSVData()->maAppData.mnDispatchLevel <= 0;
void AquaSalFrame::EndExtTextInput( EndExtTextInputFlags nFlags )
{ // tdf#82115 Commit uncommitted text when a popup menu is opened // The Windows implementation of this method commits or discards the native // input method session. It appears that very few, if any, macOS // applications discard the uncommitted text when cancelling a session so // always commit the uncommitted text.
SalFrameWindow *pWindow = static_cast<SalFrameWindow*>(mpNSWindow); if (pWindow && [pWindow isKindOfClass:[SalFrameWindow class]])
[pWindow endExtTextInput:nFlags];
}
OUString AquaSalFrame::GetKeyName( sal_uInt16 nKeyCode )
{ static std::map< sal_uInt16, OUString > aKeyMap; if( aKeyMap.empty() )
{
sal_uInt16 i; for( i = KEY_A; i <= KEY_Z; i++ )
aKeyMap[ i ] = OUString( sal_Unicode( 'A' + (i - KEY_A) ) ); for( i = KEY_0; i <= KEY_9; i++ )
aKeyMap[ i ] = OUString( sal_Unicode( '0' + (i - KEY_0) ) ); for( i = KEY_F1; i <= KEY_F26; i++ )
{
aKeyMap[ i ] = "F" + OUString::number(i - KEY_F1 + 1);
}
static Color getNSBoxBackgroundColor(NSColor* pSysColor)
{ // Figuring out what a NSBox will draw for windowBackground, etc. seems very difficult. // So just draw to a 1x1 surface and read what actually gets drawn // This is similar to getPixel #ifdefined OSL_BIGENDIAN struct
{ unsignedchar b, g, r, a;
} aPixel; #else struct
{ unsignedchar a, r, g, b;
} aPixel; #endif
switch (MiscSettings::GetAppColorMode())
{ case AppearanceMode::AUTO: default: if (pCurrentAppearance)
[NSApp setAppearance: nil]; break; case AppearanceMode::LIGHT: if (!pCurrentAppearance || ![NSAppearanceNameAqua isEqualToString: [pCurrentAppearance name]])
[NSApp setAppearance: [NSAppearance appearanceNamed: NSAppearanceNameAqua]]; break; case AppearanceMode::DARK: if (!pCurrentAppearance || ![NSAppearanceNameDarkAqua isEqualToString: [pCurrentAppearance name]])
[NSApp setAppearance: [NSAppearance appearanceNamed: NSAppearanceNameDarkAqua]]; break;
}
// Related: tdf#165266 sync NSView's appearance to NSApp's appearance // Invoking -[NSApp setAppearance:] does immediately update the // appearance of each NSWindow's titlebar, but it does not appear // to update any NSView's appearance so explicitly sync appearances.
NSAppearance *pNewAppearance = [NSApp appearance]; if (mpNSView.appearance != pNewAppearance)
mpNSView.appearance = pNewAppearance;
}
// on OSX-Aqua the style settings are independent of the frame, so it does // not really belong here. Since the connection to the Appearance_Manager // is currently done in salnativewidgets.cxx this would be a good place. // On the other hand VCL's platform independent code currently only asks // SalFrames for system settings anyway, so moving the code somewhere else // doesn't make the anything cleaner for now void AquaSalFrame::UpdateSettings( AllSettings& rSettings )
{ if ( !mpNSWindow ) return;
// tdf#165266 Force NSColor to use current effective appearance // +[NSAppearance setCurrentAppearance:] is deprecated and calling // that appears to do less and less with each new version of macos // or Xcode so run all system +[NSColor ...] calls in a block passed // to -[NSAppearance performAsCurrentDrawingAppearance:].
UpdateDarkMode(); if (@available(macOS 11, *))
{
assert(mpNSView);
[mpNSView.effectiveAppearance performAsCurrentDrawingAppearance:^() {
doUpdateSettings( rSettings ); return;
}];
} else
{
doUpdateSettings( rSettings );
}
}
SAL_WNODEPRECATED_DECLARATIONS_PUSH // "'lockFocus' is deprecated: first deprecated in macOS 10.14 - To draw, subclass NSView // and implement -drawRect:; AppKit's automatic deferred display mechanism will call // -drawRect: as necessary to display the view." if (![mpNSView lockFocusIfCanDraw]) return;
SAL_WNODEPRECATED_DECLARATIONS_POP
SAL_WNODEPRECATED_DECLARATIONS_PUSH // "'setCurrentAppearance:' is deprecated: first deprecated in macOS 12.0 - Use // -performAsCurrentDrawingAppearance: to temporarily set the drawing appearance, or // +currentDrawingAppearance to access the currently drawing appearance."
[NSAppearance setCurrentAppearance: mpNSView.effectiveAppearance];
SAL_WNODEPRECATED_DECLARATIONS_POP
Color aControlBackgroundColor(getNSBoxBackgroundColor([NSColor controlBackgroundColor]));
Color aWindowBackgroundColor(getNSBoxBackgroundColor([NSColor windowBackgroundColor]));
Color aUnderPageBackgroundColor(getNSBoxBackgroundColor([NSColor underPageBackgroundColor]));
// Background Color
aStyleSettings.BatchSetBackgrounds( aWindowBackgroundColor, false );
aStyleSettings.SetLightBorderColor( aWindowBackgroundColor );
// FIXME: Starting with macOS Big Sur, coloring has changed. Currently there is no documentation which system color should be // used for some button states and for selected tab text. As a workaround the current OS version has to be considered. This code // has to be reviewed once issue is covered by documentation.
// Set text colors for buttons and their different status according to OS settings, typically white for selected buttons, // black otherwise
// no mnemonics on macOS
aStyleSettings.SetOptions( aStyleSettings.GetOptions() | StyleSettingsOptions::NoMnemonics );
getAppleScrollBarVariant(aStyleSettings);
// set scrollbar size
aStyleSettings.SetScrollBarSize( static_cast<tools::Long>([NSScroller scrollerWidthForControlSize:NSControlSizeRegular scrollerStyle:NSScrollerStyleLegacy]) ); // images in menus false for MacOSX
aStyleSettings.SetPreferredUseImagesInMenus( false );
aStyleSettings.SetHideDisabledMenuItems( true );
aStyleSettings.SetPreferredContextMenuShortcuts( false );
if (ThemeColors::VclPluginCanUseThemeColors())
lcl_LoadColorsFromTheme(aStyleSettings);
aStyleSettings.SetSystemColorsLoaded(true);
rSettings.SetStyleSettings( aStyleSettings );
// don't draw frame around each and every toolbar
ImplGetSVData()->maNWFData.mbDockingAreaAvoidTBFrames = true;
SAL_WNODEPRECATED_DECLARATIONS_PUSH // "'unlockFocus' is deprecated: first deprecated in macOS 10.14 - To draw, subclass NSView // and implement -drawRect:; AppKit's automatic deferred display mechanism will call // -drawRect: as necessary to display the view."
[mpNSView unlockFocus];
SAL_WNODEPRECATED_DECLARATIONS_POP
}
} else
{ // FIXME: replace Carbon by Cocoa // Cocoa does not have an equivalent for GetCurrentEventButtonState // and GetCurrentEventKeyModifiers. // we could try to get away with tracking all events for modifierKeys // and all mouse events for button state in VCL_NSApplication::sendEvent, // but it is unclear whether this will get us the same result. // leave in GetCurrentEventButtonState and GetCurrentEventKeyModifiers for now
void AquaSalFrame::CaptureMouse( bool bCapture )
{ /* Remark: we'll try to use a pidgin version of capture mouse on MacOSX (neither carbon nor cocoa) there is a CaptureMouse equivalent (in Carbon there is TrackMouseLocation but this is useless to use since it is blocking)
However on cocoa the active frame seems to get mouse events also outside the window, so we'll try to forward mouse events to the capture frame in the hope that one of our frames gets a mouse event.
This will break as soon as the user activates another app, but a mouse click will normally lead to a release of the mouse anyway.
Let's see how far we get this way. Alternatively we could use one large overlay window like we did for the carbon implementation, however that is resource intensive.
*/
void AquaSalFrame::UnionClipRegion(
tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight )
{ // #i113170# may not be the main thread if called from UNO API
SalData::ensureThreadAutoreleasePool();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.