diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /vcl/headless/svpframe.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vcl/headless/svpframe.cxx')
-rw-r--r-- | vcl/headless/svpframe.cxx | 502 |
1 files changed, 502 insertions, 0 deletions
diff --git a/vcl/headless/svpframe.cxx b/vcl/headless/svpframe.cxx new file mode 100644 index 0000000000..e0971f85b9 --- /dev/null +++ b/vcl/headless/svpframe.cxx @@ -0,0 +1,502 @@ +/* -*- 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 . + */ + +#include <comphelper/lok.hxx> +#include <o3tl/safeint.hxx> +#include <vcl/syswin.hxx> +#include <sal/log.hxx> + +#include <headless/svpframe.hxx> +#include <headless/svpinst.hxx> +#ifndef IOS +#include <headless/svpgdi.hxx> +#endif +#include <salsys.hxx> + +#include <basegfx/vector/b2ivector.hxx> + +#ifndef IOS +#include <cairo.h> +#endif + +SvpSalFrame* SvpSalFrame::s_pFocusFrame = nullptr; + +#ifdef IOS +#define SvpSalGraphics AquaSalGraphics +#endif + +SvpSalFrame::SvpSalFrame( SvpSalInstance* pInstance, + SalFrame* pParent, + SalFrameStyleFlags nSalFrameStyle ) : + m_pInstance( pInstance ), + m_pParent( static_cast<SvpSalFrame*>(pParent) ), + m_nStyle( nSalFrameStyle ), + m_bVisible( false ), +#ifndef IOS + m_pSurface( nullptr ), +#endif + m_nMinWidth( 0 ), + m_nMinHeight( 0 ), + m_nMaxWidth( 0 ), + m_nMaxHeight( 0 ) +{ +#ifdef IOS + // Nothing +#elif defined ANDROID + // Nothing +#else + m_aSystemChildData.pSalFrame = this; +#endif + + if( m_pParent ) + m_pParent->m_aChildren.push_back( this ); + + if( m_pInstance ) + m_pInstance->registerFrame( this ); + + SetPosSize( 0, 0, 800, 600, SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT ); +} + +SvpSalFrame::~SvpSalFrame() +{ + if( m_pInstance ) + m_pInstance->deregisterFrame( this ); + + std::vector<SvpSalFrame*> Children = m_aChildren; + for( auto& rChild : Children ) + rChild->SetParent( m_pParent ); + if( m_pParent ) + std::erase(m_pParent->m_aChildren, this); + + if( s_pFocusFrame == this ) + { + s_pFocusFrame = nullptr; + // call directly here, else an event for a destroyed frame would be dispatched + CallCallback( SalEvent::LoseFocus, nullptr ); + // if the handler has not set a new focus frame + // pass focus to another frame, preferably a document style window + if( s_pFocusFrame == nullptr ) + { + for (auto pSalFrame : m_pInstance->getFrames() ) + { + SvpSalFrame* pFrame = static_cast<SvpSalFrame*>( pSalFrame ); + if( pFrame->m_bVisible && + pFrame->m_pParent == nullptr && + (pFrame->m_nStyle & (SalFrameStyleFlags::MOVEABLE | + SalFrameStyleFlags::SIZEABLE | + SalFrameStyleFlags::CLOSEABLE) ) + ) + { + pFrame->GetFocus(); + break; + } + } + } + } +#ifndef IOS + if (m_pSurface) + cairo_surface_destroy(m_pSurface); +#endif +} + +void SvpSalFrame::GetFocus() +{ + if (m_nStyle == SalFrameStyleFlags::NONE) + return; + if( s_pFocusFrame == this ) + return; + // FIXME: return if !m_bVisible + // That's IMHO why CppunitTest_sd_tiledrendering crashes non-headless + + if( (m_nStyle & (SalFrameStyleFlags::OWNERDRAWDECORATION | SalFrameStyleFlags::FLOAT)) == SalFrameStyleFlags::NONE ) + { + if( s_pFocusFrame ) + s_pFocusFrame->LoseFocus(); + s_pFocusFrame = this; + m_pInstance->PostEvent( this, nullptr, SalEvent::GetFocus ); + } +} + +void SvpSalFrame::LoseFocus() +{ + if( s_pFocusFrame == this ) + { + m_pInstance->PostEvent( this, nullptr, SalEvent::LoseFocus ); + s_pFocusFrame = nullptr; + } +} + +basegfx::B2IVector SvpSalFrame::GetSurfaceFrameSize() const +{ + basegfx::B2IVector aFrameSize( maGeometry.width(), maGeometry.height() ); + if( aFrameSize.getX() == 0 ) + aFrameSize.setX( 1 ); + if( aFrameSize.getY() == 0 ) + aFrameSize.setY( 1 ); + // Creating backing surfaces for invisible windows costs a big chunk of RAM. + if (Application::IsHeadlessModeEnabled()) + aFrameSize = basegfx::B2IVector( 1, 1 ); + return aFrameSize; +} + +SalGraphics* SvpSalFrame::AcquireGraphics() +{ + SvpSalGraphics* pGraphics = new SvpSalGraphics(); +#ifndef IOS + pGraphics->setSurface(m_pSurface, GetSurfaceFrameSize()); +#endif + m_aGraphics.push_back( pGraphics ); + return pGraphics; +} + +void SvpSalFrame::ReleaseGraphics( SalGraphics* pGraphics ) +{ + SvpSalGraphics* pSvpGraphics = dynamic_cast<SvpSalGraphics*>(pGraphics); + std::erase(m_aGraphics, pSvpGraphics); + delete pSvpGraphics; +} + +bool SvpSalFrame::PostEvent(std::unique_ptr<ImplSVEvent> pData) +{ + m_pInstance->PostEvent( this, pData.release(), SalEvent::UserEvent ); + return true; +} + +void SvpSalFrame::PostPaint() const +{ + if( m_bVisible ) + { + SalPaintEvent aPEvt(0, 0, maGeometry.width(), maGeometry.height()); + aPEvt.mbImmediateUpdate = false; + CallCallback( SalEvent::Paint, &aPEvt ); + } +} + +void SvpSalFrame::SetTitle(const OUString& sTitle) +{ + m_sTitle = sTitle; +} + +void SvpSalFrame::SetIcon( sal_uInt16 ) +{ +} + +void SvpSalFrame::SetMenu( SalMenu* ) +{ +} + +void SvpSalFrame::SetExtendedFrameStyle( SalExtStyle ) +{ +} + +void SvpSalFrame::Show( bool bVisible, bool bNoActivate ) +{ + if (m_nStyle == SalFrameStyleFlags::NONE) + return; + if (bVisible == m_bVisible) + { + if (m_bVisible && !bNoActivate) + GetFocus(); + return; + } + + if (bVisible) + { + m_bVisible = true; + m_pInstance->PostEvent( this, nullptr, SalEvent::Resize ); + if( ! bNoActivate ) + GetFocus(); + } + else + { + m_bVisible = false; + LoseFocus(); + } +} + +void SvpSalFrame::SetMinClientSize( tools::Long nWidth, tools::Long nHeight ) +{ + m_nMinWidth = nWidth; + m_nMinHeight = nHeight; +} + +void SvpSalFrame::SetMaxClientSize( tools::Long nWidth, tools::Long nHeight ) +{ + m_nMaxWidth = nWidth; + m_nMaxHeight = nHeight; +} + +void SvpSalFrame::SetPosSize( tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, sal_uInt16 nFlags ) +{ + if( (nFlags & SAL_FRAME_POSSIZE_X) != 0 ) + maGeometry.setX(nX); + if( (nFlags & SAL_FRAME_POSSIZE_Y) != 0 ) + maGeometry.setY(nY); + if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 ) + { + maGeometry.setWidth(nWidth); + if (m_nMaxWidth > 0 && maGeometry.width() > m_nMaxWidth) + maGeometry.setWidth(m_nMaxWidth); + if (m_nMinWidth > 0 && maGeometry.width() < m_nMinWidth) + maGeometry.setWidth(m_nMinWidth); + } + if( (nFlags & SAL_FRAME_POSSIZE_HEIGHT) != 0 ) + { + maGeometry.setHeight(nHeight); + if (m_nMaxHeight > 0 && maGeometry.height() > m_nMaxHeight) + maGeometry.setHeight(m_nMaxHeight); + if (m_nMinHeight > 0 && maGeometry.height() < m_nMinHeight) + maGeometry.setHeight(m_nMinHeight); + } +#ifndef IOS + basegfx::B2IVector aFrameSize = GetSurfaceFrameSize(); + if (!m_pSurface || cairo_image_surface_get_width(m_pSurface) != aFrameSize.getX() || + cairo_image_surface_get_height(m_pSurface) != aFrameSize.getY() ) + { + if (m_pSurface) + cairo_surface_destroy(m_pSurface); + + m_pSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, + aFrameSize.getX(), + aFrameSize.getY()); + + // update device in existing graphics + for (auto const& graphic : m_aGraphics) + { + graphic->setSurface(m_pSurface, aFrameSize); + } + } + if( m_bVisible ) + m_pInstance->PostEvent( this, nullptr, SalEvent::Resize ); +#endif +} + +void SvpSalFrame::GetClientSize( tools::Long& rWidth, tools::Long& rHeight ) +{ + rWidth = maGeometry.width(); + rHeight = maGeometry.height(); +} + +void SvpSalFrame::GetWorkArea( AbsoluteScreenPixelRectangle& rRect ) +{ + rRect = AbsoluteScreenPixelRectangle( AbsoluteScreenPixelPoint( 0, 0 ), + AbsoluteScreenPixelSize( VIRTUAL_DESKTOP_WIDTH, VIRTUAL_DESKTOP_HEIGHT ) ); +} + +SalFrame* SvpSalFrame::GetParent() const +{ + return m_pParent; +} + +void SvpSalFrame::SetWindowState(const vcl::WindowData *pState) +{ + if (pState == nullptr) + return; + + // Request for position or size change + if (!(pState->mask() & vcl::WindowDataMask::PosSize)) + return; + + tools::Long nX = maGeometry.x(); + tools::Long nY = maGeometry.y(); + tools::Long nWidth = maGeometry.width(); + tools::Long nHeight = maGeometry.height(); + + // change requested properties + if (pState->mask() & vcl::WindowDataMask::X) + nX = pState->x(); + if (pState->mask() & vcl::WindowDataMask::Y) + nY = pState->y(); + if (pState->mask() & vcl::WindowDataMask::Width) + nWidth = pState->width(); + if (pState->mask() & vcl::WindowDataMask::Height) + nHeight = pState->height(); + + SetPosSize( nX, nY, nWidth, nHeight, + SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y | + SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT ); +} + +bool SvpSalFrame::GetWindowState(vcl::WindowData* pState) +{ + pState->setPosSize(maGeometry.posSize()); + pState->setState(vcl::WindowState::Normal); + pState->setMask(vcl::WindowDataMask::PosSizeState); + return true; +} + +void SvpSalFrame::ShowFullScreen( bool, sal_Int32 ) +{ + SetPosSize( 0, 0, VIRTUAL_DESKTOP_WIDTH, VIRTUAL_DESKTOP_HEIGHT, + SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT ); +} + +void SvpSalFrame::StartPresentation( bool ) +{ +} + +void SvpSalFrame::SetAlwaysOnTop( bool ) +{ +} + +void SvpSalFrame::ToTop(SalFrameToTop nFlags) +{ + if (m_nStyle == SalFrameStyleFlags::NONE) + return; + if (nFlags & SalFrameToTop::RestoreWhenMin) + Show(true, false); + else + GetFocus(); +} + +void SvpSalFrame::SetPointer( PointerStyle ) +{ +} + +void SvpSalFrame::CaptureMouse( bool ) +{ +} + +void SvpSalFrame::SetPointerPos( tools::Long, tools::Long ) +{ +} + +void SvpSalFrame::Flush() +{ +} + +void SvpSalFrame::SetInputContext( SalInputContext* ) +{ +} + +void SvpSalFrame::EndExtTextInput( EndExtTextInputFlags ) +{ +} + +OUString SvpSalFrame::GetKeyName( sal_uInt16 ) +{ + return OUString(); +} + +bool SvpSalFrame::MapUnicodeToKeyCode( sal_Unicode, LanguageType, vcl::KeyCode& ) +{ + return false; +} + +LanguageType SvpSalFrame::GetInputLanguage() +{ + return LANGUAGE_DONTKNOW; +} + +void SvpSalFrame::UpdateSettings( AllSettings& rSettings ) +{ + StyleSettings aStyleSettings = rSettings.GetStyleSettings(); + + Color aBackgroundColor( 0xef, 0xef, 0xef ); + aStyleSettings.BatchSetBackgrounds( aBackgroundColor, false ); + aStyleSettings.SetMenuColor( aBackgroundColor ); + aStyleSettings.SetMenuBarColor( aBackgroundColor ); + + if (comphelper::LibreOfficeKit::isActive()) // TODO: remove this. + { + vcl::Font aStdFont( FAMILY_SWISS, Size( 0, 14 ) ); + aStdFont.SetCharSet( osl_getThreadTextEncoding() ); + aStdFont.SetWeight( WEIGHT_NORMAL ); + aStdFont.SetFamilyName( "Liberation Sans" ); + aStyleSettings.BatchSetFonts( aStdFont, aStdFont ); + + aStdFont.SetFontSize(Size(0, 12)); + aStyleSettings.SetMenuFont(aStdFont); + + SvpSalGraphics* pGraphics = m_aGraphics.empty() ? nullptr : m_aGraphics.back(); + bool bFreeGraphics = false; + if (!pGraphics) + { + pGraphics = dynamic_cast<SvpSalGraphics*>(AcquireGraphics()); + if (!pGraphics) + { + SAL_WARN("vcl.gtk3", "Could not get graphics - unable to update settings"); + return; + } + bFreeGraphics = true; + } + rSettings.SetStyleSettings(aStyleSettings); +#ifndef IOS // For now... + pGraphics->UpdateSettings(rSettings); +#endif + if (bFreeGraphics) + ReleaseGraphics(pGraphics); + } + else + rSettings.SetStyleSettings(aStyleSettings); +} + +void SvpSalFrame::Beep() +{ +} + +const SystemEnvData* SvpSalFrame::GetSystemData() const +{ + return &m_aSystemChildData; +} + +SalFrame::SalPointerState SvpSalFrame::GetPointerState() +{ + SalPointerState aState; + aState.mnState = 0; + return aState; +} + +KeyIndicatorState SvpSalFrame::GetIndicatorState() +{ + return KeyIndicatorState::NONE; +} + +void SvpSalFrame::SimulateKeyPress( sal_uInt16 /*nKeyCode*/ ) +{ +} + +void SvpSalFrame::SetParent( SalFrame* pNewParent ) +{ + if( m_pParent ) + std::erase(m_pParent->m_aChildren, this); + m_pParent = static_cast<SvpSalFrame*>(pNewParent); +} + +void SvpSalFrame::SetPluginParent( SystemParentData* ) +{ +} + +void SvpSalFrame::ResetClipRegion() +{ +} + +void SvpSalFrame::BeginSetClipRegion( sal_uInt32 ) +{ +} + +void SvpSalFrame::UnionClipRegion( tools::Long, tools::Long, tools::Long, tools::Long ) +{ +} + +void SvpSalFrame::EndSetClipRegion() +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |