/* -*- 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
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.