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