Update git submodules
[LibreOffice.git] / vcl / source / window / window2.cxx
blob173edb8932e0f6593c2f0b88d1ab8b92fffed3ca
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <limits.h>
22 #include <o3tl/float_int_conversion.hxx>
23 #include <sal/log.hxx>
25 #include <tools/helpers.hxx>
27 #include <vcl/toolkit/dialog.hxx>
28 #include <vcl/event.hxx>
29 #include <vcl/toolkit/fixed.hxx>
30 #include <vcl/layout.hxx>
31 #include <vcl/timer.hxx>
32 #include <vcl/window.hxx>
33 #include <vcl/scrollable.hxx>
34 #include <vcl/toolkit/scrbar.hxx>
35 #include <vcl/dockwin.hxx>
36 #include <vcl/settings.hxx>
37 #include <vcl/builder.hxx>
38 #include <o3tl/string_view.hxx>
40 #include <window.h>
41 #include <svdata.hxx>
42 #include <salgdi.hxx>
43 #include <salframe.hxx>
44 #include <scrwnd.hxx>
46 #include <com/sun/star/accessibility/AccessibleRelation.hpp>
47 #include <com/sun/star/accessibility/AccessibleRole.hpp>
49 using namespace com::sun::star;
51 namespace vcl {
53 void Window::ShowFocus( const tools::Rectangle& rRect )
55 if( mpWindowImpl->mbInShowFocus )
56 return;
57 mpWindowImpl->mbInShowFocus = true;
59 ImplWinData* pWinData = ImplGetWinData();
61 // native themeing suggest not to use focus rects
62 if( ! ( mpWindowImpl->mbUseNativeFocus &&
63 IsNativeWidgetEnabled() ) )
65 if ( !mpWindowImpl->mbInPaint )
67 if ( mpWindowImpl->mbFocusVisible )
69 if ( *pWinData->mpFocusRect == rRect )
71 mpWindowImpl->mbInShowFocus = false;
72 return;
75 ImplInvertFocus( *pWinData->mpFocusRect );
78 ImplInvertFocus( rRect );
80 pWinData->mpFocusRect = rRect;
81 mpWindowImpl->mbFocusVisible = true;
83 else
85 if( ! mpWindowImpl->mbNativeFocusVisible )
87 mpWindowImpl->mbNativeFocusVisible = true;
88 if ( !mpWindowImpl->mbInPaint )
89 Invalidate();
92 mpWindowImpl->mbInShowFocus = false;
95 void Window::HideFocus()
98 if( mpWindowImpl->mbInHideFocus )
99 return;
100 mpWindowImpl->mbInHideFocus = true;
102 // native themeing can suggest not to use focus rects
103 if( ! ( mpWindowImpl->mbUseNativeFocus &&
104 IsNativeWidgetEnabled() ) )
106 if ( !mpWindowImpl->mbFocusVisible )
108 mpWindowImpl->mbInHideFocus = false;
109 return;
112 if ( !mpWindowImpl->mbInPaint )
113 ImplInvertFocus( *ImplGetWinData()->mpFocusRect );
114 mpWindowImpl->mbFocusVisible = false;
116 else
118 if( mpWindowImpl->mbNativeFocusVisible )
120 mpWindowImpl->mbNativeFocusVisible = false;
121 if ( !mpWindowImpl->mbInPaint )
122 Invalidate();
125 mpWindowImpl->mbInHideFocus = false;
128 void Window::ShowTracking( const tools::Rectangle& rRect, ShowTrackFlags nFlags )
130 ImplWinData* pWinData = ImplGetWinData();
132 if ( !mpWindowImpl->mbInPaint || !(nFlags & ShowTrackFlags::TrackWindow) )
134 if ( mpWindowImpl->mbTrackVisible )
136 if ( (*pWinData->mpTrackRect == rRect) &&
137 (pWinData->mnTrackFlags == nFlags) )
138 return;
140 InvertTracking( *pWinData->mpTrackRect, pWinData->mnTrackFlags );
143 InvertTracking( rRect, nFlags );
146 pWinData->mpTrackRect = rRect;
147 pWinData->mnTrackFlags = nFlags;
148 mpWindowImpl->mbTrackVisible = true;
151 void Window::HideTracking()
153 if ( mpWindowImpl->mbTrackVisible )
155 ImplWinData* pWinData = ImplGetWinData();
156 if ( !mpWindowImpl->mbInPaint || !(pWinData->mnTrackFlags & ShowTrackFlags::TrackWindow) )
157 InvertTracking( *pWinData->mpTrackRect, pWinData->mnTrackFlags );
158 mpWindowImpl->mbTrackVisible = false;
162 void Window::InvertTracking( const tools::Rectangle& rRect, ShowTrackFlags nFlags )
164 OutputDevice *pOutDev = GetOutDev();
165 tools::Rectangle aRect( pOutDev->ImplLogicToDevicePixel( rRect ) );
167 if ( aRect.IsEmpty() )
168 return;
169 aRect.Normalize();
171 SalGraphics* pGraphics;
173 if ( nFlags & ShowTrackFlags::TrackWindow )
175 if ( !GetOutDev()->IsDeviceOutputNecessary() )
176 return;
178 // we need a graphics
179 if ( !GetOutDev()->mpGraphics )
181 if ( !pOutDev->AcquireGraphics() )
182 return;
185 if ( GetOutDev()->mbInitClipRegion )
186 GetOutDev()->InitClipRegion();
188 if ( GetOutDev()->mbOutputClipped )
189 return;
191 pGraphics = GetOutDev()->mpGraphics;
193 else
195 pGraphics = ImplGetFrameGraphics();
197 if ( nFlags & ShowTrackFlags::Clip )
199 vcl::Region aRegion( GetOutputRectPixel() );
200 ImplClipBoundaries( aRegion, false, false );
201 pOutDev->SelectClipRegion( aRegion, pGraphics );
205 ShowTrackFlags nStyle = nFlags & ShowTrackFlags::StyleMask;
206 if ( nStyle == ShowTrackFlags::Object )
207 pGraphics->Invert( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), SalInvert::TrackFrame, *GetOutDev() );
208 else if ( nStyle == ShowTrackFlags::Split )
209 pGraphics->Invert( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), SalInvert::N50, *GetOutDev() );
210 else
212 tools::Long nBorder = 1;
213 if ( nStyle == ShowTrackFlags::Big )
214 nBorder = 5;
215 pGraphics->Invert( aRect.Left(), aRect.Top(), aRect.GetWidth(), nBorder, SalInvert::N50, *GetOutDev() );
216 pGraphics->Invert( aRect.Left(), aRect.Bottom()-nBorder+1, aRect.GetWidth(), nBorder, SalInvert::N50, *GetOutDev() );
217 pGraphics->Invert( aRect.Left(), aRect.Top()+nBorder, nBorder, aRect.GetHeight()-(nBorder*2), SalInvert::N50, *GetOutDev() );
218 pGraphics->Invert( aRect.Right()-nBorder+1, aRect.Top()+nBorder, nBorder, aRect.GetHeight()-(nBorder*2), SalInvert::N50, *GetOutDev() );
222 IMPL_LINK( Window, ImplTrackTimerHdl, Timer*, pTimer, void )
224 if (!mpWindowImpl)
226 SAL_WARN("vcl", "ImplTrackTimerHdl has outlived dispose");
227 return;
230 ImplSVData* pSVData = ImplGetSVData();
232 // if Button-Repeat we have to change the timeout
233 if ( pSVData->mpWinData->mnTrackFlags & StartTrackingFlags::ButtonRepeat )
234 pTimer->SetTimeout( GetSettings().GetMouseSettings().GetButtonRepeat() );
236 // create Tracking-Event
237 Point aMousePos( mpWindowImpl->mpFrameData->mnLastMouseX, mpWindowImpl->mpFrameData->mnLastMouseY );
238 if( GetOutDev()->ImplIsAntiparallel() )
240 // re-mirror frame pos at pChild
241 const OutputDevice *pOutDev = GetOutDev();
242 pOutDev->ReMirror( aMousePos );
244 MouseEvent aMEvt( ScreenToOutputPixel( aMousePos ),
245 mpWindowImpl->mpFrameData->mnClickCount, MouseEventModifiers::NONE,
246 mpWindowImpl->mpFrameData->mnMouseCode,
247 mpWindowImpl->mpFrameData->mnMouseCode );
248 TrackingEvent aTEvt( aMEvt, TrackingEventFlags::Repeat );
249 Tracking( aTEvt );
252 void Window::SetUseFrameData(bool bUseFrameData)
254 if (mpWindowImpl)
255 mpWindowImpl->mbUseFrameData = bUseFrameData;
258 void Window::StartTracking( StartTrackingFlags nFlags )
260 if (!mpWindowImpl)
261 return;
263 ImplSVData* pSVData = ImplGetSVData();
264 VclPtr<vcl::Window> pTrackWin = mpWindowImpl->mbUseFrameData ?
265 mpWindowImpl->mpFrameData->mpTrackWin :
266 pSVData->mpWinData->mpTrackWin;
268 if ( pTrackWin.get() != this )
270 if ( pTrackWin )
271 pTrackWin->EndTracking( TrackingEventFlags::Cancel );
274 SAL_WARN_IF(pSVData->mpWinData->mpTrackTimer, "vcl", "StartTracking called while TrackerTimer still running");
276 if ( !mpWindowImpl->mbUseFrameData &&
277 (nFlags & (StartTrackingFlags::ScrollRepeat | StartTrackingFlags::ButtonRepeat)) )
279 pSVData->mpWinData->mpTrackTimer.reset(new AutoTimer("vcl::Window pSVData->mpWinData->mpTrackTimer"));
281 if ( nFlags & StartTrackingFlags::ScrollRepeat )
282 pSVData->mpWinData->mpTrackTimer->SetTimeout( MouseSettings::GetScrollRepeat() );
283 else
284 pSVData->mpWinData->mpTrackTimer->SetTimeout( MouseSettings::GetButtonStartRepeat() );
285 pSVData->mpWinData->mpTrackTimer->SetInvokeHandler( LINK( this, Window, ImplTrackTimerHdl ) );
286 pSVData->mpWinData->mpTrackTimer->Start();
289 if (mpWindowImpl->mbUseFrameData)
291 mpWindowImpl->mpFrameData->mpTrackWin = this;
293 else
295 pSVData->mpWinData->mpTrackWin = this;
296 pSVData->mpWinData->mnTrackFlags = nFlags;
297 CaptureMouse();
301 void Window::EndTracking( TrackingEventFlags nFlags )
303 if (!mpWindowImpl)
304 return;
306 ImplSVData* pSVData = ImplGetSVData();
307 VclPtr<vcl::Window> pTrackWin = mpWindowImpl->mbUseFrameData ?
308 mpWindowImpl->mpFrameData->mpTrackWin :
309 pSVData->mpWinData->mpTrackWin;
311 if ( pTrackWin.get() != this )
312 return;
314 if ( !mpWindowImpl->mbUseFrameData && pSVData->mpWinData->mpTrackTimer )
315 pSVData->mpWinData->mpTrackTimer.reset();
317 mpWindowImpl->mpFrameData->mpTrackWin = pSVData->mpWinData->mpTrackWin = nullptr;
318 pSVData->mpWinData->mnTrackFlags = StartTrackingFlags::NONE;
319 ReleaseMouse();
321 // call EndTracking if required
322 if (mpWindowImpl->mpFrameData)
324 Point aMousePos( mpWindowImpl->mpFrameData->mnLastMouseX, mpWindowImpl->mpFrameData->mnLastMouseY );
325 if( GetOutDev()->ImplIsAntiparallel() )
327 // re-mirror frame pos at pChild
328 const OutputDevice *pOutDev = GetOutDev();
329 pOutDev->ReMirror( aMousePos );
332 MouseEvent aMEvt( ScreenToOutputPixel( aMousePos ),
333 mpWindowImpl->mpFrameData->mnClickCount, MouseEventModifiers::NONE,
334 mpWindowImpl->mpFrameData->mnMouseCode,
335 mpWindowImpl->mpFrameData->mnMouseCode );
336 TrackingEvent aTEvt( aMEvt, nFlags | TrackingEventFlags::End );
337 // CompatTracking effectively
338 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
339 return Window::Tracking( aTEvt );
340 else
341 return Tracking( aTEvt );
345 bool Window::IsTracking() const
347 if (!mpWindowImpl)
348 return false;
349 if (mpWindowImpl->mbUseFrameData && mpWindowImpl->mpFrameData)
351 return mpWindowImpl->mpFrameData->mpTrackWin == this;
353 if (!mpWindowImpl->mbUseFrameData && ImplGetSVData()->mpWinData)
355 return ImplGetSVData()->mpWinData->mpTrackWin == this;
357 return false;
360 void Window::StartAutoScroll( StartAutoScrollFlags nFlags )
362 ImplSVData* pSVData = ImplGetSVData();
364 if ( pSVData->mpWinData->mpAutoScrollWin.get() != this )
366 if ( pSVData->mpWinData->mpAutoScrollWin )
367 pSVData->mpWinData->mpAutoScrollWin->EndAutoScroll();
370 pSVData->mpWinData->mpAutoScrollWin = this;
371 pSVData->mpWinData->mnAutoScrollFlags = nFlags;
372 pSVData->maAppData.mpWheelWindow = VclPtr<ImplWheelWindow>::Create( this );
375 void Window::EndAutoScroll()
377 ImplSVData* pSVData = ImplGetSVData();
379 if ( pSVData->mpWinData->mpAutoScrollWin.get() == this )
381 pSVData->mpWinData->mpAutoScrollWin = nullptr;
382 pSVData->mpWinData->mnAutoScrollFlags = StartAutoScrollFlags::NONE;
383 pSVData->maAppData.mpWheelWindow->ImplStop();
384 pSVData->maAppData.mpWheelWindow.disposeAndClear();
388 VclPtr<vcl::Window> Window::SaveFocus()
390 ImplSVData* pSVData = ImplGetSVData();
391 if ( pSVData->mpWinData->mpFocusWin )
393 return pSVData->mpWinData->mpFocusWin;
395 else
396 return nullptr;
399 void Window::EndSaveFocus(const VclPtr<vcl::Window>& xFocusWin)
401 if (xFocusWin && !xFocusWin->isDisposed())
403 xFocusWin->GrabFocus();
407 void Window::SetZoom( const Fraction& rZoom )
409 if ( mpWindowImpl && mpWindowImpl->maZoom != rZoom )
411 mpWindowImpl->maZoom = rZoom;
412 CompatStateChanged( StateChangedType::Zoom );
416 void Window::SetZoomedPointFont(vcl::RenderContext& rRenderContext, const vcl::Font& rFont)
418 const Fraction& rZoom = GetZoom();
419 if (rZoom.GetNumerator() != rZoom.GetDenominator())
421 vcl::Font aFont(rFont);
422 Size aSize = aFont.GetFontSize();
423 aSize.setWidth(basegfx::fround<tools::Long>(double(aSize.Width() * rZoom)));
424 aSize.setHeight(basegfx::fround<tools::Long>(double(aSize.Height() * rZoom)));
425 aFont.SetFontSize(aSize);
426 SetPointFont(rRenderContext, aFont);
428 else
430 SetPointFont(rRenderContext, rFont);
434 tools::Long Window::CalcZoom( tools::Long nCalc ) const
437 const Fraction& rZoom = GetZoom();
438 if ( rZoom.GetNumerator() != rZoom.GetDenominator() )
440 double n = double(nCalc * rZoom);
441 nCalc = basegfx::fround<tools::Long>(n);
443 return nCalc;
446 void Window::SetControlFont()
448 if (mpWindowImpl && mpWindowImpl->mpControlFont)
450 mpWindowImpl->mpControlFont.reset();
451 CompatStateChanged(StateChangedType::ControlFont);
455 void Window::SetControlFont(const vcl::Font& rFont)
457 if (rFont == vcl::Font())
459 SetControlFont();
460 return;
463 if (mpWindowImpl->mpControlFont)
465 if (*mpWindowImpl->mpControlFont == rFont)
466 return;
467 *mpWindowImpl->mpControlFont = rFont;
469 else
470 mpWindowImpl->mpControlFont = rFont;
472 CompatStateChanged(StateChangedType::ControlFont);
475 vcl::Font Window::GetControlFont() const
477 if (mpWindowImpl->mpControlFont)
478 return *mpWindowImpl->mpControlFont;
479 else
481 vcl::Font aFont;
482 return aFont;
486 void Window::ApplyControlFont(vcl::RenderContext& rRenderContext, const vcl::Font& rFont)
488 vcl::Font aFont(rFont);
489 if (IsControlFont())
490 aFont.Merge(GetControlFont());
491 SetZoomedPointFont(rRenderContext, aFont);
494 void Window::SetControlForeground()
496 if (mpWindowImpl->mbControlForeground)
498 mpWindowImpl->maControlForeground = COL_TRANSPARENT;
499 mpWindowImpl->mbControlForeground = false;
500 CompatStateChanged(StateChangedType::ControlForeground);
504 void Window::SetControlForeground(const Color& rColor)
506 if (rColor.IsTransparent())
508 if (mpWindowImpl->mbControlForeground)
510 mpWindowImpl->maControlForeground = COL_TRANSPARENT;
511 mpWindowImpl->mbControlForeground = false;
512 CompatStateChanged(StateChangedType::ControlForeground);
515 else
517 if (mpWindowImpl->maControlForeground != rColor)
519 mpWindowImpl->maControlForeground = rColor;
520 mpWindowImpl->mbControlForeground = true;
521 CompatStateChanged(StateChangedType::ControlForeground);
526 void Window::ApplyControlForeground(vcl::RenderContext& rRenderContext, const Color& rDefaultColor)
528 Color aTextColor(rDefaultColor);
529 if (IsControlForeground())
530 aTextColor = GetControlForeground();
531 rRenderContext.SetTextColor(aTextColor);
534 void Window::SetControlBackground()
536 if (mpWindowImpl->mbControlBackground)
538 mpWindowImpl->maControlBackground = COL_TRANSPARENT;
539 mpWindowImpl->mbControlBackground = false;
540 CompatStateChanged(StateChangedType::ControlBackground);
544 void Window::SetControlBackground(const Color& rColor)
546 if (rColor.IsTransparent())
548 if (mpWindowImpl->mbControlBackground)
550 mpWindowImpl->maControlBackground = COL_TRANSPARENT;
551 mpWindowImpl->mbControlBackground = false;
552 CompatStateChanged(StateChangedType::ControlBackground);
555 else
557 if (mpWindowImpl->maControlBackground != rColor)
559 mpWindowImpl->maControlBackground = rColor;
560 mpWindowImpl->mbControlBackground = true;
561 CompatStateChanged(StateChangedType::ControlBackground);
566 void Window::ApplyControlBackground(vcl::RenderContext& rRenderContext, const Color& rDefaultColor)
568 Color aColor(rDefaultColor);
569 if (IsControlBackground())
570 aColor = GetControlBackground();
571 rRenderContext.SetBackground(aColor);
574 Size Window::CalcWindowSize( const Size& rOutSz ) const
576 Size aSz = rOutSz;
577 aSz.AdjustWidth(mpWindowImpl->mnLeftBorder+mpWindowImpl->mnRightBorder );
578 aSz.AdjustHeight(mpWindowImpl->mnTopBorder+mpWindowImpl->mnBottomBorder );
579 return aSz;
582 Size Window::CalcOutputSize( const Size& rWinSz ) const
584 Size aSz = rWinSz;
585 aSz.AdjustWidth( -(mpWindowImpl->mnLeftBorder+mpWindowImpl->mnRightBorder) );
586 aSz.AdjustHeight( -(mpWindowImpl->mnTopBorder+mpWindowImpl->mnBottomBorder) );
587 return aSz;
590 vcl::Font Window::GetDrawPixelFont(OutputDevice const * pDev) const
592 vcl::Font aFont = GetPointFont(*GetOutDev());
593 Size aFontSize = aFont.GetFontSize();
594 MapMode aPtMapMode(MapUnit::MapPoint);
595 aFontSize = pDev->LogicToPixel( aFontSize, aPtMapMode );
596 aFont.SetFontSize( aFontSize );
597 return aFont;
600 tools::Long Window::GetDrawPixel( OutputDevice const * pDev, tools::Long nPixels ) const
602 tools::Long nP = nPixels;
603 if ( pDev->GetOutDevType() != OUTDEV_WINDOW )
605 MapMode aMap( MapUnit::Map100thMM );
606 Size aSz( nP, 0 );
607 aSz = PixelToLogic( aSz, aMap );
608 aSz = pDev->LogicToPixel( aSz, aMap );
609 nP = aSz.Width();
611 return nP;
614 // returns how much was actually scrolled (so that abs(retval) <= abs(nN))
615 static double lcl_HandleScrollHelper( Scrollable* pScrl, double nN, bool isMultiplyByLineSize )
617 if (!pScrl || !nN || pScrl->Inactive())
618 return 0.0;
620 tools::Long nNewPos = pScrl->GetThumbPos();
621 double scrolled = nN;
623 if ( nN == double(-LONG_MAX) )
624 nNewPos += pScrl->GetPageSize();
625 else if ( nN == double(LONG_MAX) )
626 nNewPos -= pScrl->GetPageSize();
627 else
629 // allowing both chunked and continuous scrolling
630 if(isMultiplyByLineSize){
631 nN*=pScrl->GetLineSize();
634 // compute how many quantized units to scroll
635 tools::Long magnitude = o3tl::saturating_cast<tools::Long>(fabs(nN));
636 tools::Long change = copysign(magnitude, nN);
638 nNewPos = nNewPos - change;
640 scrolled = double(change);
641 // convert back to chunked/continuous
642 if(isMultiplyByLineSize){
643 scrolled /= pScrl->GetLineSize();
647 pScrl->DoScroll( nNewPos );
649 return scrolled;
652 bool Window::HandleScrollCommand( const CommandEvent& rCmd,
653 Scrollable* pHScrl, Scrollable* pVScrl )
655 bool bRet = false;
657 if ( pHScrl || pVScrl )
659 switch( rCmd.GetCommand() )
661 case CommandEventId::StartAutoScroll:
663 StartAutoScrollFlags nFlags = StartAutoScrollFlags::NONE;
664 if ( pHScrl )
666 if ( (pHScrl->GetVisibleSize() < pHScrl->GetRangeMax()) &&
667 !pHScrl->Inactive() )
668 nFlags |= StartAutoScrollFlags::Horz;
670 if ( pVScrl )
672 if ( (pVScrl->GetVisibleSize() < pVScrl->GetRangeMax()) &&
673 !pVScrl->Inactive() )
674 nFlags |= StartAutoScrollFlags::Vert;
677 if ( nFlags != StartAutoScrollFlags::NONE )
679 StartAutoScroll( nFlags );
680 bRet = true;
683 break;
685 case CommandEventId::Wheel:
687 const CommandWheelData* pData = rCmd.GetWheelData();
689 if ( pData && (CommandWheelMode::SCROLL == pData->GetMode()) )
691 if (!pData->IsDeltaPixel())
693 double nScrollLines = pData->GetScrollLines();
694 double nLines;
695 double* partialScroll = pData->IsHorz()
696 ? &mpWindowImpl->mfPartialScrollX
697 : &mpWindowImpl->mfPartialScrollY;
698 if ( nScrollLines == COMMAND_WHEEL_PAGESCROLL )
700 if ( pData->GetDelta() < 0 )
701 nLines = double(-LONG_MAX);
702 else
703 nLines = double(LONG_MAX);
705 else
706 nLines = *partialScroll + pData->GetNotchDelta() * nScrollLines;
707 if ( nLines )
709 Scrollable* pScrl = pData->IsHorz() ? pHScrl : pVScrl;
710 double scrolled = lcl_HandleScrollHelper( pScrl, nLines, true );
711 *partialScroll = nLines - scrolled;
712 bRet = true;
715 else
717 // Mobile / touch scrolling section
718 const Point & deltaPoint = rCmd.GetMousePosPixel();
720 double deltaXInPixels = double(deltaPoint.X());
721 double deltaYInPixels = double(deltaPoint.Y());
722 Size winSize = GetOutputSizePixel();
724 if(pHScrl)
726 double visSizeX = double(pHScrl->GetVisibleSize());
727 double ratioX = deltaXInPixels / double(winSize.getWidth());
728 tools::Long deltaXInLogic = tools::Long(visSizeX * ratioX);
729 // Touch need to work by pixels. Did not apply this to
730 // Android, as android code may require adaptations
731 // to work with this scrolling code
732 #ifndef IOS
733 tools::Long lineSizeX = pHScrl->GetLineSize();
735 if(lineSizeX)
737 deltaXInLogic /= lineSizeX;
739 else
741 deltaXInLogic = 0;
743 #endif
744 if ( deltaXInLogic)
746 #ifndef IOS
747 bool const isMultiplyByLineSize = true;
748 #else
749 bool const isMultiplyByLineSize = false;
750 #endif
751 lcl_HandleScrollHelper( pHScrl, deltaXInLogic, isMultiplyByLineSize );
752 bRet = true;
755 if(pVScrl)
757 double visSizeY = double(pVScrl->GetVisibleSize());
758 double ratioY = deltaYInPixels / double(winSize.getHeight());
759 tools::Long deltaYInLogic = tools::Long(visSizeY * ratioY);
761 // Touch need to work by pixels. Did not apply this to
762 // Android, as android code may require adaptations
763 // to work with this scrolling code
764 #ifndef IOS
765 tools::Long lineSizeY = pVScrl->GetLineSize();
766 if(lineSizeY)
768 deltaYInLogic /= lineSizeY;
770 else
772 deltaYInLogic = 0;
774 #endif
775 if ( deltaYInLogic )
777 #ifndef IOS
778 bool const isMultiplyByLineSize = true;
779 #else
780 bool const isMultiplyByLineSize = false;
781 #endif
782 lcl_HandleScrollHelper( pVScrl, deltaYInLogic, isMultiplyByLineSize );
784 bRet = true;
790 break;
792 case CommandEventId::GesturePan:
794 const CommandGesturePanData* pData = rCmd.GetGesturePanData();
795 if (pData)
797 if (pData->meEventType == GestureEventPanType::Begin)
799 if (pHScrl)
800 mpWindowImpl->mpFrameData->mnTouchPanPositionX = pHScrl->GetThumbPos();
801 if (pVScrl)
802 mpWindowImpl->mpFrameData->mnTouchPanPositionY = pVScrl->GetThumbPos();
804 else if (pData->meEventType == GestureEventPanType::Update)
806 bool bHorz = pData->meOrientation == PanningOrientation::Horizontal;
807 Scrollable* pScrl = bHorz ? pHScrl : pVScrl;
808 if (pScrl)
810 Point aGesturePt(pData->mfX, pData->mfY);
811 tools::Rectangle aWinRect(this->GetOutputRectPixel());
812 bool bContains = aWinRect.Contains(aGesturePt);
813 if (bContains)
815 double nWinSize;
816 tools::Long nOriginalPos;
817 if (bHorz)
819 nWinSize = GetOutputSizePixel().getWidth();
820 nOriginalPos = mpWindowImpl->mpFrameData->mnTouchPanPositionX;
822 else
824 nWinSize = GetOutputSizePixel().getHeight();
825 nOriginalPos = mpWindowImpl->mpFrameData->mnTouchPanPositionY;
827 double nOffset = pData->mfOffset;
828 double nRatio = nOffset / nWinSize;
829 tools::Long nVisibleSize = pScrl->GetVisibleSize();
830 tools::Long nDeltaInLogic = tools::Long(nVisibleSize * nRatio);
831 tools::Long nNewPos = nOriginalPos - nDeltaInLogic;
833 pScrl->DoScroll(nNewPos);
837 else if (pData->meEventType == GestureEventPanType::End)
839 mpWindowImpl->mpFrameData->mnTouchPanPositionX = -1;
840 mpWindowImpl->mpFrameData->mnTouchPanPositionY = -1;
842 bRet = true;
844 break;
847 case CommandEventId::AutoScroll:
849 const CommandScrollData* pData = rCmd.GetAutoScrollData();
850 if ( pData && (pData->GetDeltaX() || pData->GetDeltaY()) )
852 ImplHandleScroll( pHScrl, pData->GetDeltaX(),
853 pVScrl, pData->GetDeltaY() );
854 bRet = true;
857 break;
859 default:
860 break;
864 return bRet;
867 void Window::ImplHandleScroll( Scrollable* pHScrl, double nX,
868 Scrollable* pVScrl, double nY )
870 lcl_HandleScrollHelper( pHScrl, nX, true );
871 lcl_HandleScrollHelper( pVScrl, nY, true );
874 DockingManager* Window::GetDockingManager()
876 return ImplGetDockingManager();
879 void Window::EnableDocking( bool bEnable )
881 // update list of dockable windows
882 if( bEnable )
883 ImplGetDockingManager()->AddWindow( this );
884 else
885 ImplGetDockingManager()->RemoveWindow( this );
888 // retrieves the list of owner draw decorated windows for this window hierarchy
889 ::std::vector<VclPtr<vcl::Window> >& Window::ImplGetOwnerDrawList()
891 return ImplGetTopmostFrameWindow()->mpWindowImpl->mpFrameData->maOwnerDrawList;
894 void Window::SetHelpId( const OUString& rHelpId )
896 mpWindowImpl->maHelpId = rHelpId;
899 const OUString& Window::GetHelpId() const
901 return mpWindowImpl->maHelpId;
904 // --------- old inline methods ---------------
906 vcl::Window* Window::ImplGetWindow() const
908 if ( mpWindowImpl->mpClientWindow )
909 return mpWindowImpl->mpClientWindow;
910 else
911 return const_cast<vcl::Window*>(this);
914 ImplFrameData* Window::ImplGetFrameData()
916 return mpWindowImpl ? mpWindowImpl->mpFrameData : nullptr;
919 SalFrame* Window::ImplGetFrame() const
921 return mpWindowImpl ? mpWindowImpl->mpFrame : nullptr;
924 weld::Window* Window::GetFrameWeld() const
926 SalFrame* pFrame = ImplGetFrame();
927 return pFrame ? pFrame->GetFrameWeld() : nullptr;
930 vcl::Window* Window::GetFrameWindow() const
932 SalFrame* pFrame = ImplGetFrame();
933 return pFrame ? pFrame->GetWindow() : nullptr;
936 vcl::Window* Window::ImplGetParent() const
938 return mpWindowImpl ? mpWindowImpl->mpParent.get() : nullptr;
941 vcl::Window* Window::ImplGetClientWindow() const
943 return mpWindowImpl ? mpWindowImpl->mpClientWindow.get() : nullptr;
946 vcl::Window* Window::ImplGetBorderWindow() const
948 return mpWindowImpl ? mpWindowImpl->mpBorderWindow.get() : nullptr;
951 vcl::Window* Window::ImplGetFirstOverlapWindow()
953 if (!mpWindowImpl)
955 return nullptr;
958 if ( mpWindowImpl->mbOverlapWin )
959 return this;
960 else
961 return mpWindowImpl->mpOverlapWindow;
964 const vcl::Window* Window::ImplGetFirstOverlapWindow() const
966 if (!mpWindowImpl)
968 return nullptr;
971 if ( mpWindowImpl->mbOverlapWin )
972 return this;
973 else
974 return mpWindowImpl->mpOverlapWindow;
977 vcl::Window* Window::ImplGetFrameWindow() const
979 return mpWindowImpl ? mpWindowImpl->mpFrameWindow.get() : nullptr;
982 bool Window::IsDockingWindow() const
984 return mpWindowImpl && mpWindowImpl->mbDockWin;
987 bool Window::ImplIsFloatingWindow() const
989 return mpWindowImpl && mpWindowImpl->mbFloatWin;
992 bool Window::ImplIsSplitter() const
994 return mpWindowImpl && mpWindowImpl->mbSplitter;
997 bool Window::ImplIsPushButton() const
999 return mpWindowImpl && mpWindowImpl->mbPushButton;
1002 bool Window::ImplIsOverlapWindow() const
1004 return mpWindowImpl && mpWindowImpl->mbOverlapWin;
1007 void Window::ImplSetMouseTransparent( bool bTransparent )
1009 if (mpWindowImpl)
1010 mpWindowImpl->mbMouseTransparent = bTransparent;
1013 void Window::SetCompoundControl( bool bCompound )
1015 if (mpWindowImpl)
1016 mpWindowImpl->mbCompoundControl = bCompound;
1019 WinBits Window::GetStyle() const
1021 return mpWindowImpl ? mpWindowImpl->mnStyle : 0;
1024 WinBits Window::GetPrevStyle() const
1026 return mpWindowImpl ? mpWindowImpl->mnPrevStyle : 0;
1029 WindowExtendedStyle Window::GetExtendedStyle() const
1031 return mpWindowImpl ? mpWindowImpl->mnExtendedStyle : WindowExtendedStyle::NONE;
1034 void Window::SetType( WindowType nType )
1036 if (mpWindowImpl)
1037 mpWindowImpl->mnType = nType;
1040 WindowType Window::GetType() const
1042 if (mpWindowImpl)
1043 return mpWindowImpl->mnType;
1044 else
1045 return WindowType::NONE;
1048 Dialog* Window::GetParentDialog() const
1050 const vcl::Window *pWindow = this;
1052 while( pWindow )
1054 if( pWindow->IsDialog() )
1055 break;
1057 pWindow = pWindow->GetParent();
1060 return const_cast<Dialog *>(dynamic_cast<const Dialog*>(pWindow));
1063 bool Window::IsSystemWindow() const
1065 return mpWindowImpl && mpWindowImpl->mbSysWin;
1068 bool Window::IsDialog() const
1070 return mpWindowImpl && mpWindowImpl->mbDialog;
1073 bool Window::IsMenuFloatingWindow() const
1075 return mpWindowImpl && mpWindowImpl->mbMenuFloatingWindow;
1078 bool Window::IsToolbarFloatingWindow() const
1080 return mpWindowImpl && mpWindowImpl->mbToolbarFloatingWindow;
1083 bool Window::IsNativeFrame() const
1085 if( mpWindowImpl->mbFrame )
1086 // #101741 do not check for WB_CLOSEABLE because undecorated floaters (like menus!) are closeable
1087 if( mpWindowImpl->mnStyle & (WB_MOVEABLE | WB_SIZEABLE) )
1088 return true;
1089 else
1090 return false;
1091 else
1092 return false;
1095 void Window::EnableAllResize()
1097 mpWindowImpl->mbAllResize = true;
1100 void Window::EnableChildTransparentMode( bool bEnable )
1102 mpWindowImpl->mbChildTransparent = bEnable;
1105 bool Window::IsChildTransparentModeEnabled() const
1107 return mpWindowImpl && mpWindowImpl->mbChildTransparent;
1110 bool Window::IsMouseTransparent() const
1112 return mpWindowImpl && mpWindowImpl->mbMouseTransparent;
1115 bool Window::IsPaintTransparent() const
1117 return mpWindowImpl && mpWindowImpl->mbPaintTransparent;
1120 void Window::SetDialogControlStart( bool bStart )
1122 mpWindowImpl->mbDlgCtrlStart = bStart;
1125 bool Window::IsDialogControlStart() const
1127 return mpWindowImpl && mpWindowImpl->mbDlgCtrlStart;
1130 void Window::SetDialogControlFlags( DialogControlFlags nFlags )
1132 mpWindowImpl->mnDlgCtrlFlags = nFlags;
1135 DialogControlFlags Window::GetDialogControlFlags() const
1137 return mpWindowImpl->mnDlgCtrlFlags;
1140 const InputContext& Window::GetInputContext() const
1142 return mpWindowImpl->maInputContext;
1145 bool Window::IsControlFont() const
1147 return bool(mpWindowImpl->mpControlFont);
1150 const Color& Window::GetControlForeground() const
1152 return mpWindowImpl->maControlForeground;
1155 bool Window::IsControlForeground() const
1157 return mpWindowImpl->mbControlForeground;
1160 const Color& Window::GetControlBackground() const
1162 return mpWindowImpl->maControlBackground;
1165 bool Window::IsControlBackground() const
1167 return mpWindowImpl->mbControlBackground;
1170 bool Window::IsInPaint() const
1172 return mpWindowImpl && mpWindowImpl->mbInPaint;
1175 vcl::Window* Window::GetParent() const
1177 return mpWindowImpl ? mpWindowImpl->mpRealParent.get() : nullptr;
1180 bool Window::IsVisible() const
1182 return mpWindowImpl && mpWindowImpl->mbVisible;
1185 bool Window::IsReallyVisible() const
1187 return mpWindowImpl && mpWindowImpl->mbReallyVisible;
1190 bool Window::IsReallyShown() const
1192 return mpWindowImpl && mpWindowImpl->mbReallyShown;
1195 bool Window::IsInInitShow() const
1197 return mpWindowImpl->mbInInitShow;
1200 bool Window::IsEnabled() const
1202 return mpWindowImpl && !mpWindowImpl->mbDisabled;
1205 bool Window::IsInputEnabled() const
1207 return mpWindowImpl && !mpWindowImpl->mbInputDisabled;
1210 bool Window::IsAlwaysEnableInput() const
1212 return mpWindowImpl->meAlwaysInputMode == AlwaysInputEnabled;
1215 ActivateModeFlags Window::GetActivateMode() const
1217 return mpWindowImpl->mnActivateMode;
1221 bool Window::IsAlwaysOnTopEnabled() const
1223 return mpWindowImpl->mbAlwaysOnTop;
1226 bool Window::IsDefaultPos() const
1228 return mpWindowImpl->mbDefPos;
1231 bool Window::IsDefaultSize() const
1233 return mpWindowImpl->mbDefSize;
1236 Point Window::GetOffsetPixelFrom(const vcl::Window& rWindow) const
1238 return Point(GetOutOffXPixel() - rWindow.GetOutOffXPixel(), GetOutOffYPixel() - rWindow.GetOutOffYPixel());
1241 void Window::EnablePaint( bool bEnable )
1243 mpWindowImpl->mbPaintDisabled = !bEnable;
1246 bool Window::IsPaintEnabled() const
1248 return !mpWindowImpl->mbPaintDisabled;
1251 bool Window::IsUpdateMode() const
1253 return !mpWindowImpl->mbNoUpdate;
1256 void Window::SetParentUpdateMode( bool bUpdate )
1258 mpWindowImpl->mbNoParentUpdate = !bUpdate;
1261 bool Window::IsActive() const
1263 return mpWindowImpl->mbActive;
1266 GetFocusFlags Window::GetGetFocusFlags() const
1268 return mpWindowImpl->mnGetFocusFlags;
1271 bool Window::IsCompoundControl() const
1273 return mpWindowImpl && mpWindowImpl->mbCompoundControl;
1276 bool Window::IsWait() const
1278 return (mpWindowImpl->mnWaitCount != 0);
1281 vcl::Cursor* Window::GetCursor() const
1283 if (!mpWindowImpl)
1284 return nullptr;
1285 return mpWindowImpl->mpCursor;
1288 const Fraction& Window::GetZoom() const
1290 return mpWindowImpl->maZoom;
1293 bool Window::IsZoom() const
1295 return mpWindowImpl->maZoom.GetNumerator() != mpWindowImpl->maZoom.GetDenominator();
1298 void Window::SetHelpText( const OUString& rHelpText )
1300 mpWindowImpl->maHelpText = rHelpText;
1301 mpWindowImpl->mbHelpTextDynamic = true;
1304 void Window::SetQuickHelpText( const OUString& rHelpText )
1306 if (mpWindowImpl)
1307 mpWindowImpl->maQuickHelpText = rHelpText;
1310 const OUString& Window::GetQuickHelpText() const
1312 return mpWindowImpl->maQuickHelpText;
1315 bool Window::IsCreatedWithToolkit() const
1317 return mpWindowImpl->mbCreatedWithToolkit;
1320 void Window::SetCreatedWithToolkit( bool b )
1322 mpWindowImpl->mbCreatedWithToolkit = b;
1325 PointerStyle Window::GetPointer() const
1327 return mpWindowImpl->maPointer;
1330 VCLXWindow* Window::GetWindowPeer() const
1332 return mpWindowImpl ? mpWindowImpl->mpVCLXWindow : nullptr;
1335 void Window::SetPosPixel( const Point& rNewPos )
1337 setPosSizePixel( rNewPos.X(), rNewPos.Y(), 0, 0, PosSizeFlags::Pos );
1340 void Window::SetSizePixel( const Size& rNewSize )
1342 setPosSizePixel( 0, 0, rNewSize.Width(), rNewSize.Height(),
1343 PosSizeFlags::Size );
1346 void Window::SetPosSizePixel( const Point& rNewPos, const Size& rNewSize )
1348 setPosSizePixel( rNewPos.X(), rNewPos.Y(),
1349 rNewSize.Width(), rNewSize.Height());
1352 void Window::SetOutputSizePixel( const Size& rNewSize )
1354 SetSizePixel( Size( rNewSize.Width()+mpWindowImpl->mnLeftBorder+mpWindowImpl->mnRightBorder,
1355 rNewSize.Height()+mpWindowImpl->mnTopBorder+mpWindowImpl->mnBottomBorder ) );
1358 //When a widget wants to renegotiate layout, get toplevel parent dialog and call
1359 //resize on it. Mark all intermediate containers (or container-alike) widgets
1360 //as dirty for the size remains unchanged, but layout changed circumstances
1361 namespace
1363 bool queue_ungrouped_resize(vcl::Window const *pOrigWindow)
1365 bool bSomeoneCares = false;
1367 vcl::Window *pWindow = pOrigWindow->GetParent();
1368 if (pWindow)
1370 if (isContainerWindow(*pWindow))
1372 bSomeoneCares = true;
1374 else if (pWindow->GetType() == WindowType::TABCONTROL)
1376 bSomeoneCares = true;
1378 pWindow->queue_resize();
1381 return bSomeoneCares;
1385 void Window::InvalidateSizeCache()
1387 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1388 pWindowImpl->mnOptimalWidthCache = -1;
1389 pWindowImpl->mnOptimalHeightCache = -1;
1392 static bool HasParentDockingWindow(const vcl::Window* pWindow)
1394 while( pWindow )
1396 if( pWindow->IsDockingWindow() )
1397 return true;
1399 pWindow = pWindow->GetParent();
1402 return false;
1405 void Window::queue_resize(StateChangedType eReason)
1407 if (isDisposed())
1408 return;
1410 bool bSomeoneCares = queue_ungrouped_resize(this);
1412 if (eReason != StateChangedType::Visible)
1414 InvalidateSizeCache();
1417 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1418 if (pWindowImpl->m_xSizeGroup && pWindowImpl->m_xSizeGroup->get_mode() != VclSizeGroupMode::NONE)
1420 std::set<VclPtr<vcl::Window> > &rWindows = pWindowImpl->m_xSizeGroup->get_widgets();
1421 for (VclPtr<vcl::Window> const & pOther : rWindows)
1423 if (pOther == this)
1424 continue;
1425 queue_ungrouped_resize(pOther);
1429 if (bSomeoneCares && !isDisposed())
1431 //fdo#57090 force a resync of the borders of the borderwindow onto this
1432 //window in case they have changed
1433 vcl::Window* pBorderWindow = ImplGetBorderWindow();
1434 if (pBorderWindow)
1435 pBorderWindow->Resize();
1437 if (VclPtr<vcl::Window> pParent = GetParentWithLOKNotifier())
1439 Size aSize = GetSizePixel();
1440 if (!aSize.IsEmpty() && !pParent->IsInInitShow()
1441 && (GetParentDialog() || HasParentDockingWindow(this)))
1442 LogicInvalidate(nullptr);
1446 namespace
1448 VclAlign toAlign(std::u16string_view rValue)
1450 VclAlign eRet = VclAlign::Fill;
1452 if (rValue == u"fill")
1453 eRet = VclAlign::Fill;
1454 else if (rValue == u"start")
1455 eRet = VclAlign::Start;
1456 else if (rValue == u"end")
1457 eRet = VclAlign::End;
1458 else if (rValue == u"center")
1459 eRet = VclAlign::Center;
1460 return eRet;
1464 bool Window::set_font_attribute(const OUString &rKey, std::u16string_view rValue)
1466 if (rKey == "weight")
1468 vcl::Font aFont(GetControlFont());
1469 if (rValue == u"thin")
1470 aFont.SetWeight(WEIGHT_THIN);
1471 else if (rValue == u"ultralight")
1472 aFont.SetWeight(WEIGHT_ULTRALIGHT);
1473 else if (rValue == u"light")
1474 aFont.SetWeight(WEIGHT_LIGHT);
1475 else if (rValue == u"book")
1476 aFont.SetWeight(WEIGHT_SEMILIGHT);
1477 else if (rValue == u"normal")
1478 aFont.SetWeight(WEIGHT_NORMAL);
1479 else if (rValue == u"medium")
1480 aFont.SetWeight(WEIGHT_MEDIUM);
1481 else if (rValue == u"semibold")
1482 aFont.SetWeight(WEIGHT_SEMIBOLD);
1483 else if (rValue == u"bold")
1484 aFont.SetWeight(WEIGHT_BOLD);
1485 else if (rValue == u"ultrabold")
1486 aFont.SetWeight(WEIGHT_ULTRABOLD);
1487 else
1488 aFont.SetWeight(WEIGHT_BLACK);
1489 SetControlFont(aFont);
1491 else if (rKey == "style")
1493 vcl::Font aFont(GetControlFont());
1494 if (rValue == u"normal")
1495 aFont.SetItalic(ITALIC_NONE);
1496 else if (rValue == u"oblique")
1497 aFont.SetItalic(ITALIC_OBLIQUE);
1498 else if (rValue == u"italic")
1499 aFont.SetItalic(ITALIC_NORMAL);
1500 SetControlFont(aFont);
1502 else if (rKey == "underline")
1504 vcl::Font aFont(GetControlFont());
1505 aFont.SetUnderline(toBool(rValue) ? LINESTYLE_SINGLE : LINESTYLE_NONE);
1506 SetControlFont(aFont);
1508 else if (rKey == "scale")
1510 // if no control font was set yet, take the underlying font from the device
1511 vcl::Font aFont(IsControlFont() ? GetControlFont() : GetPointFont(*GetOutDev()));
1512 aFont.SetFontHeight(aFont.GetFontHeight() * o3tl::toDouble(rValue));
1513 SetControlFont(aFont);
1515 else if (rKey == "size")
1517 vcl::Font aFont(GetControlFont());
1518 sal_Int32 nHeight = o3tl::toInt32(rValue) / 1000;
1519 aFont.SetFontHeight(nHeight);
1520 SetControlFont(aFont);
1522 else
1524 SAL_INFO("vcl.layout", "unhandled font attribute: " << rKey);
1525 return false;
1527 return true;
1530 bool Window::set_property(const OUString &rKey, const OUString &rValue)
1532 if ((rKey == "label") || (rKey == "title") || (rKey == "text") )
1534 SetText(BuilderUtils::convertMnemonicMarkup(rValue));
1536 else if (rKey == "visible")
1537 Show(toBool(rValue));
1538 else if (rKey == "sensitive")
1539 Enable(toBool(rValue));
1540 else if (rKey == "resizable")
1542 WinBits nBits = GetStyle();
1543 nBits &= ~WB_SIZEABLE;
1544 if (toBool(rValue))
1545 nBits |= WB_SIZEABLE;
1546 SetStyle(nBits);
1548 else if (rKey == "xalign")
1550 WinBits nBits = GetStyle();
1551 nBits &= ~(WB_LEFT | WB_CENTER | WB_RIGHT);
1553 float f = rValue.toFloat();
1554 assert(f == 0.0 || f == 1.0 || f == 0.5);
1555 if (f == 0.0)
1556 nBits |= WB_LEFT;
1557 else if (f == 1.0)
1558 nBits |= WB_RIGHT;
1559 else if (f == 0.5)
1560 nBits |= WB_CENTER;
1562 SetStyle(nBits);
1564 else if (rKey == "justification")
1566 WinBits nBits = GetStyle();
1567 nBits &= ~(WB_LEFT | WB_CENTER | WB_RIGHT);
1569 if (rValue == "left")
1570 nBits |= WB_LEFT;
1571 else if (rValue == "right")
1572 nBits |= WB_RIGHT;
1573 else if (rValue == "center")
1574 nBits |= WB_CENTER;
1576 SetStyle(nBits);
1578 else if (rKey == "yalign")
1580 WinBits nBits = GetStyle();
1581 nBits &= ~(WB_TOP | WB_VCENTER | WB_BOTTOM);
1583 float f = rValue.toFloat();
1584 assert(f == 0.0 || f == 1.0 || f == 0.5);
1585 if (f == 0.0)
1586 nBits |= WB_TOP;
1587 else if (f == 1.0)
1588 nBits |= WB_BOTTOM;
1589 else if (f == 0.5)
1590 nBits |= WB_VCENTER;
1592 SetStyle(nBits);
1594 else if (rKey == "wrap")
1596 WinBits nBits = GetStyle();
1597 nBits &= ~WB_WORDBREAK;
1598 if (toBool(rValue))
1599 nBits |= WB_WORDBREAK;
1600 SetStyle(nBits);
1602 else if (rKey == "height-request")
1603 set_height_request(rValue.toInt32());
1604 else if (rKey == "width-request")
1605 set_width_request(rValue.toInt32());
1606 else if (rKey == "hexpand")
1607 set_hexpand(toBool(rValue));
1608 else if (rKey == "vexpand")
1609 set_vexpand(toBool(rValue));
1610 else if (rKey == "halign")
1611 set_halign(toAlign(rValue));
1612 else if (rKey == "valign")
1613 set_valign(toAlign(rValue));
1614 else if (rKey == "tooltip-markup")
1615 SetQuickHelpText(rValue);
1616 else if (rKey == "tooltip-text")
1617 SetQuickHelpText(rValue);
1618 else if (rKey == "border-width")
1619 set_border_width(rValue.toInt32());
1620 else if (rKey == "margin-start" || rKey == "margin-left")
1622 assert(rKey == "margin-start" && "margin-left deprecated in favor of margin-start");
1623 set_margin_start(rValue.toInt32());
1625 else if (rKey == "margin-end" || rKey == "margin-right")
1627 assert(rKey == "margin-end" && "margin-right deprecated in favor of margin-end");
1628 set_margin_end(rValue.toInt32());
1630 else if (rKey == "margin-top")
1631 set_margin_top(rValue.toInt32());
1632 else if (rKey == "margin-bottom")
1633 set_margin_bottom(rValue.toInt32());
1634 else if (rKey == "hscrollbar-policy")
1636 WinBits nBits = GetStyle();
1637 nBits &= ~(WB_AUTOHSCROLL|WB_HSCROLL);
1638 if (rValue == "always")
1639 nBits |= WB_HSCROLL;
1640 else if (rValue == "automatic")
1641 nBits |= WB_AUTOHSCROLL;
1642 SetStyle(nBits);
1644 else if (rKey == "vscrollbar-policy")
1646 WinBits nBits = GetStyle();
1647 nBits &= ~(WB_AUTOVSCROLL|WB_VSCROLL);
1648 if (rValue == "always")
1649 nBits |= WB_VSCROLL;
1650 else if (rValue == "automatic")
1651 nBits |= WB_AUTOVSCROLL;
1652 SetStyle(nBits);
1654 else if (rKey == "accessible-name")
1656 SetAccessibleName(rValue);
1658 else if (rKey == "accessible-description")
1660 SetAccessibleDescription(rValue);
1662 else if (rKey == "accessible-role")
1664 sal_Int16 role = BuilderUtils::getRoleFromName(rValue);
1665 if (role != css::accessibility::AccessibleRole::UNKNOWN)
1666 SetAccessibleRole(role);
1668 else if (rKey == "use-markup")
1670 //https://live.gnome.org/GnomeGoals/RemoveMarkupInMessages
1671 SAL_WARN_IF(toBool(rValue), "vcl.layout", "Use pango attributes instead of mark-up");
1673 else if (rKey == "has-focus")
1675 if (toBool(rValue))
1676 GrabFocus();
1678 else if (rKey == "can-focus")
1680 WinBits nBits = GetStyle();
1681 nBits &= ~(WB_TABSTOP|WB_NOTABSTOP);
1682 if (toBool(rValue))
1683 nBits |= WB_TABSTOP;
1684 else
1685 nBits |= WB_NOTABSTOP;
1686 SetStyle(nBits);
1688 else
1690 SAL_INFO("vcl.layout", "unhandled property: " << rKey);
1691 return false;
1693 return true;
1696 void Window::set_height_request(sal_Int32 nHeightRequest)
1698 if (!mpWindowImpl)
1699 return;
1701 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1703 if ( pWindowImpl->mnHeightRequest != nHeightRequest )
1705 pWindowImpl->mnHeightRequest = nHeightRequest;
1706 queue_resize();
1710 void Window::set_width_request(sal_Int32 nWidthRequest)
1712 if (!mpWindowImpl)
1713 return;
1715 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1717 if ( pWindowImpl->mnWidthRequest != nWidthRequest )
1719 pWindowImpl->mnWidthRequest = nWidthRequest;
1720 queue_resize();
1724 Size Window::get_ungrouped_preferred_size() const
1726 Size aRet(get_width_request(), get_height_request());
1727 if (aRet.Width() == -1 || aRet.Height() == -1)
1729 //cache gets blown away by queue_resize
1730 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1731 if (pWindowImpl->mnOptimalWidthCache == -1 || pWindowImpl->mnOptimalHeightCache == -1)
1733 Size aOptimal(GetOptimalSize());
1734 pWindowImpl->mnOptimalWidthCache = aOptimal.Width();
1735 pWindowImpl->mnOptimalHeightCache = aOptimal.Height();
1738 if (aRet.Width() == -1)
1739 aRet.setWidth( pWindowImpl->mnOptimalWidthCache );
1740 if (aRet.Height() == -1)
1741 aRet.setHeight( pWindowImpl->mnOptimalHeightCache );
1743 return aRet;
1746 Size Window::get_preferred_size() const
1748 Size aRet(get_ungrouped_preferred_size());
1750 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1751 if (pWindowImpl->m_xSizeGroup)
1753 const VclSizeGroupMode eMode = pWindowImpl->m_xSizeGroup->get_mode();
1754 if (eMode != VclSizeGroupMode::NONE)
1756 const bool bIgnoreInHidden = pWindowImpl->m_xSizeGroup->get_ignore_hidden();
1757 const std::set<VclPtr<vcl::Window> > &rWindows = pWindowImpl->m_xSizeGroup->get_widgets();
1758 for (auto const& window : rWindows)
1760 const vcl::Window *pOther = window;
1761 if (pOther == this)
1762 continue;
1763 if (bIgnoreInHidden && !pOther->IsVisible())
1764 continue;
1765 Size aOtherSize = pOther->get_ungrouped_preferred_size();
1766 if (eMode == VclSizeGroupMode::Both || eMode == VclSizeGroupMode::Horizontal)
1767 aRet.setWidth( std::max(aRet.Width(), aOtherSize.Width()) );
1768 if (eMode == VclSizeGroupMode::Both || eMode == VclSizeGroupMode::Vertical)
1769 aRet.setHeight( std::max(aRet.Height(), aOtherSize.Height()) );
1774 return aRet;
1777 VclAlign Window::get_halign() const
1779 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1780 return pWindowImpl->meHalign;
1783 void Window::set_halign(VclAlign eAlign)
1785 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1786 pWindowImpl->meHalign = eAlign;
1789 VclAlign Window::get_valign() const
1791 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1792 return pWindowImpl->meValign;
1795 void Window::set_valign(VclAlign eAlign)
1797 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1798 pWindowImpl->meValign = eAlign;
1801 bool Window::get_hexpand() const
1803 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1804 return pWindowImpl->mbHexpand;
1807 void Window::set_hexpand(bool bExpand)
1809 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1810 pWindowImpl->mbHexpand = bExpand;
1813 bool Window::get_vexpand() const
1815 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1816 return pWindowImpl->mbVexpand;
1819 void Window::set_vexpand(bool bExpand)
1821 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1822 pWindowImpl->mbVexpand = bExpand;
1825 bool Window::get_expand() const
1827 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1828 return pWindowImpl->mbExpand;
1831 void Window::set_expand(bool bExpand)
1833 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1834 pWindowImpl->mbExpand = bExpand;
1837 VclPackType Window::get_pack_type() const
1839 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1840 return pWindowImpl->mePackType;
1843 void Window::set_pack_type(VclPackType ePackType)
1845 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1846 pWindowImpl->mePackType = ePackType;
1849 sal_Int32 Window::get_padding() const
1851 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1852 return pWindowImpl->mnPadding;
1855 void Window::set_padding(sal_Int32 nPadding)
1857 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1858 pWindowImpl->mnPadding = nPadding;
1861 bool Window::get_fill() const
1863 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1864 return pWindowImpl->mbFill;
1867 void Window::set_fill(bool bFill)
1869 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1870 pWindowImpl->mbFill = bFill;
1873 sal_Int32 Window::get_grid_width() const
1875 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1876 return pWindowImpl->mnGridWidth;
1879 void Window::set_grid_width(sal_Int32 nCols)
1881 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1882 pWindowImpl->mnGridWidth = nCols;
1885 sal_Int32 Window::get_grid_left_attach() const
1887 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1888 return pWindowImpl->mnGridLeftAttach;
1891 void Window::set_grid_left_attach(sal_Int32 nAttach)
1893 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1894 pWindowImpl->mnGridLeftAttach = nAttach;
1897 sal_Int32 Window::get_grid_height() const
1899 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1900 return pWindowImpl->mnGridHeight;
1903 void Window::set_grid_height(sal_Int32 nRows)
1905 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1906 pWindowImpl->mnGridHeight = nRows;
1909 sal_Int32 Window::get_grid_top_attach() const
1911 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1912 return pWindowImpl->mnGridTopAttach;
1915 void Window::set_grid_top_attach(sal_Int32 nAttach)
1917 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1918 pWindowImpl->mnGridTopAttach = nAttach;
1921 void Window::set_border_width(sal_Int32 nBorderWidth)
1923 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1924 pWindowImpl->mnBorderWidth = nBorderWidth;
1927 sal_Int32 Window::get_border_width() const
1929 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1930 return pWindowImpl->mnBorderWidth;
1933 void Window::set_margin_start(sal_Int32 nWidth)
1935 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1936 if (pWindowImpl->mnMarginLeft != nWidth)
1938 pWindowImpl->mnMarginLeft = nWidth;
1939 queue_resize();
1943 sal_Int32 Window::get_margin_start() const
1945 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1946 return pWindowImpl->mnMarginLeft;
1949 void Window::set_margin_end(sal_Int32 nWidth)
1951 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1952 if (pWindowImpl->mnMarginRight != nWidth)
1954 pWindowImpl->mnMarginRight = nWidth;
1955 queue_resize();
1959 sal_Int32 Window::get_margin_end() const
1961 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1962 return pWindowImpl->mnMarginRight;
1965 void Window::set_margin_top(sal_Int32 nWidth)
1967 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1968 if (pWindowImpl->mnMarginTop != nWidth)
1970 pWindowImpl->mnMarginTop = nWidth;
1971 queue_resize();
1975 sal_Int32 Window::get_margin_top() const
1977 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1978 return pWindowImpl->mnMarginTop;
1981 void Window::set_margin_bottom(sal_Int32 nWidth)
1983 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1984 if (pWindowImpl->mnMarginBottom != nWidth)
1986 pWindowImpl->mnMarginBottom = nWidth;
1987 queue_resize();
1991 sal_Int32 Window::get_margin_bottom() const
1993 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
1994 return pWindowImpl->mnMarginBottom;
1997 sal_Int32 Window::get_height_request() const
1999 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
2000 return pWindowImpl->mnHeightRequest;
2003 sal_Int32 Window::get_width_request() const
2005 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
2006 return pWindowImpl->mnWidthRequest;
2009 bool Window::get_secondary() const
2011 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
2012 return pWindowImpl->mbSecondary;
2015 void Window::set_secondary(bool bSecondary)
2017 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
2018 pWindowImpl->mbSecondary = bSecondary;
2021 bool Window::get_non_homogeneous() const
2023 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
2024 return pWindowImpl->mbNonHomogeneous;
2027 void Window::set_non_homogeneous(bool bNonHomogeneous)
2029 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
2030 pWindowImpl->mbNonHomogeneous = bNonHomogeneous;
2033 void Window::add_to_size_group(const std::shared_ptr<VclSizeGroup>& xGroup)
2035 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
2036 //To-Do, multiple groups
2037 pWindowImpl->m_xSizeGroup = xGroup;
2038 pWindowImpl->m_xSizeGroup->insert(this);
2039 if (VclSizeGroupMode::NONE != pWindowImpl->m_xSizeGroup->get_mode())
2040 queue_resize();
2043 void Window::remove_from_all_size_groups()
2045 WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl.get() : mpWindowImpl.get();
2046 //To-Do, multiple groups
2047 if (pWindowImpl->m_xSizeGroup)
2049 if (VclSizeGroupMode::NONE != pWindowImpl->m_xSizeGroup->get_mode())
2050 queue_resize();
2051 pWindowImpl->m_xSizeGroup->erase(this);
2052 pWindowImpl->m_xSizeGroup.reset();
2056 void Window::add_mnemonic_label(FixedText *pLabel)
2058 std::vector<VclPtr<FixedText> >& v = mpWindowImpl->m_aMnemonicLabels;
2059 if (std::find(v.begin(), v.end(), VclPtr<FixedText>(pLabel)) != v.end())
2060 return;
2061 v.emplace_back(pLabel);
2062 pLabel->set_mnemonic_widget(this);
2065 void Window::remove_mnemonic_label(FixedText *pLabel)
2067 std::vector<VclPtr<FixedText> >& v = mpWindowImpl->m_aMnemonicLabels;
2068 auto aFind = std::find(v.begin(), v.end(), VclPtr<FixedText>(pLabel));
2069 if (aFind == v.end())
2070 return;
2071 v.erase(aFind);
2072 pLabel->set_mnemonic_widget(nullptr);
2075 const std::vector<VclPtr<FixedText> >& Window::list_mnemonic_labels() const
2077 return mpWindowImpl->m_aMnemonicLabels;
2080 } /* namespace vcl */
2082 void InvertFocusRect(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
2084 const int nBorder = 1;
2085 rRenderContext.Invert(tools::Rectangle(Point(rRect.Left(), rRect.Top()), Size(rRect.GetWidth(), nBorder)), InvertFlags::N50);
2086 rRenderContext.Invert(tools::Rectangle(Point(rRect.Left(), rRect.Bottom()-nBorder+1), Size(rRect.GetWidth(), nBorder)), InvertFlags::N50);
2087 rRenderContext.Invert(tools::Rectangle(Point(rRect.Left(), rRect.Top()+nBorder), Size(nBorder, rRect.GetHeight()-(nBorder*2))), InvertFlags::N50);
2088 rRenderContext.Invert(tools::Rectangle(Point(rRect.Right()-nBorder+1, rRect.Top()+nBorder), Size(nBorder, rRect.GetHeight()-(nBorder*2))), InvertFlags::N50);
2091 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */