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 <strings.hrc>
21 #include <svdata.hxx>
22 #include <brdwin.hxx>
23 #include <window.h>
24 
25 #include <vcl/textrectinfo.hxx>
26 #include <vcl/event.hxx>
27 #include <vcl/decoview.hxx>
28 #include <vcl/syswin.hxx>
29 #include <vcl/dockwin.hxx>
30 #include <vcl/floatwin.hxx>
31 #include <vcl/help.hxx>
32 #include <vcl/edit.hxx>
33 #include <vcl/settings.hxx>
34 #include <vcl/toolbox.hxx>
35 #include <vcl/ptrstyle.hxx>
36 
37 using namespace ::com::sun::star::uno;
38 
39 // useful caption height for title bar buttons
40 #define MIN_CAPTION_HEIGHT 18
41 
42 namespace vcl {
43 
ImplCalcSymbolRect(tools::Rectangle & rRect)44 void Window::ImplCalcSymbolRect( tools::Rectangle& rRect )
45 {
46     // Add border, not shown in the non-default representation,
47     // as we want to use it for small buttons
48     rRect.AdjustLeft( -1 );
49     rRect.AdjustTop( -1 );
50     rRect.AdjustRight( 1 );
51     rRect.AdjustBottom( 1 );
52 
53     // we leave 5% room between the symbol and the button border
54     long nExtraWidth = ((rRect.GetWidth()*50)+500)/1000;
55     long nExtraHeight = ((rRect.GetHeight()*50)+500)/1000;
56     rRect.AdjustLeft(nExtraWidth );
57     rRect.AdjustRight( -nExtraWidth );
58     rRect.AdjustTop(nExtraHeight );
59     rRect.AdjustBottom( -nExtraHeight );
60 }
61 
62 } /* namespace vcl */
63 
ImplDrawBrdWinSymbol(vcl::RenderContext * pDev,const tools::Rectangle & rRect,SymbolType eSymbol)64 static void ImplDrawBrdWinSymbol( vcl::RenderContext* pDev,
65                                   const tools::Rectangle& rRect, SymbolType eSymbol )
66 {
67     // we leave 5% room between the symbol and the button border
68     DecorationView  aDecoView( pDev );
69     tools::Rectangle       aTempRect = rRect;
70     vcl::Window::ImplCalcSymbolRect( aTempRect );
71     aDecoView.DrawSymbol( aTempRect, eSymbol,
72                           pDev->GetSettings().GetStyleSettings().GetButtonTextColor() );
73 }
74 
ImplDrawBrdWinSymbolButton(vcl::RenderContext * pDev,const tools::Rectangle & rRect,SymbolType eSymbol,DrawButtonFlags nState)75 static void ImplDrawBrdWinSymbolButton( vcl::RenderContext* pDev,
76                                         const tools::Rectangle& rRect,
77                                         SymbolType eSymbol, DrawButtonFlags nState )
78 {
79     bool bMouseOver(nState & DrawButtonFlags::Highlight);
80     nState &= ~DrawButtonFlags::Highlight;
81 
82     tools::Rectangle aTempRect;
83     vcl::Window *pWin = dynamic_cast< vcl::Window* >(pDev);
84     if( pWin )
85     {
86         if( bMouseOver )
87         {
88             // provide a bright background for selection effect
89             pDev->SetFillColor( pDev->GetSettings().GetStyleSettings().GetWindowColor() );
90             pDev->SetLineColor();
91             pDev->DrawRect( rRect );
92             pWin->DrawSelectionBackground( rRect, 2, bool(nState & DrawButtonFlags::Pressed),
93                                             true );
94         }
95         aTempRect = rRect;
96         aTempRect.AdjustLeft(3 );
97         aTempRect.AdjustRight( -4 );
98         aTempRect.AdjustTop(3 );
99         aTempRect.AdjustBottom( -4 );
100     }
101     else
102     {
103         DecorationView aDecoView( pDev );
104         aTempRect = aDecoView.DrawButton( rRect, nState|DrawButtonFlags::Flat );
105     }
106     ImplDrawBrdWinSymbol( pDev, aTempRect, eSymbol );
107 }
108 
109 
~ImplBorderWindowView()110 ImplBorderWindowView::~ImplBorderWindowView()
111 {
112 }
113 
MouseMove(const MouseEvent &)114 bool ImplBorderWindowView::MouseMove( const MouseEvent& )
115 {
116     return false;
117 }
118 
MouseButtonDown(const MouseEvent &)119 bool ImplBorderWindowView::MouseButtonDown( const MouseEvent& )
120 {
121     return false;
122 }
123 
Tracking(const TrackingEvent &)124 bool ImplBorderWindowView::Tracking( const TrackingEvent& )
125 {
126     return false;
127 }
128 
RequestHelp(const Point &,tools::Rectangle &)129 OUString ImplBorderWindowView::RequestHelp( const Point&, tools::Rectangle& )
130 {
131     return OUString();
132 }
133 
GetMenuRect() const134 tools::Rectangle ImplBorderWindowView::GetMenuRect() const
135 {
136     return tools::Rectangle();
137 }
138 
ImplInitTitle(ImplBorderFrameData * pData)139 void ImplBorderWindowView::ImplInitTitle(ImplBorderFrameData* pData)
140 {
141     ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
142 
143     if ( !(pBorderWindow->GetStyle() & (WB_MOVEABLE | WB_POPUP)) ||
144           (pData->mnTitleType == BorderWindowTitleType::NONE) )
145     {
146         pData->mnTitleType   = BorderWindowTitleType::NONE;
147         pData->mnTitleHeight = 0;
148     }
149     else
150     {
151         const StyleSettings& rStyleSettings = pData->mpOutDev->GetSettings().GetStyleSettings();
152         if (pData->mnTitleType == BorderWindowTitleType::Tearoff)
153             pData->mnTitleHeight = ToolBox::ImplGetDragWidth(*pData->mpBorderWindow, false) + 2;
154         else
155         {
156             if (pData->mnTitleType == BorderWindowTitleType::Small)
157             {
158                 pBorderWindow->SetPointFont(*pBorderWindow, rStyleSettings.GetFloatTitleFont() );
159                 pData->mnTitleHeight = rStyleSettings.GetFloatTitleHeight();
160             }
161             else // pData->mnTitleType == BorderWindowTitleType::Normal
162             {
163                 // FIXME RenderContext
164                 pBorderWindow->SetPointFont(*pBorderWindow, rStyleSettings.GetTitleFont());
165                 pData->mnTitleHeight = rStyleSettings.GetTitleHeight();
166             }
167             long nTextHeight = pBorderWindow->GetTextHeight();
168             if (nTextHeight > pData->mnTitleHeight)
169                 pData->mnTitleHeight = nTextHeight;
170         }
171     }
172 }
173 
ImplHitTest(ImplBorderFrameData const * pData,const Point & rPos)174 BorderWindowHitTest ImplBorderWindowView::ImplHitTest( ImplBorderFrameData const * pData, const Point& rPos )
175 {
176     ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
177 
178     if ( pData->maTitleRect.IsInside( rPos ) )
179     {
180         if ( pData->maCloseRect.IsInside( rPos ) )
181             return BorderWindowHitTest::Close;
182         else if ( pData->maRollRect.IsInside( rPos ) )
183             return BorderWindowHitTest::Roll;
184         else if ( pData->maMenuRect.IsInside( rPos ) )
185             return BorderWindowHitTest::Menu;
186         else if ( pData->maDockRect.IsInside( rPos ) )
187             return BorderWindowHitTest::Dock;
188         else if ( pData->maHideRect.IsInside( rPos ) )
189             return BorderWindowHitTest::Hide;
190         else if ( pData->maHelpRect.IsInside( rPos ) )
191             return BorderWindowHitTest::Help;
192         else
193             return BorderWindowHitTest::Title;
194     }
195 
196     if ( (pBorderWindow->GetStyle() & WB_SIZEABLE) &&
197          !pBorderWindow->mbRollUp )
198     {
199         long nSizeWidth = pData->mnNoTitleTop+pData->mnTitleHeight;
200         if ( nSizeWidth < 16 )
201             nSizeWidth = 16;
202 
203         // no corner resize for floating toolbars, which would lead to jumps while formatting
204         // setting nSizeWidth = 0 will only return pure left,top,right,bottom
205         if( pBorderWindow->GetStyle() & (WB_OWNERDRAWDECORATION | WB_POPUP) )
206             nSizeWidth = 0;
207 
208         if ( rPos.X() < pData->mnLeftBorder )
209         {
210             if ( rPos.Y() < nSizeWidth )
211                 return BorderWindowHitTest::TopLeft;
212             else if ( rPos.Y() >= pData->mnHeight-nSizeWidth )
213                 return BorderWindowHitTest::BottomLeft;
214             else
215                 return BorderWindowHitTest::Left;
216         }
217         else if ( rPos.X() >= pData->mnWidth-pData->mnRightBorder )
218         {
219             if ( rPos.Y() < nSizeWidth )
220                 return BorderWindowHitTest::TopRight;
221             else if ( rPos.Y() >= pData->mnHeight-nSizeWidth )
222                 return BorderWindowHitTest::BottomRight;
223             else
224                 return BorderWindowHitTest::Right;
225         }
226         else if ( rPos.Y() < pData->mnNoTitleTop )
227         {
228             if ( rPos.X() < nSizeWidth )
229                 return BorderWindowHitTest::TopLeft;
230             else if ( rPos.X() >= pData->mnWidth-nSizeWidth )
231                 return BorderWindowHitTest::TopRight;
232             else
233                 return BorderWindowHitTest::Top;
234         }
235         else if ( rPos.Y() >= pData->mnHeight-pData->mnBottomBorder )
236         {
237             if ( rPos.X() < nSizeWidth )
238                 return BorderWindowHitTest::BottomLeft;
239             else if ( rPos.X() >= pData->mnWidth-nSizeWidth )
240                 return BorderWindowHitTest::BottomRight;
241             else
242                 return BorderWindowHitTest::Bottom;
243         }
244     }
245 
246     return BorderWindowHitTest::NONE;
247 }
248 
ImplMouseMove(ImplBorderFrameData * pData,const MouseEvent & rMEvt)249 void ImplBorderWindowView::ImplMouseMove( ImplBorderFrameData* pData, const MouseEvent& rMEvt )
250 {
251     DrawButtonFlags oldCloseState = pData->mnCloseState;
252     DrawButtonFlags oldMenuState = pData->mnMenuState;
253     pData->mnCloseState &= ~DrawButtonFlags::Highlight;
254     pData->mnMenuState &= ~DrawButtonFlags::Highlight;
255 
256     Point aMousePos = rMEvt.GetPosPixel();
257     BorderWindowHitTest nHitTest = ImplHitTest( pData, aMousePos );
258     PointerStyle ePtrStyle = PointerStyle::Arrow;
259     if ( nHitTest & BorderWindowHitTest::Left )
260         ePtrStyle = PointerStyle::WindowWSize;
261     else if ( nHitTest & BorderWindowHitTest::Right )
262         ePtrStyle = PointerStyle::WindowESize;
263     else if ( nHitTest & BorderWindowHitTest::Top )
264         ePtrStyle = PointerStyle::WindowNSize;
265     else if ( nHitTest & BorderWindowHitTest::Bottom )
266         ePtrStyle = PointerStyle::WindowSSize;
267     else if ( nHitTest & BorderWindowHitTest::TopLeft )
268         ePtrStyle = PointerStyle::WindowNWSize;
269     else if ( nHitTest & BorderWindowHitTest::BottomRight )
270         ePtrStyle = PointerStyle::WindowSESize;
271     else if ( nHitTest & BorderWindowHitTest::TopRight )
272         ePtrStyle = PointerStyle::WindowNESize;
273     else if ( nHitTest & BorderWindowHitTest::BottomLeft )
274         ePtrStyle = PointerStyle::WindowSWSize;
275     else if ( nHitTest & BorderWindowHitTest::Close )
276         pData->mnCloseState |= DrawButtonFlags::Highlight;
277     else if ( nHitTest & BorderWindowHitTest::Menu )
278         pData->mnMenuState |= DrawButtonFlags::Highlight;
279     else if ( nHitTest & BorderWindowHitTest::Title &&
280               pData->mnTitleType == BorderWindowTitleType::Tearoff && !rMEvt.IsLeaveWindow() )
281         ePtrStyle = PointerStyle::Move;
282     pData->mpBorderWindow->SetPointer( ePtrStyle );
283 
284     if( pData->mnCloseState != oldCloseState )
285         pData->mpBorderWindow->Invalidate( pData->maCloseRect );
286     if( pData->mnMenuState != oldMenuState )
287         pData->mpBorderWindow->Invalidate( pData->maMenuRect );
288 }
289 
ImplRequestHelp(ImplBorderFrameData const * pData,const Point & rPos,tools::Rectangle & rHelpRect)290 OUString ImplBorderWindowView::ImplRequestHelp( ImplBorderFrameData const * pData,
291                                               const Point& rPos,
292                                               tools::Rectangle& rHelpRect )
293 {
294     const char* pHelpId = nullptr;
295     OUString aHelpStr;
296     BorderWindowHitTest nHitTest = ImplHitTest( pData, rPos );
297     if ( nHitTest != BorderWindowHitTest::NONE )
298     {
299         if ( nHitTest & BorderWindowHitTest::Close )
300         {
301             pHelpId     = SV_HELPTEXT_CLOSE;
302             rHelpRect   = pData->maCloseRect;
303         }
304         else if ( nHitTest & BorderWindowHitTest::Roll )
305         {
306             if ( pData->mpBorderWindow->mbRollUp )
307                 pHelpId = SV_HELPTEXT_ROLLDOWN;
308             else
309                 pHelpId = SV_HELPTEXT_ROLLUP;
310             rHelpRect   = pData->maRollRect;
311         }
312         else if ( nHitTest & BorderWindowHitTest::Dock )
313         {
314             pHelpId     = SV_HELPTEXT_MAXIMIZE;
315             rHelpRect   = pData->maDockRect;
316         }
317         else if ( nHitTest & BorderWindowHitTest::Hide )
318         {
319             pHelpId     = SV_HELPTEXT_MINIMIZE;
320             rHelpRect   = pData->maHideRect;
321         }
322         else if ( nHitTest & BorderWindowHitTest::Help )
323         {
324             pHelpId     = SV_HELPTEXT_HELP;
325             rHelpRect   = pData->maHelpRect;
326         }
327         else if ( nHitTest & BorderWindowHitTest::Title )
328         {
329             if( !pData->maTitleRect.IsEmpty() )
330             {
331                 // tooltip only if title truncated
332                 if( pData->mbTitleClipped )
333                 {
334                     rHelpRect   = pData->maTitleRect;
335                     // no help id, use window title as help string
336                     aHelpStr    = pData->mpBorderWindow->GetText();
337                 }
338             }
339         }
340     }
341 
342     if (pHelpId)
343         aHelpStr = VclResId(pHelpId);
344 
345     return aHelpStr;
346 }
347 
ImplCalcTitleWidth(const ImplBorderFrameData * pData)348 long ImplBorderWindowView::ImplCalcTitleWidth( const ImplBorderFrameData* pData )
349 {
350     // title is not visible therefore no width
351     if ( !pData->mnTitleHeight )
352         return 0;
353 
354     ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
355     long nTitleWidth = pBorderWindow->GetTextWidth( pBorderWindow->GetText() )+6;
356     nTitleWidth += pData->maCloseRect.GetWidth();
357     nTitleWidth += pData->maRollRect.GetWidth();
358     nTitleWidth += pData->maDockRect.GetWidth();
359     nTitleWidth += pData->maMenuRect.GetWidth();
360     nTitleWidth += pData->maHideRect.GetWidth();
361     nTitleWidth += pData->maHelpRect.GetWidth();
362     nTitleWidth += pData->mnLeftBorder+pData->mnRightBorder;
363     return nTitleWidth;
364 }
365 
366 
ImplNoBorderWindowView()367 ImplNoBorderWindowView::ImplNoBorderWindowView()
368 {
369 }
370 
Init(OutputDevice *,long,long)371 void ImplNoBorderWindowView::Init( OutputDevice*, long, long )
372 {
373 }
374 
GetBorder(sal_Int32 & rLeftBorder,sal_Int32 & rTopBorder,sal_Int32 & rRightBorder,sal_Int32 & rBottomBorder) const375 void ImplNoBorderWindowView::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
376                                         sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
377 {
378     rLeftBorder     = 0;
379     rTopBorder      = 0;
380     rRightBorder    = 0;
381     rBottomBorder   = 0;
382 }
383 
CalcTitleWidth() const384 long ImplNoBorderWindowView::CalcTitleWidth() const
385 {
386     return 0;
387 }
388 
DrawWindow(vcl::RenderContext &,const Point *)389 void ImplNoBorderWindowView::DrawWindow(vcl::RenderContext&, const Point*)
390 {
391 }
392 
ImplSmallBorderWindowView(ImplBorderWindow * pBorderWindow)393 ImplSmallBorderWindowView::ImplSmallBorderWindowView( ImplBorderWindow* pBorderWindow )
394     : mpBorderWindow(pBorderWindow)
395     , mpOutDev(nullptr)
396     , mnWidth(0)
397     , mnHeight(0)
398     , mnLeftBorder(0)
399     , mnTopBorder(0)
400     , mnRightBorder(0)
401     , mnBottomBorder(0)
402     , mbNWFBorder(false)
403 {
404 }
405 
Init(OutputDevice * pDev,long nWidth,long nHeight)406 void ImplSmallBorderWindowView::Init( OutputDevice* pDev, long nWidth, long nHeight )
407 {
408     mpOutDev    = pDev;
409     mnWidth     = nWidth;
410     mnHeight    = nHeight;
411     mbNWFBorder = false;
412 
413     vcl::Window *pWin = nullptr, *pCtrl = nullptr;
414     if (mpOutDev->GetOutDevType() == OUTDEV_WINDOW)
415         pWin = static_cast<vcl::Window*>(mpOutDev.get());
416 
417     if (pWin)
418         pCtrl = mpBorderWindow->GetWindow(GetWindowType::Client);
419 
420     long nOrigLeftBorder = mnLeftBorder;
421     long nOrigTopBorder = mnTopBorder;
422     long nOrigRightBorder = mnRightBorder;
423     long nOrigBottomBorder = mnBottomBorder;
424 
425     WindowBorderStyle nBorderStyle = mpBorderWindow->GetBorderStyle();
426     if ( nBorderStyle & WindowBorderStyle::NOBORDER )
427     {
428         mnLeftBorder    = 0;
429         mnTopBorder     = 0;
430         mnRightBorder   = 0;
431         mnBottomBorder  = 0;
432     }
433     else
434     {
435         // FIXME: this is currently only on macOS, check with other
436         // platforms
437         if( ImplGetSVData()->maNWFData.mbNoFocusRects && !( nBorderStyle & WindowBorderStyle::NWF ) )
438         {
439             // for native widget drawing we must find out what
440             // control this border belongs to
441             ControlType aCtrlType = ControlType::Generic;
442             if (pCtrl)
443             {
444                 switch( pCtrl->GetType() )
445                 {
446                     case WindowType::LISTBOX:
447                         if( pCtrl->GetStyle() & WB_DROPDOWN )
448                         {
449                             aCtrlType = ControlType::Listbox;
450                             mbNWFBorder = true;
451                         }
452                         break;
453                     case WindowType::COMBOBOX:
454                         if( pCtrl->GetStyle() & WB_DROPDOWN )
455                         {
456                             aCtrlType = ControlType::Combobox;
457                             mbNWFBorder = true;
458                         }
459                         break;
460                     case WindowType::MULTILINEEDIT:
461                         aCtrlType = ControlType::MultilineEditbox;
462                         mbNWFBorder = true;
463                         break;
464                     case WindowType::EDIT:
465                     case WindowType::PATTERNFIELD:
466                     case WindowType::METRICFIELD:
467                     case WindowType::CURRENCYFIELD:
468                     case WindowType::DATEFIELD:
469                     case WindowType::TIMEFIELD:
470                     case WindowType::LONGCURRENCYFIELD:
471                     case WindowType::NUMERICFIELD:
472                     case WindowType::SPINFIELD:
473                     case WindowType::CALCINPUTLINE:
474                         mbNWFBorder = true;
475                         if (pCtrl->GetStyle() & WB_SPIN)
476                             aCtrlType = ControlType::Spinbox;
477                         else
478                             aCtrlType = ControlType::Editbox;
479                         break;
480                     default:
481                         break;
482                 }
483             }
484             if( mbNWFBorder )
485             {
486                 ImplControlValue aControlValue;
487                 Size aMinSize( mnWidth - mnLeftBorder - mnRightBorder, mnHeight - mnTopBorder - mnBottomBorder );
488                 if( aMinSize.Width() < 10 ) aMinSize.setWidth( 10 );
489                 if( aMinSize.Height() < 10 ) aMinSize.setHeight( 10 );
490                 tools::Rectangle aCtrlRegion( Point(mnLeftBorder, mnTopBorder), aMinSize );
491                 tools::Rectangle aBounds, aContent;
492                 if( pWin->GetNativeControlRegion( aCtrlType, ControlPart::Entire, aCtrlRegion,
493                                                   ControlState::ENABLED, aControlValue,
494                                                   aBounds, aContent ) )
495                 {
496                     mnLeftBorder    = aContent.Left() - aBounds.Left();
497                     mnRightBorder   = aBounds.Right() - aContent.Right();
498                     mnTopBorder     = aContent.Top() - aBounds.Top();
499                     mnBottomBorder  = aBounds.Bottom() - aContent.Bottom();
500                     if( mnWidth && mnHeight )
501                     {
502 
503                         mpBorderWindow->SetPaintTransparent( true );
504                         mpBorderWindow->SetBackground();
505                         pCtrl->SetPaintTransparent( true );
506 
507                         vcl::Window* pCompoundParent = nullptr;
508                         if( pWin->GetParent() && pWin->GetParent()->IsCompoundControl() )
509                             pCompoundParent = pWin->GetParent();
510 
511                         if( pCompoundParent )
512                             pCompoundParent->SetPaintTransparent( true );
513 
514                         if( mnWidth < aBounds.GetWidth() || mnHeight < aBounds.GetHeight() )
515                         {
516                             if( ! pCompoundParent ) // compound controls have to fix themselves
517                             {
518                                 Point aPos( mpBorderWindow->GetPosPixel() );
519                                 if( mnWidth < aBounds.GetWidth() )
520                                     aPos.AdjustX( -((aBounds.GetWidth() - mnWidth) / 2) );
521                                 if( mnHeight < aBounds.GetHeight() )
522                                     aPos.AdjustY( -((aBounds.GetHeight() - mnHeight) / 2) );
523                                 mpBorderWindow->SetPosSizePixel( aPos, aBounds.GetSize() );
524                             }
525                         }
526                     }
527                 }
528                 else
529                     mbNWFBorder = false;
530             }
531         }
532 
533         if( ! mbNWFBorder )
534         {
535             DrawFrameStyle nStyle = DrawFrameStyle::NONE;
536             DrawFrameFlags nFlags = DrawFrameFlags::NoDraw;
537             // move border outside if border was converted or if the BorderWindow is a frame window,
538             if ( mpBorderWindow->mbSmallOutBorder )
539                 nStyle = DrawFrameStyle::DoubleOut;
540             else if ( nBorderStyle & WindowBorderStyle::NWF )
541                 nStyle = DrawFrameStyle::NWF;
542             else
543                 nStyle = DrawFrameStyle::DoubleIn;
544             if ( nBorderStyle & WindowBorderStyle::MONO )
545                 nFlags |= DrawFrameFlags::Mono;
546 
547             DecorationView  aDecoView( mpOutDev );
548             tools::Rectangle       aRect( 0, 0, 10, 10 );
549             tools::Rectangle       aCalcRect = aDecoView.DrawFrame( aRect, nStyle, nFlags );
550             mnLeftBorder    = aCalcRect.Left();
551             mnTopBorder     = aCalcRect.Top();
552             mnRightBorder   = aRect.Right()-aCalcRect.Right();
553             mnBottomBorder  = aRect.Bottom()-aCalcRect.Bottom();
554         }
555     }
556 
557     if (pCtrl)
558     {
559         //fdo#57090 If the borders have changed, then trigger a queue_resize on
560         //the bordered window, which will resync its borders at that point
561         if (nOrigLeftBorder != mnLeftBorder ||
562             nOrigTopBorder != mnTopBorder ||
563             nOrigRightBorder != mnRightBorder ||
564             nOrigBottomBorder != mnBottomBorder)
565         {
566             pCtrl->queue_resize();
567         }
568     }
569 }
570 
GetBorder(sal_Int32 & rLeftBorder,sal_Int32 & rTopBorder,sal_Int32 & rRightBorder,sal_Int32 & rBottomBorder) const571 void ImplSmallBorderWindowView::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
572                                            sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
573 {
574     rLeftBorder     = mnLeftBorder;
575     rTopBorder      = mnTopBorder;
576     rRightBorder    = mnRightBorder;
577     rBottomBorder   = mnBottomBorder;
578 }
579 
CalcTitleWidth() const580 long ImplSmallBorderWindowView::CalcTitleWidth() const
581 {
582     return 0;
583 }
584 
DrawWindow(vcl::RenderContext & rRenderContext,const Point *)585 void ImplSmallBorderWindowView::DrawWindow(vcl::RenderContext& rRenderContext, const Point*)
586 {
587     WindowBorderStyle nBorderStyle = mpBorderWindow->GetBorderStyle();
588     if (nBorderStyle & WindowBorderStyle::NOBORDER)
589         return;
590 
591     bool bNativeOK = false;
592     // for native widget drawing we must find out what
593     // control this border belongs to
594     vcl::Window* pCtrl = mpBorderWindow->GetWindow(GetWindowType::Client);
595 
596     ControlType aCtrlType = ControlType::Generic;
597     ControlPart aCtrlPart = ControlPart::Entire;
598     if (pCtrl)
599     {
600         switch (pCtrl->GetType())
601         {
602             case WindowType::MULTILINEEDIT:
603                 aCtrlType = ControlType::MultilineEditbox;
604                 break;
605             case WindowType::EDIT:
606             case WindowType::PATTERNFIELD:
607             case WindowType::METRICFIELD:
608             case WindowType::CURRENCYFIELD:
609             case WindowType::DATEFIELD:
610             case WindowType::TIMEFIELD:
611             case WindowType::LONGCURRENCYFIELD:
612             case WindowType::NUMERICFIELD:
613             case WindowType::SPINFIELD:
614             case WindowType::CALCINPUTLINE:
615                 if (pCtrl->GetStyle() & WB_SPIN)
616                     aCtrlType = ControlType::Spinbox;
617                 else
618                     aCtrlType = ControlType::Editbox;
619                 break;
620 
621             case WindowType::LISTBOX:
622             case WindowType::MULTILISTBOX:
623             case WindowType::TREELISTBOX:
624                 aCtrlType = ControlType::Listbox;
625                 if (pCtrl->GetStyle() & WB_DROPDOWN)
626                     aCtrlPart = ControlPart::Entire;
627                 else
628                     aCtrlPart = ControlPart::ListboxWindow;
629                 break;
630 
631             case WindowType::LISTBOXWINDOW:
632                 aCtrlType = ControlType::Listbox;
633                 aCtrlPart = ControlPart::ListboxWindow;
634                 break;
635 
636             case WindowType::COMBOBOX:
637             case WindowType::PATTERNBOX:
638             case WindowType::NUMERICBOX:
639             case WindowType::METRICBOX:
640             case WindowType::CURRENCYBOX:
641             case WindowType::DATEBOX:
642             case WindowType::TIMEBOX:
643             case WindowType::LONGCURRENCYBOX:
644                 if (pCtrl->GetStyle() & WB_DROPDOWN)
645                 {
646                     aCtrlType = ControlType::Combobox;
647                     aCtrlPart = ControlPart::Entire;
648                 }
649                 else
650                 {
651                     aCtrlType = ControlType::Listbox;
652                     aCtrlPart = ControlPart::ListboxWindow;
653                 }
654                 break;
655 
656             default:
657                 break;
658         }
659     }
660 
661     if (aCtrlType != ControlType::Generic && pCtrl->IsNativeControlSupported(aCtrlType, aCtrlPart))
662     {
663         ImplControlValue aControlValue;
664         ControlState nState = ControlState::ENABLED;
665 
666         if (!mpBorderWindow->IsEnabled())
667             nState &= ~ControlState::ENABLED;
668         if (mpBorderWindow->HasFocus())
669             nState |= ControlState::FOCUSED;
670         else if(mbNWFBorder)
671         {
672             // FIXME: this is currently only on macOS, see if other platforms can profit
673 
674             // FIXME: for macOS focus rings all controls need to support GetNativeControlRegion
675             // for the dropdown style
676             if (pCtrl->HasFocus() || pCtrl->HasChildPathFocus())
677                 nState |= ControlState::FOCUSED;
678         }
679 
680         bool bMouseOver = false;
681         vcl::Window *pCtrlChild = pCtrl->GetWindow(GetWindowType::FirstChild);
682         while(pCtrlChild && !(bMouseOver = pCtrlChild->IsMouseOver()))
683         {
684             pCtrlChild = pCtrlChild->GetWindow(GetWindowType::Next);
685         }
686 
687         if (bMouseOver)
688             nState |= ControlState::ROLLOVER;
689 
690         Point aPoint;
691         tools::Rectangle aCtrlRegion(aPoint, Size(mnWidth, mnHeight));
692 
693         tools::Rectangle aBoundingRgn(aPoint, Size(mnWidth, mnHeight));
694         tools::Rectangle aContentRgn(aCtrlRegion);
695         if (!ImplGetSVData()->maNWFData.mbCanDrawWidgetAnySize &&
696             rRenderContext.GetNativeControlRegion(aCtrlType, aCtrlPart, aCtrlRegion,
697                                          nState, aControlValue,
698                                          aBoundingRgn, aContentRgn))
699         {
700             aCtrlRegion=aContentRgn;
701         }
702 
703         bNativeOK = rRenderContext.DrawNativeControl(aCtrlType, aCtrlPart, aCtrlRegion, nState, aControlValue, OUString());
704 
705         // if the native theme draws the spinbuttons in one call, make sure the proper settings
706         // are passed, this might force a redraw though... (TODO: improve)
707         if ((aCtrlType == ControlType::Spinbox) && !pCtrl->IsNativeControlSupported(ControlType::Spinbox, ControlPart::ButtonUp))
708         {
709             Edit* pEdit = static_cast<Edit*>(pCtrl)->GetSubEdit();
710             if (pEdit && !pEdit->SupportsDoubleBuffering())
711                 pCtrl->Paint(*pCtrl, tools::Rectangle());  // make sure the buttons are also drawn as they might overwrite the border
712         }
713     }
714 
715     if (bNativeOK)
716         return;
717 
718     DrawFrameStyle nStyle = DrawFrameStyle::NONE;
719     DrawFrameFlags nFlags = DrawFrameFlags::NONE;
720     // move border outside if border was converted or if the border window is a frame window,
721     if (mpBorderWindow->mbSmallOutBorder)
722         nStyle = DrawFrameStyle::DoubleOut;
723     else if (nBorderStyle & WindowBorderStyle::NWF)
724         nStyle = DrawFrameStyle::NWF;
725     else
726         nStyle = DrawFrameStyle::DoubleIn;
727     if (nBorderStyle & WindowBorderStyle::MONO)
728         nFlags |= DrawFrameFlags::Mono;
729     if (nBorderStyle & WindowBorderStyle::MENU)
730         nFlags |= DrawFrameFlags::Menu;
731     // tell DrawFrame that we're drawing a window border of a frame window to avoid round corners
732     if (mpBorderWindow == mpBorderWindow->ImplGetFrameWindow())
733         nFlags |= DrawFrameFlags::WindowBorder;
734 
735     DecorationView aDecoView(&rRenderContext);
736     tools::Rectangle aInRect(Point(), Size(mnWidth, mnHeight));
737     aDecoView.DrawFrame(aInRect, nStyle, nFlags);
738 }
739 
740 
ImplStdBorderWindowView(ImplBorderWindow * pBorderWindow)741 ImplStdBorderWindowView::ImplStdBorderWindowView( ImplBorderWindow* pBorderWindow )
742 {
743     maFrameData.mpBorderWindow  = pBorderWindow;
744     maFrameData.mbDragFull      = false;
745     maFrameData.mnHitTest       = BorderWindowHitTest::NONE;
746     maFrameData.mnCloseState    = DrawButtonFlags::NONE;
747     maFrameData.mnRollState     = DrawButtonFlags::NONE;
748     maFrameData.mnDockState     = DrawButtonFlags::NONE;
749     maFrameData.mnMenuState     = DrawButtonFlags::NONE;
750     maFrameData.mnHideState     = DrawButtonFlags::NONE;
751     maFrameData.mnHelpState     = DrawButtonFlags::NONE;
752     maFrameData.mbTitleClipped  = false;
753 }
754 
~ImplStdBorderWindowView()755 ImplStdBorderWindowView::~ImplStdBorderWindowView()
756 {
757 }
758 
MouseMove(const MouseEvent & rMEvt)759 bool ImplStdBorderWindowView::MouseMove( const MouseEvent& rMEvt )
760 {
761     ImplMouseMove( &maFrameData, rMEvt );
762     return true;
763 }
764 
MouseButtonDown(const MouseEvent & rMEvt)765 bool ImplStdBorderWindowView::MouseButtonDown( const MouseEvent& rMEvt )
766 {
767     ImplBorderWindow* pBorderWindow = maFrameData.mpBorderWindow;
768 
769     if ( rMEvt.IsLeft() || rMEvt.IsRight() )
770     {
771         maFrameData.maMouseOff = rMEvt.GetPosPixel();
772         maFrameData.mnHitTest = ImplHitTest( &maFrameData, maFrameData.maMouseOff );
773         if ( maFrameData.mnHitTest != BorderWindowHitTest::NONE )
774         {
775             DragFullOptions nDragFullTest = DragFullOptions::NONE;
776             bool bTracking = true;
777             bool bHitTest = true;
778 
779             if ( maFrameData.mnHitTest & BorderWindowHitTest::Close )
780             {
781                 maFrameData.mnCloseState |= DrawButtonFlags::Pressed;
782                 pBorderWindow->InvalidateBorder();
783             }
784             else if ( maFrameData.mnHitTest & BorderWindowHitTest::Roll )
785             {
786                 maFrameData.mnRollState |= DrawButtonFlags::Pressed;
787                 pBorderWindow->InvalidateBorder();
788             }
789             else if ( maFrameData.mnHitTest & BorderWindowHitTest::Dock )
790             {
791                 maFrameData.mnDockState |= DrawButtonFlags::Pressed;
792                 pBorderWindow->InvalidateBorder();
793             }
794             else if ( maFrameData.mnHitTest & BorderWindowHitTest::Menu )
795             {
796                 maFrameData.mnMenuState |= DrawButtonFlags::Pressed;
797                 pBorderWindow->InvalidateBorder();
798 
799                 // call handler already on mouse down
800                 if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
801                 {
802                     SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow());
803                     pClientWindow->TitleButtonClick( TitleButton::Menu );
804                 }
805             }
806             else if ( maFrameData.mnHitTest & BorderWindowHitTest::Hide )
807             {
808                 maFrameData.mnHideState |= DrawButtonFlags::Pressed;
809                 pBorderWindow->InvalidateBorder();
810             }
811             else if ( maFrameData.mnHitTest & BorderWindowHitTest::Help )
812             {
813                 maFrameData.mnHelpState |= DrawButtonFlags::Pressed;
814                 pBorderWindow->InvalidateBorder();
815             }
816             else
817             {
818                 if ( rMEvt.GetClicks() == 1 )
819                 {
820                     Point aPos  = pBorderWindow->GetPosPixel();
821                     Size  aSize = pBorderWindow->GetOutputSizePixel();
822                     maFrameData.mnTrackX      = aPos.X();
823                     maFrameData.mnTrackY      = aPos.Y();
824                     maFrameData.mnTrackWidth  = aSize.Width();
825                     maFrameData.mnTrackHeight = aSize.Height();
826 
827                     if (maFrameData.mnHitTest & BorderWindowHitTest::Title)
828                         nDragFullTest = DragFullOptions::WindowMove;
829                     else
830                         nDragFullTest = DragFullOptions::WindowSize;
831                 }
832                 else
833                 {
834                     bTracking = false;
835 
836                     if ( (maFrameData.mnHitTest & BorderWindowHitTest::Title) &&
837                          ((rMEvt.GetClicks() % 2) == 0) )
838                     {
839                         maFrameData.mnHitTest = BorderWindowHitTest::NONE;
840                         bHitTest = false;
841 
842                         if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
843                         {
844                             SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow());
845                             // always perform docking on double click, no button required
846                             pClientWindow->TitleButtonClick( TitleButton::Docking );
847                         }
848                     }
849                 }
850             }
851 
852             if ( bTracking )
853             {
854                 maFrameData.mbDragFull = false;
855                 if ( nDragFullTest != DragFullOptions::NONE )
856                     maFrameData.mbDragFull = true;   // always fulldrag for proper docking, ignore system settings
857                 pBorderWindow->StartTracking();
858             }
859             else if ( bHitTest )
860                 maFrameData.mnHitTest = BorderWindowHitTest::NONE;
861         }
862     }
863 
864     return true;
865 }
866 
Tracking(const TrackingEvent & rTEvt)867 bool ImplStdBorderWindowView::Tracking( const TrackingEvent& rTEvt )
868 {
869     ImplBorderWindow* pBorderWindow = maFrameData.mpBorderWindow;
870 
871     if ( rTEvt.IsTrackingEnded() )
872     {
873         BorderWindowHitTest nHitTest = maFrameData.mnHitTest;
874         maFrameData.mnHitTest = BorderWindowHitTest::NONE;
875 
876         if ( nHitTest & BorderWindowHitTest::Close )
877         {
878             if ( maFrameData.mnCloseState & DrawButtonFlags::Pressed )
879             {
880                 maFrameData.mnCloseState &= ~DrawButtonFlags::Pressed;
881                 pBorderWindow->InvalidateBorder();
882 
883                 // do not call a Click-Handler when aborting
884                 if ( !rTEvt.IsTrackingCanceled() )
885                 {
886                     // dispatch to correct window type (why is Close() not virtual ??? )
887                     // TODO: make Close() virtual
888                     VclPtr<vcl::Window> pWin = pBorderWindow->ImplGetClientWindow()->ImplGetWindow();
889                     SystemWindow  *pSysWin  = dynamic_cast<SystemWindow* >(pWin.get());
890                     DockingWindow *pDockWin = dynamic_cast<DockingWindow*>(pWin.get());
891                     if ( pSysWin )
892                         pSysWin->Close();
893                     else if ( pDockWin )
894                         pDockWin->Close();
895                 }
896             }
897         }
898         else if ( nHitTest & BorderWindowHitTest::Roll )
899         {
900             if ( maFrameData.mnRollState & DrawButtonFlags::Pressed )
901             {
902                 maFrameData.mnRollState &= ~DrawButtonFlags::Pressed;
903                 pBorderWindow->InvalidateBorder();
904 
905                 // do not call a Click-Handler when aborting
906                 if ( !rTEvt.IsTrackingCanceled() )
907                 {
908                     if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
909                     {
910                         SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow());
911                         if ( pClientWindow->IsRollUp() )
912                             pClientWindow->RollDown();
913                         else
914                             pClientWindow->RollUp();
915                     }
916                 }
917             }
918         }
919         else if ( nHitTest & BorderWindowHitTest::Dock )
920         {
921             if ( maFrameData.mnDockState & DrawButtonFlags::Pressed )
922             {
923                 maFrameData.mnDockState &= ~DrawButtonFlags::Pressed;
924                 pBorderWindow->InvalidateBorder();
925 
926                 // do not call a Click-Handler when aborting
927                 if ( !rTEvt.IsTrackingCanceled() )
928                 {
929                     if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
930                     {
931                         SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow());
932                         pClientWindow->TitleButtonClick( TitleButton::Docking );
933                     }
934                 }
935             }
936         }
937         else if ( nHitTest & BorderWindowHitTest::Menu )
938         {
939             if ( maFrameData.mnMenuState & DrawButtonFlags::Pressed )
940             {
941                 maFrameData.mnMenuState &= ~DrawButtonFlags::Pressed;
942                 pBorderWindow->InvalidateBorder();
943 
944                 // handler already called on mouse down
945             }
946         }
947         else if ( nHitTest & BorderWindowHitTest::Hide )
948         {
949             if ( maFrameData.mnHideState & DrawButtonFlags::Pressed )
950             {
951                 maFrameData.mnHideState &= ~DrawButtonFlags::Pressed;
952                 pBorderWindow->InvalidateBorder();
953 
954                 // do not call a Click-Handler when aborting
955                 if ( !rTEvt.IsTrackingCanceled() )
956                 {
957                     if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
958                     {
959                         SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow());
960                         pClientWindow->TitleButtonClick( TitleButton::Hide );
961                     }
962                 }
963             }
964         }
965         else if ( nHitTest & BorderWindowHitTest::Help )
966         {
967             if ( maFrameData.mnHelpState & DrawButtonFlags::Pressed )
968             {
969                 maFrameData.mnHelpState &= ~DrawButtonFlags::Pressed;
970                 pBorderWindow->InvalidateBorder();
971             }
972         }
973         else
974         {
975             if ( maFrameData.mbDragFull )
976             {
977                 // restore old state when aborting
978                 if ( rTEvt.IsTrackingCanceled() )
979                     pBorderWindow->SetPosSizePixel( Point( maFrameData.mnTrackX, maFrameData.mnTrackY ), Size( maFrameData.mnTrackWidth, maFrameData.mnTrackHeight ) );
980             }
981             else
982             {
983                 pBorderWindow->HideTracking();
984                 if ( !rTEvt.IsTrackingCanceled() )
985                     pBorderWindow->SetPosSizePixel( Point( maFrameData.mnTrackX, maFrameData.mnTrackY ), Size( maFrameData.mnTrackWidth, maFrameData.mnTrackHeight ) );
986             }
987 
988             if ( !rTEvt.IsTrackingCanceled() )
989             {
990                 if ( pBorderWindow->ImplGetClientWindow()->ImplIsFloatingWindow() )
991                 {
992                     if ( static_cast<FloatingWindow*>(pBorderWindow->ImplGetClientWindow())->IsInPopupMode() )
993                         static_cast<FloatingWindow*>(pBorderWindow->ImplGetClientWindow())->EndPopupMode( FloatWinPopupEndFlags::TearOff );
994                 }
995             }
996         }
997     }
998     else if ( !rTEvt.GetMouseEvent().IsSynthetic() )
999     {
1000         Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
1001 
1002         if ( maFrameData.mnHitTest & BorderWindowHitTest::Close )
1003         {
1004             if ( maFrameData.maCloseRect.IsInside( aMousePos ) )
1005             {
1006                 if ( !(maFrameData.mnCloseState & DrawButtonFlags::Pressed) )
1007                 {
1008                     maFrameData.mnCloseState |= DrawButtonFlags::Pressed;
1009                     pBorderWindow->InvalidateBorder();
1010                 }
1011             }
1012             else
1013             {
1014                 if ( maFrameData.mnCloseState & DrawButtonFlags::Pressed )
1015                 {
1016                     maFrameData.mnCloseState &= ~DrawButtonFlags::Pressed;
1017                     pBorderWindow->InvalidateBorder();
1018                 }
1019             }
1020         }
1021         else if ( maFrameData.mnHitTest & BorderWindowHitTest::Roll )
1022         {
1023             if ( maFrameData.maRollRect.IsInside( aMousePos ) )
1024             {
1025                 if ( !(maFrameData.mnRollState & DrawButtonFlags::Pressed) )
1026                 {
1027                     maFrameData.mnRollState |= DrawButtonFlags::Pressed;
1028                     pBorderWindow->InvalidateBorder();
1029                 }
1030             }
1031             else
1032             {
1033                 if ( maFrameData.mnRollState & DrawButtonFlags::Pressed )
1034                 {
1035                     maFrameData.mnRollState &= ~DrawButtonFlags::Pressed;
1036                     pBorderWindow->InvalidateBorder();
1037                 }
1038             }
1039         }
1040         else if ( maFrameData.mnHitTest & BorderWindowHitTest::Dock )
1041         {
1042             if ( maFrameData.maDockRect.IsInside( aMousePos ) )
1043             {
1044                 if ( !(maFrameData.mnDockState & DrawButtonFlags::Pressed) )
1045                 {
1046                     maFrameData.mnDockState |= DrawButtonFlags::Pressed;
1047                     pBorderWindow->InvalidateBorder();
1048                 }
1049             }
1050             else
1051             {
1052                 if ( maFrameData.mnDockState & DrawButtonFlags::Pressed )
1053                 {
1054                     maFrameData.mnDockState &= ~DrawButtonFlags::Pressed;
1055                     pBorderWindow->InvalidateBorder();
1056                 }
1057             }
1058         }
1059         else if ( maFrameData.mnHitTest & BorderWindowHitTest::Menu )
1060         {
1061             if ( maFrameData.maMenuRect.IsInside( aMousePos ) )
1062             {
1063                 if ( !(maFrameData.mnMenuState & DrawButtonFlags::Pressed) )
1064                 {
1065                     maFrameData.mnMenuState |= DrawButtonFlags::Pressed;
1066                     pBorderWindow->InvalidateBorder();
1067                 }
1068             }
1069             else
1070             {
1071                 if ( maFrameData.mnMenuState & DrawButtonFlags::Pressed )
1072                 {
1073                     maFrameData.mnMenuState &= ~DrawButtonFlags::Pressed;
1074                     pBorderWindow->InvalidateBorder();
1075                 }
1076             }
1077         }
1078         else if ( maFrameData.mnHitTest & BorderWindowHitTest::Hide )
1079         {
1080             if ( maFrameData.maHideRect.IsInside( aMousePos ) )
1081             {
1082                 if ( !(maFrameData.mnHideState & DrawButtonFlags::Pressed) )
1083                 {
1084                     maFrameData.mnHideState |= DrawButtonFlags::Pressed;
1085                     pBorderWindow->InvalidateBorder();
1086                 }
1087             }
1088             else
1089             {
1090                 if ( maFrameData.mnHideState & DrawButtonFlags::Pressed )
1091                 {
1092                     maFrameData.mnHideState &= ~DrawButtonFlags::Pressed;
1093                     pBorderWindow->InvalidateBorder();
1094                 }
1095             }
1096         }
1097         else if ( maFrameData.mnHitTest & BorderWindowHitTest::Help )
1098         {
1099             if ( maFrameData.maHelpRect.IsInside( aMousePos ) )
1100             {
1101                 if ( !(maFrameData.mnHelpState & DrawButtonFlags::Pressed) )
1102                 {
1103                     maFrameData.mnHelpState |= DrawButtonFlags::Pressed;
1104                     pBorderWindow->InvalidateBorder();
1105                 }
1106             }
1107             else
1108             {
1109                 if ( maFrameData.mnHelpState & DrawButtonFlags::Pressed )
1110                 {
1111                     maFrameData.mnHelpState &= ~DrawButtonFlags::Pressed;
1112                     pBorderWindow->InvalidateBorder();
1113                 }
1114             }
1115         }
1116         else
1117         {
1118             aMousePos.AdjustX( -(maFrameData.maMouseOff.X()) );
1119             aMousePos.AdjustY( -(maFrameData.maMouseOff.Y()) );
1120 
1121             if ( maFrameData.mnHitTest & BorderWindowHitTest::Title )
1122             {
1123                 maFrameData.mpBorderWindow->SetPointer( PointerStyle::Move );
1124 
1125                 Point aPos = pBorderWindow->GetPosPixel();
1126                 aPos.AdjustX(aMousePos.X() );
1127                 aPos.AdjustY(aMousePos.Y() );
1128                 if ( maFrameData.mbDragFull )
1129                 {
1130                     pBorderWindow->SetPosPixel( aPos );
1131                     pBorderWindow->ImplUpdateAll();
1132                     pBorderWindow->ImplGetFrameWindow()->ImplUpdateAll();
1133                 }
1134                 else
1135                 {
1136                     maFrameData.mnTrackX = aPos.X();
1137                     maFrameData.mnTrackY = aPos.Y();
1138                     pBorderWindow->ShowTracking( tools::Rectangle( pBorderWindow->ScreenToOutputPixel( aPos ), pBorderWindow->GetOutputSizePixel() ), ShowTrackFlags::Big );
1139                 }
1140             }
1141             else
1142             {
1143                 Point       aOldPos         = pBorderWindow->GetPosPixel();
1144                 Size        aSize           = pBorderWindow->GetSizePixel();
1145                 tools::Rectangle   aNewRect( aOldPos, aSize );
1146                 long        nOldWidth       = aSize.Width();
1147                 long        nOldHeight      = aSize.Height();
1148                 long        nBorderWidth    = maFrameData.mnLeftBorder+maFrameData.mnRightBorder;
1149                 long        nBorderHeight   = maFrameData.mnTopBorder+maFrameData.mnBottomBorder;
1150                 long        nMinWidth       = pBorderWindow->mnMinWidth+nBorderWidth;
1151                 long        nMinHeight      = pBorderWindow->mnMinHeight+nBorderHeight;
1152                 long        nMinWidth2      = nBorderWidth;
1153                 long        nMaxWidth       = pBorderWindow->mnMaxWidth+nBorderWidth;
1154                 long        nMaxHeight      = pBorderWindow->mnMaxHeight+nBorderHeight;
1155 
1156                 if ( maFrameData.mnTitleHeight )
1157                 {
1158                     nMinWidth2 += 4;
1159 
1160                     if ( pBorderWindow->GetStyle() & WB_CLOSEABLE )
1161                         nMinWidth2 += maFrameData.maCloseRect.GetWidth();
1162                 }
1163                 if ( nMinWidth2 > nMinWidth )
1164                     nMinWidth = nMinWidth2;
1165                 if ( maFrameData.mnHitTest & (BorderWindowHitTest::Left | BorderWindowHitTest::TopLeft | BorderWindowHitTest::BottomLeft) )
1166                 {
1167                     aNewRect.AdjustLeft(aMousePos.X() );
1168                     if ( aNewRect.GetWidth() < nMinWidth )
1169                         aNewRect.SetLeft( aNewRect.Right()-nMinWidth+1 );
1170                     else if ( aNewRect.GetWidth() > nMaxWidth )
1171                         aNewRect.SetLeft( aNewRect.Right()-nMaxWidth+1 );
1172                 }
1173                 else if ( maFrameData.mnHitTest & (BorderWindowHitTest::Right | BorderWindowHitTest::TopRight | BorderWindowHitTest::BottomRight) )
1174                 {
1175                     aNewRect.AdjustRight(aMousePos.X() );
1176                     if ( aNewRect.GetWidth() < nMinWidth )
1177                         aNewRect.SetRight( aNewRect.Left()+nMinWidth+1 );
1178                     else if ( aNewRect.GetWidth() > nMaxWidth )
1179                         aNewRect.SetRight( aNewRect.Left()+nMaxWidth+1 );
1180                 }
1181                 if ( maFrameData.mnHitTest & (BorderWindowHitTest::Top | BorderWindowHitTest::TopLeft | BorderWindowHitTest::TopRight) )
1182                 {
1183                     aNewRect.AdjustTop(aMousePos.Y() );
1184                     if ( aNewRect.GetHeight() < nMinHeight )
1185                         aNewRect.SetTop( aNewRect.Bottom()-nMinHeight+1 );
1186                     else if ( aNewRect.GetHeight() > nMaxHeight )
1187                         aNewRect.SetTop( aNewRect.Bottom()-nMaxHeight+1 );
1188                 }
1189                 else if ( maFrameData.mnHitTest & (BorderWindowHitTest::Bottom | BorderWindowHitTest::BottomLeft | BorderWindowHitTest::BottomRight) )
1190                 {
1191                     aNewRect.AdjustBottom(aMousePos.Y() );
1192                     if ( aNewRect.GetHeight() < nMinHeight )
1193                         aNewRect.SetBottom( aNewRect.Top()+nMinHeight+1 );
1194                     else if ( aNewRect.GetHeight() > nMaxHeight )
1195                         aNewRect.SetBottom( aNewRect.Top()+nMaxHeight+1 );
1196                 }
1197 
1198                 // call Resizing-Handler for SystemWindows
1199                 if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
1200                 {
1201                     // adjust size for Resizing-call
1202                     aSize = aNewRect.GetSize();
1203                     aSize.AdjustWidth( -nBorderWidth );
1204                     aSize.AdjustHeight( -nBorderHeight );
1205                     static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow())->Resizing( aSize );
1206                     aSize.AdjustWidth(nBorderWidth );
1207                     aSize.AdjustHeight(nBorderHeight );
1208                     if ( aSize.Width() < nMinWidth )
1209                         aSize.setWidth( nMinWidth );
1210                     if ( aSize.Height() < nMinHeight )
1211                         aSize.setHeight( nMinHeight );
1212                     if ( aSize.Width() > nMaxWidth )
1213                         aSize.setWidth( nMaxWidth );
1214                     if ( aSize.Height() > nMaxHeight )
1215                         aSize.setHeight( nMaxHeight );
1216                     if ( maFrameData.mnHitTest & (BorderWindowHitTest::Left | BorderWindowHitTest::TopLeft | BorderWindowHitTest::BottomLeft) )
1217                         aNewRect.SetLeft( aNewRect.Right()-aSize.Width()+1 );
1218                     else
1219                         aNewRect.SetRight( aNewRect.Left()+aSize.Width()-1 );
1220                     if ( maFrameData.mnHitTest & (BorderWindowHitTest::Top | BorderWindowHitTest::TopLeft | BorderWindowHitTest::TopRight) )
1221                         aNewRect.SetTop( aNewRect.Bottom()-aSize.Height()+1 );
1222                     else
1223                         aNewRect.SetBottom( aNewRect.Top()+aSize.Height()-1 );
1224                 }
1225 
1226                 if ( maFrameData.mbDragFull )
1227                 {
1228                     // no move (only resize) if position did not change
1229                     if( aOldPos != aNewRect.TopLeft() )
1230                         pBorderWindow->setPosSizePixel( aNewRect.Left(), aNewRect.Top(),
1231                                                     aNewRect.GetWidth(), aNewRect.GetHeight() );
1232                     else
1233                         pBorderWindow->setPosSizePixel( aNewRect.Left(), aNewRect.Top(),
1234                                                     aNewRect.GetWidth(), aNewRect.GetHeight(), PosSizeFlags::Size );
1235 
1236                     pBorderWindow->ImplUpdateAll();
1237                     pBorderWindow->ImplGetFrameWindow()->ImplUpdateAll();
1238                     if ( maFrameData.mnHitTest & (BorderWindowHitTest::Right | BorderWindowHitTest::TopRight | BorderWindowHitTest::BottomRight) )
1239                         maFrameData.maMouseOff.AdjustX(aNewRect.GetWidth()-nOldWidth );
1240                     if ( maFrameData.mnHitTest & (BorderWindowHitTest::Bottom | BorderWindowHitTest::BottomLeft | BorderWindowHitTest::BottomRight) )
1241                         maFrameData.maMouseOff.AdjustY(aNewRect.GetHeight()-nOldHeight );
1242                 }
1243                 else
1244                 {
1245                     maFrameData.mnTrackX        = aNewRect.Left();
1246                     maFrameData.mnTrackY        = aNewRect.Top();
1247                     maFrameData.mnTrackWidth    = aNewRect.GetWidth();
1248                     maFrameData.mnTrackHeight   = aNewRect.GetHeight();
1249                     pBorderWindow->ShowTracking( tools::Rectangle( pBorderWindow->ScreenToOutputPixel( aNewRect.TopLeft() ), aNewRect.GetSize() ), ShowTrackFlags::Big );
1250                 }
1251             }
1252         }
1253     }
1254 
1255     return true;
1256 }
1257 
RequestHelp(const Point & rPos,tools::Rectangle & rHelpRect)1258 OUString ImplStdBorderWindowView::RequestHelp( const Point& rPos, tools::Rectangle& rHelpRect )
1259 {
1260     return ImplRequestHelp( &maFrameData, rPos, rHelpRect );
1261 }
1262 
GetMenuRect() const1263 tools::Rectangle ImplStdBorderWindowView::GetMenuRect() const
1264 {
1265     return maFrameData.maMenuRect;
1266 }
1267 
Init(OutputDevice * pDev,long nWidth,long nHeight)1268 void ImplStdBorderWindowView::Init( OutputDevice* pDev, long nWidth, long nHeight )
1269 {
1270     ImplBorderFrameData*    pData = &maFrameData;
1271     ImplBorderWindow*       pBorderWindow = maFrameData.mpBorderWindow;
1272     const StyleSettings&    rStyleSettings = pDev->GetSettings().GetStyleSettings();
1273     DecorationView          aDecoView( pDev );
1274     tools::Rectangle               aRect( 0, 0, 10, 10 );
1275     tools::Rectangle               aCalcRect = aDecoView.DrawFrame( aRect, DrawFrameStyle::DoubleOut, DrawFrameFlags::NoDraw );
1276 
1277     pData->mpOutDev         = pDev;
1278     pData->mnWidth          = nWidth;
1279     pData->mnHeight         = nHeight;
1280 
1281     pData->mnTitleType      = pBorderWindow->mnTitleType;
1282 
1283     if ( !(pBorderWindow->GetStyle() & (WB_MOVEABLE | WB_POPUP)) || (pData->mnTitleType == BorderWindowTitleType::NONE) )
1284         pData->mnBorderSize = 0;
1285     else if ( pData->mnTitleType == BorderWindowTitleType::Tearoff )
1286         pData->mnBorderSize = 0;
1287     else
1288         pData->mnBorderSize = StyleSettings::GetBorderSize();
1289     pData->mnLeftBorder     = aCalcRect.Left();
1290     pData->mnTopBorder      = aCalcRect.Top();
1291     pData->mnRightBorder    = aRect.Right()-aCalcRect.Right();
1292     pData->mnBottomBorder   = aRect.Bottom()-aCalcRect.Bottom();
1293     pData->mnLeftBorder    += pData->mnBorderSize;
1294     pData->mnTopBorder     += pData->mnBorderSize;
1295     pData->mnRightBorder   += pData->mnBorderSize;
1296     pData->mnBottomBorder  += pData->mnBorderSize;
1297     pData->mnNoTitleTop     = pData->mnTopBorder;
1298 
1299     ImplInitTitle(&maFrameData);
1300     if (pData->mnTitleHeight)
1301     {
1302         // to improve symbol display force a minimum title height
1303         if (pData->mnTitleType != BorderWindowTitleType::Tearoff &&
1304             pData->mnTitleHeight < MIN_CAPTION_HEIGHT)
1305             pData->mnTitleHeight = MIN_CAPTION_HEIGHT;
1306 
1307         // set a proper background for drawing
1308         // highlighted buttons in the title
1309         pBorderWindow->SetBackground( rStyleSettings.GetFaceColor() );
1310 
1311         pData->maTitleRect.SetLeft( pData->mnLeftBorder );
1312         pData->maTitleRect.SetRight( nWidth-pData->mnRightBorder-1 );
1313         pData->maTitleRect.SetTop( pData->mnTopBorder );
1314         pData->maTitleRect.SetBottom( pData->maTitleRect.Top()+pData->mnTitleHeight-1 );
1315 
1316         if ( pData->mnTitleType & (BorderWindowTitleType::Normal | BorderWindowTitleType::Small) )
1317         {
1318             long nRight         = pData->maTitleRect.Right() - 3;
1319             long const nItemTop = pData->maTitleRect.Top() + 2;
1320             long const nItemBottom = pData->maTitleRect.Bottom() - 2;
1321 
1322             auto addSquareOnRight = [&nRight, nItemTop, nItemBottom](
1323                 tools::Rectangle & rect, long gap)
1324             {
1325                 rect.SetTop( nItemTop );
1326                 rect.SetBottom( nItemBottom );
1327                 rect.SetRight( nRight );
1328                 rect.SetLeft( rect.Right() - rect.GetHeight() + 1 );
1329                 nRight -= rect.GetWidth() + gap;
1330             };
1331 
1332             if ( pBorderWindow->GetStyle() & WB_CLOSEABLE )
1333             {
1334                 addSquareOnRight(pData->maCloseRect, 3);
1335             }
1336 
1337             if ( pBorderWindow->mbMenuBtn )
1338             {
1339                 addSquareOnRight(pData->maMenuRect, 0);
1340             }
1341 
1342             if ( pBorderWindow->mbDockBtn )
1343             {
1344                 addSquareOnRight(pData->maDockRect, 0);
1345             }
1346 
1347             if ( pBorderWindow->mbHideBtn )
1348             {
1349                 addSquareOnRight(pData->maHideRect, 0);
1350             }
1351 
1352             if ( pBorderWindow->GetStyle() & WB_ROLLABLE )
1353             {
1354                 addSquareOnRight(pData->maRollRect, 0);
1355             }
1356         }
1357         else
1358         {
1359             pData->maCloseRect.SetEmpty();
1360             pData->maDockRect.SetEmpty();
1361             pData->maMenuRect.SetEmpty();
1362             pData->maHideRect.SetEmpty();
1363             pData->maRollRect.SetEmpty();
1364             pData->maHelpRect.SetEmpty();
1365         }
1366 
1367         pData->mnTopBorder  += pData->mnTitleHeight;
1368     }
1369     else
1370     {
1371         pData->maTitleRect.SetEmpty();
1372         pData->maCloseRect.SetEmpty();
1373         pData->maDockRect.SetEmpty();
1374         pData->maMenuRect.SetEmpty();
1375         pData->maHideRect.SetEmpty();
1376         pData->maRollRect.SetEmpty();
1377         pData->maHelpRect.SetEmpty();
1378     }
1379 }
1380 
GetBorder(sal_Int32 & rLeftBorder,sal_Int32 & rTopBorder,sal_Int32 & rRightBorder,sal_Int32 & rBottomBorder) const1381 void ImplStdBorderWindowView::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
1382                                          sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
1383 {
1384     rLeftBorder     = maFrameData.mnLeftBorder;
1385     rTopBorder      = maFrameData.mnTopBorder;
1386     rRightBorder    = maFrameData.mnRightBorder;
1387     rBottomBorder   = maFrameData.mnBottomBorder;
1388 }
1389 
CalcTitleWidth() const1390 long ImplStdBorderWindowView::CalcTitleWidth() const
1391 {
1392     return ImplCalcTitleWidth( &maFrameData );
1393 }
1394 
DrawWindow(vcl::RenderContext & rRenderContext,const Point * pOffset)1395 void ImplStdBorderWindowView::DrawWindow(vcl::RenderContext& rRenderContext, const Point* pOffset)
1396 {
1397     ImplBorderFrameData* pData = &maFrameData;
1398     ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
1399     Point aTmpPoint = pOffset ? *pOffset : Point();
1400     tools::Rectangle aInRect( aTmpPoint, Size( pData->mnWidth, pData->mnHeight ) );
1401     const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1402     DecorationView aDecoView(&rRenderContext);
1403     Color aFaceColor(rStyleSettings.GetFaceColor());
1404     Color aFrameColor(aFaceColor);
1405 
1406     aFrameColor.DecreaseContrast(sal_uInt8(0.5 * 255));
1407 
1408     // Draw Frame
1409     vcl::Region oldClipRgn(rRenderContext.GetClipRegion());
1410 
1411     // for popups, don't draw part of the frame
1412     if (!(pData->mnTitleType & (BorderWindowTitleType::Normal | BorderWindowTitleType::Small)))
1413     {
1414         FloatingWindow* pWin = dynamic_cast<FloatingWindow*>(pData->mpBorderWindow->GetWindow(GetWindowType::Client));
1415         if (pWin)
1416         {
1417             vcl::Region aClipRgn(aInRect);
1418             tools::Rectangle aItemClipRect(pWin->ImplGetItemEdgeClipRect());
1419             if (!aItemClipRect.IsEmpty())
1420             {
1421                 aItemClipRect.SetPos(pData->mpBorderWindow->AbsoluteScreenToOutputPixel(aItemClipRect.TopLeft()));
1422                 aClipRgn.Exclude(aItemClipRect);
1423                 rRenderContext.SetClipRegion(aClipRgn);
1424             }
1425         }
1426     }
1427 
1428     // single line frame
1429     rRenderContext.SetLineColor(aFrameColor);
1430     rRenderContext.SetFillColor();
1431     rRenderContext.DrawRect(aInRect);
1432     aInRect.AdjustLeft( 1 );
1433     aInRect.AdjustRight( -1 );
1434     aInRect.AdjustTop( 1 );
1435     aInRect.AdjustBottom( -1 );
1436 
1437     // restore
1438     if (!(pData->mnTitleType & (BorderWindowTitleType::Normal | BorderWindowTitleType::Small)))
1439         rRenderContext.SetClipRegion(oldClipRgn);
1440 
1441     // Draw Border
1442     rRenderContext.SetLineColor();
1443     long nBorderSize = pData->mnBorderSize;
1444     if (nBorderSize)
1445     {
1446         rRenderContext.SetFillColor(rStyleSettings.GetFaceColor());
1447         rRenderContext.DrawRect(tools::Rectangle(Point(aInRect.Left(), aInRect.Top()),
1448                                  Size(aInRect.GetWidth(), nBorderSize)));
1449         rRenderContext.DrawRect(tools::Rectangle(Point(aInRect.Left(), aInRect.Top() + nBorderSize),
1450                                  Size(nBorderSize, aInRect.GetHeight() - nBorderSize)));
1451         rRenderContext.DrawRect(tools::Rectangle(Point(aInRect.Left(), aInRect.Bottom() - nBorderSize + 1),
1452                                  Size(aInRect.GetWidth(), nBorderSize)));
1453         rRenderContext.DrawRect(tools::Rectangle(Point(aInRect.Right()-nBorderSize + 1, aInRect.Top() + nBorderSize),
1454                                  Size(nBorderSize, aInRect.GetHeight() - nBorderSize)));
1455     }
1456 
1457     // Draw Title
1458     if (!pData->maTitleRect.IsEmpty())
1459     {
1460         aInRect = pData->maTitleRect;
1461 
1462         // use no gradient anymore, just a static titlecolor
1463         if (pData->mnTitleType == BorderWindowTitleType::Tearoff)
1464             rRenderContext.SetFillColor(rStyleSettings.GetFaceGradientColor());
1465         else if (pData->mnTitleType == BorderWindowTitleType::Popup)
1466             rRenderContext.SetFillColor(aFaceColor);
1467         else
1468             rRenderContext.SetFillColor(aFrameColor);
1469 
1470         rRenderContext.SetTextColor(rStyleSettings.GetButtonTextColor());
1471         tools::Rectangle aTitleRect(pData->maTitleRect);
1472         if(pOffset)
1473             aTitleRect.Move(pOffset->X(), pOffset->Y());
1474         rRenderContext.DrawRect(aTitleRect);
1475 
1476         if (pData->mnTitleType != BorderWindowTitleType::Tearoff)
1477         {
1478             aInRect.AdjustLeft(2 );
1479             aInRect.AdjustRight( -2 );
1480 
1481             if (!pData->maHelpRect.IsEmpty())
1482                 aInRect.SetRight( pData->maHelpRect.Left() - 2 );
1483             else if (!pData->maRollRect.IsEmpty())
1484                 aInRect.SetRight( pData->maRollRect.Left() - 2 );
1485             else if (!pData->maHideRect.IsEmpty())
1486                 aInRect.SetRight( pData->maHideRect.Left() - 2 );
1487             else if (!pData->maDockRect.IsEmpty())
1488                 aInRect.SetRight( pData->maDockRect.Left() - 2 );
1489             else if (!pData->maMenuRect.IsEmpty())
1490                 aInRect.SetRight( pData->maMenuRect.Left() - 2 );
1491             else if (!pData->maCloseRect.IsEmpty())
1492                 aInRect.SetRight( pData->maCloseRect.Left() - 2 );
1493 
1494             if (pOffset)
1495                 aInRect.Move(pOffset->X(), pOffset->Y());
1496 
1497             DrawTextFlags nTextStyle = DrawTextFlags::Left | DrawTextFlags::VCenter | DrawTextFlags::EndEllipsis | DrawTextFlags::Clip;
1498 
1499             // must show tooltip ?
1500             TextRectInfo aInfo;
1501             rRenderContext.GetTextRect(aInRect, pBorderWindow->GetText(), nTextStyle, &aInfo);
1502             pData->mbTitleClipped = aInfo.IsEllipses();
1503 
1504             rRenderContext.DrawText(aInRect, pBorderWindow->GetText(), nTextStyle);
1505         }
1506         else
1507         {
1508             ToolBox::ImplDrawGrip(rRenderContext, aTitleRect, ToolBox::ImplGetDragWidth(rRenderContext, false),
1509                                   WindowAlign::Left, false);
1510         }
1511     }
1512 
1513     if (!pData->maCloseRect.IsEmpty())
1514     {
1515         tools::Rectangle aSymbolRect(pData->maCloseRect);
1516         if (pOffset)
1517             aSymbolRect.Move(pOffset->X(), pOffset->Y());
1518         ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::CLOSE, pData->mnCloseState);
1519     }
1520     if (!pData->maDockRect.IsEmpty())
1521     {
1522         tools::Rectangle aSymbolRect(pData->maDockRect);
1523         if (pOffset)
1524             aSymbolRect.Move(pOffset->X(), pOffset->Y());
1525         ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::DOCK, pData->mnDockState);
1526     }
1527     if (!pData->maMenuRect.IsEmpty())
1528     {
1529         tools::Rectangle aSymbolRect(pData->maMenuRect);
1530         if (pOffset)
1531             aSymbolRect.Move(pOffset->X(), pOffset->Y());
1532         ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::MENU, pData->mnMenuState);
1533     }
1534     if (!pData->maHideRect.IsEmpty())
1535     {
1536         tools::Rectangle aSymbolRect(pData->maHideRect);
1537         if (pOffset)
1538             aSymbolRect.Move(pOffset->X(), pOffset->Y());
1539         ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::HIDE, pData->mnHideState);
1540     }
1541     if (!pData->maRollRect.IsEmpty())
1542     {
1543         SymbolType eType;
1544         if (pBorderWindow->mbRollUp)
1545             eType = SymbolType::ROLLDOWN;
1546         else
1547             eType = SymbolType::ROLLUP;
1548         tools::Rectangle aSymbolRect(pData->maRollRect);
1549         if (pOffset)
1550             aSymbolRect.Move(pOffset->X(), pOffset->Y());
1551         ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, eType, pData->mnRollState);
1552     }
1553 
1554     if (!pData->maHelpRect.IsEmpty())
1555     {
1556         tools::Rectangle aSymbolRect(pData->maHelpRect);
1557         if (pOffset)
1558             aSymbolRect.Move(pOffset->X(), pOffset->Y());
1559         ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::HELP, pData->mnHelpState);
1560     }
1561 }
1562 
ImplInit(vcl::Window * pParent,WinBits nStyle,BorderWindowStyle nTypeStyle,SystemParentData * pSystemParentData)1563 void ImplBorderWindow::ImplInit( vcl::Window* pParent,
1564                                  WinBits nStyle, BorderWindowStyle nTypeStyle,
1565                                  SystemParentData* pSystemParentData
1566                                  )
1567 {
1568     // remove all unwanted WindowBits
1569     WinBits nOrgStyle = nStyle;
1570     WinBits nTestStyle = (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_CLOSEABLE | WB_STANDALONE | WB_DIALOGCONTROL | WB_NODIALOGCONTROL | WB_SYSTEMFLOATWIN | WB_INTROWIN | WB_DEFAULTWIN | WB_TOOLTIPWIN | WB_NOSHADOW | WB_OWNERDRAWDECORATION | WB_SYSTEMCHILDWINDOW  | WB_POPUP);
1571     if ( nTypeStyle & BorderWindowStyle::App )
1572         nTestStyle |= WB_APP;
1573     nStyle &= nTestStyle;
1574 
1575     mpWindowImpl->mbBorderWin       = true;
1576     mbSmallOutBorder    = false;
1577     if ( nTypeStyle & BorderWindowStyle::Frame )
1578     {
1579         if( nStyle & WB_SYSTEMCHILDWINDOW )
1580         {
1581             mpWindowImpl->mbOverlapWin  = true;
1582             mpWindowImpl->mbFrame       = true;
1583             mbFrameBorder               = false;
1584         }
1585         else if( nStyle & (WB_OWNERDRAWDECORATION | WB_POPUP) )
1586         {
1587             mpWindowImpl->mbOverlapWin  = true;
1588             mpWindowImpl->mbFrame       = true;
1589             mbFrameBorder   = (nOrgStyle & WB_NOBORDER) == 0;
1590         }
1591         else
1592         {
1593             mpWindowImpl->mbOverlapWin  = true;
1594             mpWindowImpl->mbFrame       = true;
1595             mbFrameBorder   = false;
1596             // closeable windows may have a border as well, eg. system floating windows without caption
1597             if ( (nOrgStyle & (WB_BORDER | WB_NOBORDER | WB_MOVEABLE | WB_SIZEABLE/* | WB_CLOSEABLE*/)) == WB_BORDER )
1598                 mbSmallOutBorder = true;
1599         }
1600     }
1601     else if ( nTypeStyle & BorderWindowStyle::Overlap )
1602     {
1603         mpWindowImpl->mbOverlapWin  = true;
1604         mbFrameBorder   = true;
1605     }
1606     else
1607         mbFrameBorder   = false;
1608 
1609     if ( nTypeStyle & BorderWindowStyle::Float )
1610         mbFloatWindow = true;
1611     else
1612         mbFloatWindow = false;
1613 
1614     Window::ImplInit( pParent, nStyle, pSystemParentData );
1615     SetBackground();
1616     SetTextFillColor();
1617 
1618     mpMenuBarWindow = nullptr;
1619     mnMinWidth      = 0;
1620     mnMinHeight     = 0;
1621     mnMaxWidth      = SHRT_MAX;
1622     mnMaxHeight     = SHRT_MAX;
1623     mnOrgMenuHeight = 0;
1624     mbRollUp        = false;
1625     mbMenuHide      = false;
1626     mbDockBtn       = false;
1627     mbMenuBtn       = false;
1628     mbHideBtn       = false;
1629     mbDisplayActive = IsActive();
1630 
1631     if ( nTypeStyle & BorderWindowStyle::Float )
1632         mnTitleType = BorderWindowTitleType::Small;
1633     else
1634         mnTitleType = BorderWindowTitleType::Normal;
1635     mnBorderStyle   = WindowBorderStyle::NORMAL;
1636     InitView();
1637 }
1638 
ImplBorderWindow(vcl::Window * pParent,SystemParentData * pSystemParentData,WinBits nStyle,BorderWindowStyle nTypeStyle)1639 ImplBorderWindow::ImplBorderWindow( vcl::Window* pParent,
1640                                     SystemParentData* pSystemParentData,
1641                                     WinBits nStyle, BorderWindowStyle nTypeStyle
1642                                     ) : Window( WindowType::BORDERWINDOW )
1643 {
1644     ImplInit( pParent, nStyle, nTypeStyle, pSystemParentData );
1645 }
1646 
ImplBorderWindow(vcl::Window * pParent,WinBits nStyle,BorderWindowStyle nTypeStyle)1647 ImplBorderWindow::ImplBorderWindow( vcl::Window* pParent, WinBits nStyle ,
1648                                     BorderWindowStyle nTypeStyle ) :
1649     Window( WindowType::BORDERWINDOW )
1650 {
1651     ImplInit( pParent, nStyle, nTypeStyle, nullptr );
1652 }
1653 
~ImplBorderWindow()1654 ImplBorderWindow::~ImplBorderWindow()
1655 {
1656     disposeOnce();
1657 }
1658 
dispose()1659 void ImplBorderWindow::dispose()
1660 {
1661     mpBorderView.reset();
1662     mpMenuBarWindow.clear();
1663     mpNotebookBar.disposeAndClear();
1664     vcl::Window::dispose();
1665 }
1666 
MouseMove(const MouseEvent & rMEvt)1667 void ImplBorderWindow::MouseMove( const MouseEvent& rMEvt )
1668 {
1669     if (mpBorderView)
1670         mpBorderView->MouseMove( rMEvt );
1671 }
1672 
MouseButtonDown(const MouseEvent & rMEvt)1673 void ImplBorderWindow::MouseButtonDown( const MouseEvent& rMEvt )
1674 {
1675     if (mpBorderView)
1676         mpBorderView->MouseButtonDown( rMEvt );
1677 }
1678 
Tracking(const TrackingEvent & rTEvt)1679 void ImplBorderWindow::Tracking( const TrackingEvent& rTEvt )
1680 {
1681     if (mpBorderView)
1682         mpBorderView->Tracking( rTEvt );
1683 }
1684 
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle &)1685 void ImplBorderWindow::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& )
1686 {
1687     if (mpBorderView)
1688         mpBorderView->DrawWindow(rRenderContext);
1689 }
1690 
Draw(OutputDevice * pOutDev,const Point & rPos)1691 void ImplBorderWindow::Draw( OutputDevice* pOutDev, const Point& rPos )
1692 {
1693     if (mpBorderView)
1694         mpBorderView->DrawWindow(*pOutDev, &rPos);
1695 }
1696 
Activate()1697 void ImplBorderWindow::Activate()
1698 {
1699     SetDisplayActive( true );
1700     Window::Activate();
1701 }
1702 
Deactivate()1703 void ImplBorderWindow::Deactivate()
1704 {
1705     // remove active windows from the ruler, also ignore the Deactivate
1706     // if a menu becomes active
1707     if ( GetActivateMode() != ActivateModeFlags::NONE && !ImplGetSVData()->maWinData.mbNoDeactivate )
1708         SetDisplayActive( false );
1709     Window::Deactivate();
1710 }
1711 
RequestHelp(const HelpEvent & rHEvt)1712 void ImplBorderWindow::RequestHelp( const HelpEvent& rHEvt )
1713 {
1714     // no keyboard help for border window
1715     if ( rHEvt.GetMode() & (HelpEventMode::BALLOON | HelpEventMode::QUICK) && !rHEvt.KeyboardActivated() )
1716     {
1717         Point       aMousePosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
1718         tools::Rectangle   aHelpRect;
1719         OUString    aHelpStr( mpBorderView->RequestHelp( aMousePosPixel, aHelpRect ) );
1720 
1721         // retrieve rectangle
1722         if ( !aHelpStr.isEmpty() )
1723         {
1724             aHelpRect.SetPos( OutputToScreenPixel( aHelpRect.TopLeft() ) );
1725             if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
1726                 Help::ShowBalloon( this, aHelpRect.Center(), aHelpRect, aHelpStr );
1727             else
1728                 Help::ShowQuickHelp( this, aHelpRect, aHelpStr );
1729             return;
1730         }
1731     }
1732 
1733     Window::RequestHelp( rHEvt );
1734 }
1735 
Resize()1736 void ImplBorderWindow::Resize()
1737 {
1738     Size aSize = GetOutputSizePixel();
1739 
1740     if ( !mbRollUp )
1741     {
1742         vcl::Window* pClientWindow = ImplGetClientWindow();
1743 
1744         sal_Int32 nLeftBorder;
1745         sal_Int32 nTopBorder;
1746         sal_Int32 nRightBorder;
1747         sal_Int32 nBottomBorder;
1748         mpBorderView->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
1749 
1750         if (mpMenuBarWindow)
1751         {
1752             long nMenuHeight = mpMenuBarWindow->GetSizePixel().Height();
1753             if ( mbMenuHide )
1754             {
1755                 if ( nMenuHeight )
1756                     mnOrgMenuHeight = nMenuHeight;
1757                 nMenuHeight = 0;
1758             }
1759             else
1760             {
1761                 if ( !nMenuHeight )
1762                     nMenuHeight = mnOrgMenuHeight;
1763             }
1764             mpMenuBarWindow->setPosSizePixel(
1765                     nLeftBorder, nTopBorder,
1766                     aSize.Width()-nLeftBorder-nRightBorder,
1767                     nMenuHeight);
1768 
1769             // shift the notebookbar down accordingly
1770             nTopBorder += nMenuHeight;
1771         }
1772 
1773         if (mpNotebookBar)
1774         {
1775             long nNotebookBarHeight = mpNotebookBar->GetSizePixel().Height();
1776 
1777             const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1778             const BitmapEx& aPersona = rStyleSettings.GetPersonaHeader();
1779             // since size of notebookbar changes, to make common persona for menubar
1780             // and notebookbar persona should be set again with changed coordinates
1781             if (!aPersona.IsEmpty())
1782                 {
1783                     Wallpaper aWallpaper(aPersona);
1784                     aWallpaper.SetStyle(WallpaperStyle::TopRight);
1785                     aWallpaper.SetRect(tools::Rectangle(Point(0, -nTopBorder),
1786                            Size(aSize.Width() - nLeftBorder - nRightBorder,
1787                                 nNotebookBarHeight + nTopBorder)));
1788                     mpNotebookBar->SetBackground(aWallpaper);
1789                 }
1790 
1791             mpNotebookBar->setPosSizePixel(
1792                     nLeftBorder, nTopBorder,
1793                     aSize.Width() - nLeftBorder - nRightBorder,
1794                     nNotebookBarHeight);
1795         }
1796 
1797         GetBorder( pClientWindow->mpWindowImpl->mnLeftBorder, pClientWindow->mpWindowImpl->mnTopBorder,
1798                    pClientWindow->mpWindowImpl->mnRightBorder, pClientWindow->mpWindowImpl->mnBottomBorder );
1799         pClientWindow->ImplPosSizeWindow( pClientWindow->mpWindowImpl->mnLeftBorder,
1800                                           pClientWindow->mpWindowImpl->mnTopBorder,
1801                                           aSize.Width()-pClientWindow->mpWindowImpl->mnLeftBorder-pClientWindow->mpWindowImpl->mnRightBorder,
1802                                           aSize.Height()-pClientWindow->mpWindowImpl->mnTopBorder-pClientWindow->mpWindowImpl->mnBottomBorder,
1803                                           PosSizeFlags::X | PosSizeFlags::Y |
1804                                           PosSizeFlags::Width | PosSizeFlags::Height );
1805     }
1806 
1807     // UpdateView
1808     mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1809     InvalidateBorder();
1810 
1811     Window::Resize();
1812 }
1813 
StateChanged(StateChangedType nType)1814 void ImplBorderWindow::StateChanged( StateChangedType nType )
1815 {
1816     if ( (nType == StateChangedType::Text) ||
1817          (nType == StateChangedType::Data) )
1818     {
1819         if (IsReallyVisible() && mbFrameBorder)
1820             InvalidateBorder();
1821     }
1822 
1823     Window::StateChanged( nType );
1824 }
1825 
DataChanged(const DataChangedEvent & rDCEvt)1826 void ImplBorderWindow::DataChanged( const DataChangedEvent& rDCEvt )
1827 {
1828     if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
1829          (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
1830          ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1831           (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
1832     {
1833         if ( !mpWindowImpl->mbFrame || (GetStyle() & (WB_OWNERDRAWDECORATION | WB_POPUP)) )
1834             UpdateView( true, ImplGetWindow()->GetOutputSizePixel() );
1835     }
1836 
1837     Window::DataChanged( rDCEvt );
1838 }
1839 
InitView()1840 void ImplBorderWindow::InitView()
1841 {
1842     if ( mbSmallOutBorder )
1843         mpBorderView.reset(new ImplSmallBorderWindowView( this ));
1844     else if ( mpWindowImpl->mbFrame )
1845     {
1846         if( mbFrameBorder )
1847             mpBorderView.reset(new ImplStdBorderWindowView( this ));
1848         else
1849             mpBorderView.reset(new ImplNoBorderWindowView);
1850     }
1851     else if ( !mbFrameBorder )
1852         mpBorderView.reset(new ImplSmallBorderWindowView( this ));
1853     else
1854         mpBorderView.reset(new ImplStdBorderWindowView( this ));
1855     Size aSize = GetOutputSizePixel();
1856     mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1857 }
1858 
UpdateView(bool bNewView,const Size & rNewOutSize)1859 void ImplBorderWindow::UpdateView( bool bNewView, const Size& rNewOutSize )
1860 {
1861     sal_Int32 nLeftBorder;
1862     sal_Int32 nTopBorder;
1863     sal_Int32 nRightBorder;
1864     sal_Int32 nBottomBorder;
1865     Size aOldSize = GetSizePixel();
1866     Size aOutputSize = rNewOutSize;
1867 
1868     if ( bNewView )
1869     {
1870         mpBorderView.reset();
1871         InitView();
1872     }
1873     else
1874     {
1875         Size aSize = aOutputSize;
1876         mpBorderView->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
1877         aSize.AdjustWidth(nLeftBorder+nRightBorder );
1878         aSize.AdjustHeight(nTopBorder+nBottomBorder );
1879         mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1880     }
1881 
1882     vcl::Window* pClientWindow = ImplGetClientWindow();
1883     if ( pClientWindow )
1884     {
1885         GetBorder( pClientWindow->mpWindowImpl->mnLeftBorder, pClientWindow->mpWindowImpl->mnTopBorder,
1886                    pClientWindow->mpWindowImpl->mnRightBorder, pClientWindow->mpWindowImpl->mnBottomBorder );
1887     }
1888     GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
1889     if ( aOldSize.Width() || aOldSize.Height() )
1890     {
1891         aOutputSize.AdjustWidth(nLeftBorder+nRightBorder );
1892         aOutputSize.AdjustHeight(nTopBorder+nBottomBorder );
1893         if ( aOutputSize == GetSizePixel() )
1894             InvalidateBorder();
1895         else
1896             SetSizePixel( aOutputSize );
1897     }
1898 }
1899 
InvalidateBorder()1900 void ImplBorderWindow::InvalidateBorder()
1901 {
1902     if ( IsReallyVisible() )
1903     {
1904         // invalidate only if we have a border
1905         sal_Int32 nLeftBorder;
1906         sal_Int32 nTopBorder;
1907         sal_Int32 nRightBorder;
1908         sal_Int32 nBottomBorder;
1909         mpBorderView->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
1910         if ( nLeftBorder || nTopBorder || nRightBorder || nBottomBorder )
1911         {
1912             tools::Rectangle   aWinRect( Point( 0, 0 ), GetOutputSizePixel() );
1913             vcl::Region      aRegion( aWinRect );
1914             aWinRect.AdjustLeft(nLeftBorder );
1915             aWinRect.AdjustTop(nTopBorder );
1916             aWinRect.AdjustRight( -nRightBorder );
1917             aWinRect.AdjustBottom( -nBottomBorder );
1918             // no output area anymore, now invalidate all
1919             if ( (aWinRect.Right() < aWinRect.Left()) ||
1920                  (aWinRect.Bottom() < aWinRect.Top()) )
1921                 Invalidate( InvalidateFlags::NoChildren );
1922             else
1923             {
1924                 aRegion.Exclude( aWinRect );
1925                 Invalidate( aRegion, InvalidateFlags::NoChildren );
1926             }
1927         }
1928     }
1929 }
1930 
SetDisplayActive(bool bActive)1931 void ImplBorderWindow::SetDisplayActive( bool bActive )
1932 {
1933     if ( mbDisplayActive != bActive )
1934     {
1935         mbDisplayActive = bActive;
1936         if ( mbFrameBorder )
1937             InvalidateBorder();
1938     }
1939 }
1940 
SetTitleType(BorderWindowTitleType nTitleType,const Size & rSize)1941 void ImplBorderWindow::SetTitleType( BorderWindowTitleType nTitleType, const Size& rSize )
1942 {
1943     mnTitleType = nTitleType;
1944     UpdateView( false, rSize );
1945 }
1946 
SetBorderStyle(WindowBorderStyle nStyle)1947 void ImplBorderWindow::SetBorderStyle( WindowBorderStyle nStyle )
1948 {
1949     if ( !mbFrameBorder && (mnBorderStyle != nStyle) )
1950     {
1951         mnBorderStyle = nStyle;
1952         UpdateView( false, ImplGetWindow()->GetOutputSizePixel() );
1953     }
1954 }
1955 
SetRollUp(bool bRollUp,const Size & rSize)1956 void ImplBorderWindow::SetRollUp( bool bRollUp, const Size& rSize )
1957 {
1958     mbRollUp = bRollUp;
1959     UpdateView( false, rSize );
1960 }
1961 
SetCloseButton()1962 void ImplBorderWindow::SetCloseButton()
1963 {
1964     SetStyle( GetStyle() | WB_CLOSEABLE );
1965     Size aSize = GetOutputSizePixel();
1966     mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1967     InvalidateBorder();
1968 }
1969 
SetDockButton(bool bDockButton)1970 void ImplBorderWindow::SetDockButton( bool bDockButton )
1971 {
1972     mbDockBtn = bDockButton;
1973     Size aSize = GetOutputSizePixel();
1974     mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1975     InvalidateBorder();
1976 }
1977 
SetHideButton(bool bHideButton)1978 void ImplBorderWindow::SetHideButton( bool bHideButton )
1979 {
1980     mbHideBtn = bHideButton;
1981     Size aSize = GetOutputSizePixel();
1982     mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1983     InvalidateBorder();
1984 }
1985 
SetMenuButton(bool bMenuButton)1986 void ImplBorderWindow::SetMenuButton( bool bMenuButton )
1987 {
1988     mbMenuBtn = bMenuButton;
1989     Size aSize = GetOutputSizePixel();
1990     mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1991     InvalidateBorder();
1992 }
1993 
UpdateMenuHeight()1994 void ImplBorderWindow::UpdateMenuHeight()
1995 {
1996     Resize();
1997 }
1998 
SetMenuBarWindow(vcl::Window * pWindow)1999 void ImplBorderWindow::SetMenuBarWindow( vcl::Window* pWindow )
2000 {
2001     mpMenuBarWindow = pWindow;
2002     UpdateMenuHeight();
2003     if ( pWindow )
2004         pWindow->Show();
2005 }
2006 
SetMenuBarMode(bool bHide)2007 void ImplBorderWindow::SetMenuBarMode( bool bHide )
2008 {
2009     mbMenuHide = bHide;
2010     UpdateMenuHeight();
2011 }
2012 
SetNotebookBar(const OUString & rUIXMLDescription,const css::uno::Reference<css::frame::XFrame> & rFrame,const NotebookBarAddonsItem & aNotebookBarAddonsItem)2013 void ImplBorderWindow::SetNotebookBar(const OUString& rUIXMLDescription,
2014                                       const css::uno::Reference<css::frame::XFrame>& rFrame,
2015                                       const NotebookBarAddonsItem& aNotebookBarAddonsItem)
2016 {
2017     if (mpNotebookBar)
2018         mpNotebookBar.disposeAndClear();
2019     mpNotebookBar = VclPtr<NotebookBar>::Create(this, "NotebookBar", rUIXMLDescription, rFrame,
2020                                                 aNotebookBarAddonsItem);
2021     Resize();
2022 }
2023 
CloseNotebookBar()2024 void ImplBorderWindow::CloseNotebookBar()
2025 {
2026     if (mpNotebookBar)
2027         mpNotebookBar.disposeAndClear();
2028     mpNotebookBar = nullptr;
2029     Resize();
2030 }
2031 
GetBorder(sal_Int32 & rLeftBorder,sal_Int32 & rTopBorder,sal_Int32 & rRightBorder,sal_Int32 & rBottomBorder) const2032 void ImplBorderWindow::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
2033                                   sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
2034 {
2035     mpBorderView->GetBorder(rLeftBorder, rTopBorder, rRightBorder, rBottomBorder);
2036 
2037     if (mpMenuBarWindow && !mbMenuHide)
2038         rTopBorder += mpMenuBarWindow->GetSizePixel().Height();
2039 
2040     if (mpNotebookBar && mpNotebookBar->IsVisible())
2041         rTopBorder += mpNotebookBar->GetSizePixel().Height();
2042 }
2043 
CalcTitleWidth() const2044 long ImplBorderWindow::CalcTitleWidth() const
2045 {
2046     return mpBorderView->CalcTitleWidth();
2047 }
2048 
GetMenuRect() const2049 tools::Rectangle ImplBorderWindow::GetMenuRect() const
2050 {
2051     return mpBorderView->GetMenuRect();
2052 }
2053 
GetOptimalSize() const2054 Size ImplBorderWindow::GetOptimalSize() const
2055 {
2056     const vcl::Window* pClientWindow = ImplGetClientWindow();
2057     if (pClientWindow)
2058         return pClientWindow->GetOptimalSize();
2059     return Size(mnMinWidth, mnMinHeight);
2060 }
2061 
queue_resize(StateChangedType eReason)2062 void ImplBorderWindow::queue_resize(StateChangedType eReason)
2063 {
2064     //if we are floating, then we don't want to inform our parent that it needs
2065     //to calculate a new layout allocation. Because while we are a child
2066     //of our parent we are not embedded into the parent so it doesn't care
2067     //about us.
2068     if (mbFloatWindow)
2069         return;
2070     vcl::Window::queue_resize(eReason);
2071 }
2072 
2073 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2074