1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <comphelper/lok.hxx>
21 #include <vcl/syswin.hxx>
22 #include <sal/log.hxx>
23 
24 #include <headless/svpframe.hxx>
25 #include <headless/svpinst.hxx>
26 #ifndef IOS
27 #include <headless/svpgdi.hxx>
28 #endif
29 
30 #include <basegfx/vector/b2ivector.hxx>
31 
32 #ifndef IOS
33 #include <cairo.h>
34 #endif
35 
36 SvpSalFrame* SvpSalFrame::s_pFocusFrame = nullptr;
37 
38 #ifdef IOS
39 #define SvpSalGraphics AquaSalGraphics
40 #endif
41 
SvpSalFrame(SvpSalInstance * pInstance,SalFrame * pParent,SalFrameStyleFlags nSalFrameStyle)42 SvpSalFrame::SvpSalFrame( SvpSalInstance* pInstance,
43                           SalFrame* pParent,
44                           SalFrameStyleFlags nSalFrameStyle ) :
45     m_pInstance( pInstance ),
46     m_pParent( static_cast<SvpSalFrame*>(pParent) ),
47     m_nStyle( nSalFrameStyle ),
48     m_bVisible( false ),
49 #ifndef IOS
50     m_pSurface( nullptr ),
51 #endif
52     m_nMinWidth( 0 ),
53     m_nMinHeight( 0 ),
54     m_nMaxWidth( 0 ),
55     m_nMaxHeight( 0 )
56 {
57     // SAL_DEBUG("SvpSalFrame::SvpSalFrame: " << this);
58 #ifdef IOS
59     // Nothing
60 #elif defined ANDROID
61     // Nothing
62 #else
63     m_aSystemChildData.pSalFrame    = this;
64 #endif
65 
66     if( m_pParent )
67         m_pParent->m_aChildren.push_back( this );
68 
69     if( m_pInstance )
70         m_pInstance->registerFrame( this );
71 
72     SetPosSize( 0, 0, 800, 600, SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
73 }
74 
~SvpSalFrame()75 SvpSalFrame::~SvpSalFrame()
76 {
77     if( m_pInstance )
78         m_pInstance->deregisterFrame( this );
79 
80     std::list<SvpSalFrame*> Children = m_aChildren;
81     for( auto& rChild : Children )
82         rChild->SetParent( m_pParent );
83     if( m_pParent )
84         m_pParent->m_aChildren.remove( this );
85 
86     if( s_pFocusFrame == this )
87     {
88         // SAL_DEBUG("SvpSalFrame::~SvpSalFrame: losing focus: " << this);
89         s_pFocusFrame = nullptr;
90         // call directly here, else an event for a destroyed frame would be dispatched
91         CallCallback( SalEvent::LoseFocus, nullptr );
92         // if the handler has not set a new focus frame
93         // pass focus to another frame, preferably a document style window
94         if( s_pFocusFrame == nullptr )
95         {
96             for (auto pSalFrame : m_pInstance->getFrames() )
97             {
98                 SvpSalFrame* pFrame = static_cast<SvpSalFrame*>( pSalFrame );
99                 if( pFrame->m_bVisible        &&
100                     pFrame->m_pParent == nullptr &&
101                     (pFrame->m_nStyle & (SalFrameStyleFlags::MOVEABLE |
102                                          SalFrameStyleFlags::SIZEABLE |
103                                          SalFrameStyleFlags::CLOSEABLE) )
104                     )
105                 {
106                     pFrame->GetFocus();
107                     break;
108                 }
109             }
110         }
111     }
112 #ifndef IOS
113     if (m_pSurface)
114         cairo_surface_destroy(m_pSurface);
115 #endif
116 }
117 
GetFocus()118 void SvpSalFrame::GetFocus()
119 {
120     if( s_pFocusFrame == this )
121         return;
122 
123     if( (m_nStyle & (SalFrameStyleFlags::OWNERDRAWDECORATION | SalFrameStyleFlags::FLOAT)) == SalFrameStyleFlags::NONE )
124     {
125         if( s_pFocusFrame )
126             s_pFocusFrame->LoseFocus();
127         // SAL_DEBUG("SvpSalFrame::GetFocus(): " << this);
128         s_pFocusFrame = this;
129         m_pInstance->PostEvent( this, nullptr, SalEvent::GetFocus );
130     }
131 }
132 
LoseFocus()133 void SvpSalFrame::LoseFocus()
134 {
135     if( s_pFocusFrame == this )
136     {
137         // SAL_DEBUG("SvpSalFrame::LoseFocus: " << this);
138         m_pInstance->PostEvent( this, nullptr, SalEvent::LoseFocus );
139         s_pFocusFrame = nullptr;
140     }
141 }
142 
AcquireGraphics()143 SalGraphics* SvpSalFrame::AcquireGraphics()
144 {
145     SvpSalGraphics* pGraphics = new SvpSalGraphics();
146 #ifndef IOS
147     pGraphics->setSurface(m_pSurface, basegfx::B2IVector(maGeometry.nWidth, maGeometry.nHeight));
148 #endif
149     m_aGraphics.push_back( pGraphics );
150     return pGraphics;
151 }
152 
ReleaseGraphics(SalGraphics * pGraphics)153 void SvpSalFrame::ReleaseGraphics( SalGraphics* pGraphics )
154 {
155     SvpSalGraphics* pSvpGraphics = dynamic_cast<SvpSalGraphics*>(pGraphics);
156     m_aGraphics.erase(std::remove(m_aGraphics.begin(), m_aGraphics.end(), pSvpGraphics), m_aGraphics.end());
157     delete pSvpGraphics;
158 }
159 
PostEvent(std::unique_ptr<ImplSVEvent> pData)160 bool SvpSalFrame::PostEvent(std::unique_ptr<ImplSVEvent> pData)
161 {
162     m_pInstance->PostEvent( this, pData.release(), SalEvent::UserEvent );
163     return true;
164 }
165 
PostPaint() const166 void SvpSalFrame::PostPaint() const
167 {
168     if( m_bVisible )
169     {
170         SalPaintEvent aPEvt(0, 0, maGeometry.nWidth, maGeometry.nHeight);
171         aPEvt.mbImmediateUpdate = false;
172         CallCallback( SalEvent::Paint, &aPEvt );
173     }
174 }
175 
SetTitle(const OUString &)176 void SvpSalFrame::SetTitle( const OUString& )
177 {
178 }
179 
SetIcon(sal_uInt16)180 void SvpSalFrame::SetIcon( sal_uInt16 )
181 {
182 }
183 
SetMenu(SalMenu *)184 void SvpSalFrame::SetMenu( SalMenu* )
185 {
186 }
187 
DrawMenuBar()188 void SvpSalFrame::DrawMenuBar()
189 {
190 }
191 
SetExtendedFrameStyle(SalExtStyle)192 void SvpSalFrame::SetExtendedFrameStyle( SalExtStyle )
193 {
194 }
195 
Show(bool bVisible,bool bNoActivate)196 void SvpSalFrame::Show( bool bVisible, bool bNoActivate )
197 {
198     if( bVisible && ! m_bVisible )
199     {
200         // SAL_DEBUG("SvpSalFrame::Show: showing: " << this);
201         m_bVisible = true;
202         m_pInstance->PostEvent( this, nullptr, SalEvent::Resize );
203         if( ! bNoActivate )
204             GetFocus();
205     }
206     else if( ! bVisible && m_bVisible )
207     {
208         // SAL_DEBUG("SvpSalFrame::Show: hiding: " << this);
209         m_bVisible = false;
210         m_pInstance->PostEvent( this, nullptr, SalEvent::Resize );
211         LoseFocus();
212     }
213     else
214     {
215         // SAL_DEBUG("SvpSalFrame::Show: nothing: " << this);
216     }
217 }
218 
SetMinClientSize(long nWidth,long nHeight)219 void SvpSalFrame::SetMinClientSize( long nWidth, long nHeight )
220 {
221     m_nMinWidth = nWidth;
222     m_nMinHeight = nHeight;
223 }
224 
SetMaxClientSize(long nWidth,long nHeight)225 void SvpSalFrame::SetMaxClientSize( long nWidth, long nHeight )
226 {
227     m_nMaxWidth = nWidth;
228     m_nMaxHeight = nHeight;
229 }
230 
SetPosSize(long nX,long nY,long nWidth,long nHeight,sal_uInt16 nFlags)231 void SvpSalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags )
232 {
233     if( (nFlags & SAL_FRAME_POSSIZE_X) != 0 )
234         maGeometry.nX = nX;
235     if( (nFlags & SAL_FRAME_POSSIZE_Y) != 0 )
236         maGeometry.nY = nY;
237     if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 )
238     {
239         maGeometry.nWidth = nWidth;
240         if( m_nMaxWidth > 0 && maGeometry.nWidth > static_cast<unsigned int>(m_nMaxWidth) )
241             maGeometry.nWidth = m_nMaxWidth;
242         if( m_nMinWidth > 0 && maGeometry.nWidth < static_cast<unsigned int>(m_nMinWidth) )
243             maGeometry.nWidth = m_nMinWidth;
244     }
245     if( (nFlags & SAL_FRAME_POSSIZE_HEIGHT) != 0 )
246     {
247         maGeometry.nHeight = nHeight;
248         if( m_nMaxHeight > 0 && maGeometry.nHeight > static_cast<unsigned int>(m_nMaxHeight) )
249             maGeometry.nHeight = m_nMaxHeight;
250         if( m_nMinHeight > 0 && maGeometry.nHeight < static_cast<unsigned int>(m_nMinHeight) )
251             maGeometry.nHeight = m_nMinHeight;
252     }
253 #ifndef IOS
254     basegfx::B2IVector aFrameSize( maGeometry.nWidth, maGeometry.nHeight );
255     if (!m_pSurface || cairo_image_surface_get_width(m_pSurface) != aFrameSize.getX() ||
256                        cairo_image_surface_get_height(m_pSurface) != aFrameSize.getY() )
257     {
258         if( aFrameSize.getX() == 0 )
259             aFrameSize.setX( 1 );
260         if( aFrameSize.getY() == 0 )
261             aFrameSize.setY( 1 );
262 
263         if (m_pSurface)
264             cairo_surface_destroy(m_pSurface);
265 
266         // Creating backing surfaces for invisible windows costs a big chunk of RAM.
267         if (Application::IsHeadlessModeEnabled())
268              aFrameSize = basegfx::B2IVector( 1, 1 );
269 
270         m_pSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
271                                                 aFrameSize.getX(),
272                                                 aFrameSize.getY());
273 
274         // update device in existing graphics
275         for (auto const& graphic : m_aGraphics)
276         {
277              graphic->setSurface(m_pSurface, aFrameSize);
278         }
279     }
280     if( m_bVisible )
281         m_pInstance->PostEvent( this, nullptr, SalEvent::Resize );
282 #endif
283 }
284 
GetClientSize(long & rWidth,long & rHeight)285 void SvpSalFrame::GetClientSize( long& rWidth, long& rHeight )
286 {
287     rWidth = maGeometry.nWidth;
288     rHeight = maGeometry.nHeight;
289 }
290 
GetWorkArea(tools::Rectangle & rRect)291 void SvpSalFrame::GetWorkArea( tools::Rectangle& rRect )
292 {
293     rRect = tools::Rectangle( Point( 0, 0 ),
294                        Size( VIRTUAL_DESKTOP_WIDTH, VIRTUAL_DESKTOP_HEIGHT ) );
295 }
296 
GetParent() const297 SalFrame* SvpSalFrame::GetParent() const
298 {
299     return m_pParent;
300 }
301 
302 static constexpr auto FRAMESTATE_MASK_GEOMETRY =
303      WindowStateMask::X     | WindowStateMask::Y |
304      WindowStateMask::Width | WindowStateMask::Height;
305 
SetWindowState(const SalFrameState * pState)306 void SvpSalFrame::SetWindowState( const SalFrameState *pState )
307 {
308     if (pState == nullptr)
309         return;
310 
311     // Request for position or size change
312     if (pState->mnMask & FRAMESTATE_MASK_GEOMETRY)
313     {
314         long nX = maGeometry.nX;
315         long nY = maGeometry.nY;
316         long nWidth = maGeometry.nWidth;
317         long nHeight = maGeometry.nHeight;
318 
319         // change requested properties
320         if (pState->mnMask & WindowStateMask::X)
321             nX = pState->mnX;
322         if (pState->mnMask & WindowStateMask::Y)
323             nY = pState->mnY;
324         if (pState->mnMask & WindowStateMask::Width)
325             nWidth = pState->mnWidth;
326         if (pState->mnMask & WindowStateMask::Height)
327             nHeight = pState->mnHeight;
328 
329         SetPosSize( nX, nY, nWidth, nHeight,
330                     SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y |
331                     SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
332     }
333 }
334 
GetWindowState(SalFrameState * pState)335 bool SvpSalFrame::GetWindowState( SalFrameState* pState )
336 {
337     pState->mnState = WindowStateState::Normal;
338     pState->mnX      = maGeometry.nX;
339     pState->mnY      = maGeometry.nY;
340     pState->mnWidth  = maGeometry.nWidth;
341     pState->mnHeight = maGeometry.nHeight;
342     pState->mnMask   = FRAMESTATE_MASK_GEOMETRY | WindowStateMask::State;
343 
344     return true;
345 }
346 
ShowFullScreen(bool,sal_Int32)347 void SvpSalFrame::ShowFullScreen( bool, sal_Int32 )
348 {
349     SetPosSize( 0, 0, VIRTUAL_DESKTOP_WIDTH, VIRTUAL_DESKTOP_HEIGHT,
350                 SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
351 }
352 
StartPresentation(bool)353 void SvpSalFrame::StartPresentation( bool )
354 {
355 }
356 
SetAlwaysOnTop(bool)357 void SvpSalFrame::SetAlwaysOnTop( bool )
358 {
359 }
360 
ToTop(SalFrameToTop)361 void SvpSalFrame::ToTop( SalFrameToTop )
362 {
363     GetFocus();
364 }
365 
SetPointer(PointerStyle)366 void SvpSalFrame::SetPointer( PointerStyle )
367 {
368 }
369 
CaptureMouse(bool)370 void SvpSalFrame::CaptureMouse( bool )
371 {
372 }
373 
SetPointerPos(long,long)374 void SvpSalFrame::SetPointerPos( long, long )
375 {
376 }
377 
Flush()378 void SvpSalFrame::Flush()
379 {
380 }
381 
SetInputContext(SalInputContext *)382 void SvpSalFrame::SetInputContext( SalInputContext* )
383 {
384 }
385 
EndExtTextInput(EndExtTextInputFlags)386 void SvpSalFrame::EndExtTextInput( EndExtTextInputFlags )
387 {
388 }
389 
GetKeyName(sal_uInt16)390 OUString SvpSalFrame::GetKeyName( sal_uInt16 )
391 {
392     return OUString();
393 }
394 
MapUnicodeToKeyCode(sal_Unicode,LanguageType,vcl::KeyCode &)395 bool SvpSalFrame::MapUnicodeToKeyCode( sal_Unicode, LanguageType, vcl::KeyCode& )
396 {
397     return false;
398 }
399 
GetInputLanguage()400 LanguageType SvpSalFrame::GetInputLanguage()
401 {
402     return LANGUAGE_DONTKNOW;
403 }
404 
UpdateSettings(AllSettings & rSettings)405 void SvpSalFrame::UpdateSettings( AllSettings& rSettings )
406 {
407     StyleSettings aStyleSettings = rSettings.GetStyleSettings();
408 
409     Color aBackgroundColor( 0xef, 0xef, 0xef );
410     aStyleSettings.BatchSetBackgrounds( aBackgroundColor, false );
411     aStyleSettings.SetMenuColor( aBackgroundColor );
412     aStyleSettings.SetMenuBarColor( aBackgroundColor );
413 
414     if (comphelper::LibreOfficeKit::isActive()) // TODO: remove this.
415     {
416         vcl::Font aStdFont( FAMILY_SWISS, Size( 0, 14 ) );
417         aStdFont.SetCharSet( osl_getThreadTextEncoding() );
418         aStdFont.SetWeight( WEIGHT_NORMAL );
419         aStdFont.SetFamilyName( "Liberation Sans" );
420         aStyleSettings.BatchSetFonts( aStdFont, aStdFont );
421 
422         aStdFont.SetFontSize(Size(0, 12));
423         aStyleSettings.SetMenuFont(aStdFont);
424 
425         SvpSalGraphics* pGraphics = m_aGraphics.back();
426         bool bFreeGraphics = false;
427         if (!pGraphics)
428         {
429             pGraphics = dynamic_cast<SvpSalGraphics*>(AcquireGraphics());
430             if (!pGraphics)
431             {
432                 SAL_WARN("vcl.gtk3", "Could not get graphics - unable to update settings");
433                 return;
434             }
435             bFreeGraphics = true;
436         }
437         rSettings.SetStyleSettings(aStyleSettings);
438 #ifndef IOS // For now...
439         pGraphics->UpdateSettings(rSettings);
440 #endif
441         if (bFreeGraphics)
442             ReleaseGraphics(pGraphics);
443     }
444     else
445         rSettings.SetStyleSettings(aStyleSettings);
446 }
447 
Beep()448 void SvpSalFrame::Beep()
449 {
450 }
451 
GetSystemData() const452 const SystemEnvData* SvpSalFrame::GetSystemData() const
453 {
454     return &m_aSystemChildData;
455 }
456 
GetPointerState()457 SalFrame::SalPointerState SvpSalFrame::GetPointerState()
458 {
459     SalPointerState aState;
460     aState.mnState = 0;
461     return aState;
462 }
463 
GetIndicatorState()464 KeyIndicatorState SvpSalFrame::GetIndicatorState()
465 {
466     return KeyIndicatorState::NONE;
467 }
468 
SimulateKeyPress(sal_uInt16)469 void SvpSalFrame::SimulateKeyPress( sal_uInt16 /*nKeyCode*/ )
470 {
471 }
472 
SetParent(SalFrame * pNewParent)473 void SvpSalFrame::SetParent( SalFrame* pNewParent )
474 {
475     if( m_pParent )
476         m_pParent->m_aChildren.remove( this );
477     m_pParent = static_cast<SvpSalFrame*>(pNewParent);
478 }
479 
SetPluginParent(SystemParentData *)480 bool SvpSalFrame::SetPluginParent( SystemParentData* )
481 {
482     return true;
483 }
484 
ResetClipRegion()485 void SvpSalFrame::ResetClipRegion()
486 {
487 }
488 
BeginSetClipRegion(sal_uInt32)489 void SvpSalFrame::BeginSetClipRegion( sal_uInt32 )
490 {
491 }
492 
UnionClipRegion(long,long,long,long)493 void SvpSalFrame::UnionClipRegion( long, long, long, long )
494 {
495 }
496 
EndSetClipRegion()497 void SvpSalFrame::EndSetClipRegion()
498 {
499 }
500 
501 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
502