Line data Source code
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 <config_features.h>
21 :
22 : #include <vcl/window.hxx>
23 : #include <vcl/dialog.hxx>
24 : #include <vcl/virdev.hxx>
25 : #include <vcl/cursor.hxx>
26 : #include <vcl/settings.hxx>
27 :
28 : #include <sal/types.h>
29 :
30 : #include <window.h>
31 : #include <salgdi.hxx>
32 : #include <salframe.hxx>
33 : #include <svdata.hxx>
34 :
35 : #define IMPL_PAINT_PAINT ((sal_uInt16)0x0001)
36 : #define IMPL_PAINT_PAINTALL ((sal_uInt16)0x0002)
37 : #define IMPL_PAINT_PAINTALLCHILDREN ((sal_uInt16)0x0004)
38 : #define IMPL_PAINT_PAINTCHILDREN ((sal_uInt16)0x0008)
39 : #define IMPL_PAINT_ERASE ((sal_uInt16)0x0010)
40 : #define IMPL_PAINT_CHECKRTL ((sal_uInt16)0x0020)
41 :
42 : class PaintHelper
43 : {
44 : private:
45 : VclPtr<vcl::Window> m_pWindow;
46 : VclPtr<VirtualDevice> m_pBuffer; ///< Buffer for the double-buffering
47 : vcl::Region* m_pChildRegion;
48 : Rectangle m_aSelectionRect;
49 : Rectangle m_aPaintRect;
50 : vcl::Region m_aPaintRegion;
51 : sal_uInt16 m_nPaintFlags;
52 : bool m_bPop : 1;
53 : bool m_bRestoreCursor : 1;
54 : bool m_bCreatedBuffer : 1; ///< This PaintHelper created the buffer for the double-buffering, and should dispose it when being destructed (if it is still alive by then).
55 : public:
56 : PaintHelper(vcl::Window* pWindow, const VclPtr<VirtualDevice>& rBuffer, sal_uInt16 nPaintFlags);
57 146054 : void SetPop()
58 : {
59 146054 : m_bPop = true;
60 146054 : }
61 146054 : void SetPaintRect(const Rectangle& rRect)
62 : {
63 146054 : m_aPaintRect = rRect;
64 146054 : }
65 0 : void SetSelectionRect(const Rectangle& rRect)
66 : {
67 0 : m_aSelectionRect = rRect;
68 0 : }
69 12226 : void SetRestoreCursor(bool bRestoreCursor)
70 : {
71 12226 : m_bRestoreCursor = bRestoreCursor;
72 12226 : }
73 12465 : bool GetRestoreCursor() const
74 : {
75 12465 : return m_bRestoreCursor;
76 : }
77 146054 : sal_uInt16 GetPaintFlags() const
78 : {
79 146054 : return m_nPaintFlags;
80 : }
81 146054 : vcl::Region& GetPaintRegion()
82 : {
83 146054 : return m_aPaintRegion;
84 : }
85 : void DoPaint(const vcl::Region* pRegion);
86 :
87 : /// Create m_pBuffer, and set it up to have the same settings as m_pWindow.
88 : void CreateBuffer();
89 :
90 : /// Setup m_pBuffer according to the settings of the current m_pWindow.
91 : void SetupBuffer();
92 :
93 : /// Paint the content of the buffer to the current m_pWindow.
94 : void PaintBuffer();
95 :
96 : ~PaintHelper();
97 : };
98 :
99 764034 : PaintHelper::PaintHelper(vcl::Window *pWindow, const VclPtr<VirtualDevice>& rBuffer, sal_uInt16 nPaintFlags)
100 : : m_pWindow(pWindow)
101 : , m_pBuffer(rBuffer)
102 : , m_pChildRegion(NULL)
103 : , m_nPaintFlags(nPaintFlags)
104 : , m_bPop(false)
105 : , m_bRestoreCursor(false)
106 764034 : , m_bCreatedBuffer(false)
107 : {
108 764034 : }
109 :
110 0 : void PaintHelper::CreateBuffer()
111 : {
112 : assert(!m_pBuffer);
113 :
114 0 : m_pBuffer = VclPtrInstance<VirtualDevice>();
115 0 : m_bCreatedBuffer = true;
116 :
117 0 : SetupBuffer();
118 :
119 : // update the output size now, after all the settings were copied
120 0 : m_pBuffer->SetOutputSize(m_pWindow->GetOutputSize());
121 :
122 : // we need to remember the mnOutOffX / mnOutOffY, but actually really
123 : // set it just temporarily for the subwidgets - so we are setting it here
124 : // only to remember the value & to be able to pass it to the descendants
125 : // FIXME: once everything's double-buffered, this is (hopefully) not
126 : // necessary as the m_pBuffer is always created for the main window.
127 0 : m_pBuffer->mnOutOffX = m_pWindow->GetOutOffXPixel();
128 0 : m_pBuffer->mnOutOffY = m_pWindow->GetOutOffYPixel();
129 0 : }
130 :
131 0 : void PaintHelper::SetupBuffer()
132 : {
133 : // transfer various settings
134 : // FIXME: this must disappear as we move to RenderContext only,
135 : // the painting must become state-less, so that no actual
136 : // vcl::Window setting affects this
137 0 : if (m_pWindow->IsBackground())
138 0 : m_pBuffer->SetBackground(m_pWindow->GetBackground());
139 : else
140 : SAL_WARN("vcl.doublebuffering", "the root of the double-buffering hierarchy should not have a transparent background");
141 :
142 0 : m_pBuffer->SetClipRegion(m_pWindow->GetClipRegion());
143 0 : m_pBuffer->SetFillColor(m_pWindow->GetFillColor());
144 0 : m_pBuffer->SetFont(m_pWindow->GetFont());
145 0 : m_pBuffer->SetLineColor(m_pWindow->GetLineColor());
146 0 : m_pBuffer->SetMapMode(m_pWindow->GetMapMode());
147 0 : m_pBuffer->SetRefPoint(m_pWindow->GetRefPoint());
148 0 : m_pBuffer->SetSettings(m_pWindow->GetSettings());
149 0 : m_pBuffer->SetTextColor(m_pWindow->GetTextColor());
150 0 : m_pBuffer->SetTextLineColor(m_pWindow->GetTextLineColor());
151 0 : m_pBuffer->SetOverlineColor(m_pWindow->GetOverlineColor());
152 0 : m_pBuffer->SetTextFillColor(m_pWindow->GetTextFillColor());
153 0 : m_pBuffer->SetTextAlign(m_pWindow->GetTextAlign());
154 0 : m_pBuffer->SetRasterOp(m_pWindow->GetRasterOp());
155 0 : m_pBuffer->SetLayoutMode(m_pWindow->GetLayoutMode());
156 0 : m_pBuffer->SetDigitLanguage(m_pWindow->GetDigitLanguage());
157 0 : }
158 :
159 0 : void PaintHelper::PaintBuffer()
160 : {
161 : assert(m_pBuffer);
162 : assert(m_bCreatedBuffer);
163 :
164 0 : m_pBuffer->mnOutOffX = 0;
165 0 : m_pBuffer->mnOutOffY = 0;
166 :
167 : // copy the buffer content to the actual window
168 : // export VCL_DOUBLEBUFFERING_AVOID_PAINT=1 to see where we are
169 : // painting directly instead of using Invalidate()
170 : // [ie. everything you can see was painted directly to the
171 : // window either above or in eg. an event handler]
172 0 : if (!getenv("VCL_DOUBLEBUFFERING_AVOID_PAINT"))
173 0 : m_pWindow->DrawOutDev(m_aPaintRect.TopLeft(), m_aPaintRect.GetSize(), m_aPaintRect.TopLeft(), m_aPaintRect.GetSize(), *m_pBuffer.get());
174 0 : }
175 :
176 238364 : void PaintHelper::DoPaint(const vcl::Region* pRegion)
177 : {
178 238364 : WindowImpl* pWindowImpl = m_pWindow->ImplGetWindowImpl();
179 238364 : vcl::Region* pWinChildClipRegion = m_pWindow->ImplGetWinChildClipRegion();
180 238364 : if (pWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL || m_pBuffer)
181 : {
182 152373 : pWindowImpl->maInvalidateRegion = *pWinChildClipRegion;
183 : }
184 : else
185 : {
186 85991 : if (pRegion)
187 59317 : pWindowImpl->maInvalidateRegion.Union( *pRegion );
188 :
189 85991 : if (pWindowImpl->mpWinData && pWindowImpl->mbTrackVisible)
190 : /* #98602# need to repaint all children within the
191 : * tracking rectangle, so the following invert
192 : * operation takes places without traces of the previous
193 : * one.
194 : */
195 0 : pWindowImpl->maInvalidateRegion.Union(*pWindowImpl->mpWinData->mpTrackRect);
196 :
197 85991 : if (pWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALLCHILDREN)
198 41714 : m_pChildRegion = new vcl::Region(pWindowImpl->maInvalidateRegion);
199 85991 : pWindowImpl->maInvalidateRegion.Intersect(*pWinChildClipRegion);
200 : }
201 238364 : pWindowImpl->mnPaintFlags = 0;
202 238364 : if (!pWindowImpl->maInvalidateRegion.IsEmpty())
203 : {
204 146054 : m_pWindow->BeginPaint();
205 :
206 : // double-buffering: setup the buffer if it does not exist
207 146054 : if (!m_pBuffer && m_pWindow->SupportsDoubleBuffering())
208 0 : CreateBuffer();
209 :
210 : // double-buffering: if this window does not support double-buffering,
211 : // but we are in the middle of double-buffered paint, we might be
212 : // losing information
213 146054 : if (m_pBuffer && !m_pWindow->SupportsDoubleBuffering())
214 : SAL_WARN("vcl.doublebuffering", "non-double buffered window in the double-buffered hierarchy, painting directly: " << typeid(*m_pWindow.get()).name());
215 :
216 146054 : if (m_pBuffer && m_pWindow->SupportsDoubleBuffering())
217 : {
218 : // double-buffering
219 0 : SetupBuffer();
220 0 : m_pWindow->ApplySettings(*m_pBuffer.get());
221 :
222 : // temporarily decrease the mnOutOffX/Y of the buffer for the
223 : // subwidgets (because the m_pBuffer is our base here)
224 : // FIXME: once everything's double-buffered, this is (hopefully) not
225 : // necessary as the m_pBuffer is always created for the main window.
226 0 : long nOutOffX = m_pBuffer->mnOutOffX;
227 0 : long nOutOffY = m_pBuffer->mnOutOffY;
228 0 : m_pBuffer->mnOutOffX = m_pWindow->GetOutOffXPixel() - m_pBuffer->mnOutOffX;
229 0 : m_pBuffer->mnOutOffY = m_pWindow->GetOutOffYPixel() - m_pBuffer->mnOutOffY;
230 :
231 0 : m_pWindow->PushPaintHelper(this, *m_pBuffer.get());
232 0 : m_pWindow->Paint(*m_pBuffer.get(), m_aPaintRect);
233 :
234 : // restore the mnOutOffX/Y value
235 0 : m_pBuffer->mnOutOffX = nOutOffX;
236 0 : m_pBuffer->mnOutOffY = nOutOffY;
237 : }
238 : else
239 : {
240 : // direct painting
241 146054 : m_pWindow->ApplySettings(*m_pWindow);
242 146054 : m_pWindow->PushPaintHelper(this, *m_pWindow);
243 146054 : m_pWindow->Paint(*m_pWindow, m_aPaintRect);
244 : }
245 :
246 146054 : m_pWindow->EndPaint();
247 : }
248 238364 : }
249 :
250 : namespace vcl
251 : {
252 :
253 1061 : void RenderTools::DrawSelectionBackground(vcl::RenderContext& rRenderContext, vcl::Window& rWindow,
254 : const Rectangle& rRect, sal_uInt16 nHighlight,
255 : bool bChecked, bool bDrawBorder, bool bDrawExtBorderOnly,
256 : Color* pSelectionTextColor, long nCornerRadius, Color* pPaintColor)
257 : {
258 1061 : if (rRect.IsEmpty())
259 1061 : return;
260 :
261 1061 : bool bRoundEdges = nCornerRadius > 0;
262 :
263 1061 : const StyleSettings& rStyles = rRenderContext.GetSettings().GetStyleSettings();
264 :
265 : // colors used for item highlighting
266 1061 : Color aSelectionBorderColor(pPaintColor ? *pPaintColor : rStyles.GetHighlightColor());
267 1061 : Color aSelectionFillColor(aSelectionBorderColor);
268 :
269 1061 : bool bDark = rStyles.GetFaceColor().IsDark();
270 1061 : bool bBright = ( rStyles.GetFaceColor() == Color( COL_WHITE ) );
271 :
272 1061 : int c1 = aSelectionBorderColor.GetLuminance();
273 1061 : int c2 = rWindow.GetDisplayBackground().GetColor().GetLuminance();
274 :
275 1061 : if (!bDark && !bBright && std::abs(c2 - c1) < (pPaintColor ? 40 : 75))
276 : {
277 : // constrast too low
278 : sal_uInt16 h, s, b;
279 0 : aSelectionFillColor.RGBtoHSB( h, s, b );
280 0 : if( b > 50 ) b -= 40;
281 0 : else b += 40;
282 0 : aSelectionFillColor.SetColor( Color::HSBtoRGB( h, s, b ) );
283 0 : aSelectionBorderColor = aSelectionFillColor;
284 : }
285 :
286 1061 : if (bRoundEdges)
287 : {
288 1058 : if (aSelectionBorderColor.IsDark())
289 1058 : aSelectionBorderColor.IncreaseLuminance(128);
290 : else
291 0 : aSelectionBorderColor.DecreaseLuminance(128);
292 : }
293 :
294 1061 : Rectangle aRect(rRect);
295 1061 : if (bDrawExtBorderOnly)
296 : {
297 0 : aRect.Left() -= 1;
298 0 : aRect.Top() -= 1;
299 0 : aRect.Right() += 1;
300 0 : aRect.Bottom() += 1;
301 : }
302 1061 : rRenderContext.Push(PushFlags::FILLCOLOR | PushFlags::LINECOLOR);
303 :
304 1061 : if (bDrawBorder)
305 1061 : rRenderContext.SetLineColor(bDark ? Color(COL_WHITE) : (bBright ? Color(COL_BLACK) : aSelectionBorderColor));
306 : else
307 0 : rRenderContext.SetLineColor();
308 :
309 1061 : sal_uInt16 nPercent = 0;
310 1061 : if (!nHighlight)
311 : {
312 1058 : if (bDark)
313 0 : aSelectionFillColor = COL_BLACK;
314 : else
315 1058 : nPercent = 80; // just checked (light)
316 : }
317 : else
318 : {
319 3 : if (bChecked && nHighlight == 2)
320 : {
321 0 : if (bDark)
322 0 : aSelectionFillColor = COL_LIGHTGRAY;
323 0 : else if (bBright)
324 : {
325 0 : aSelectionFillColor = COL_BLACK;
326 0 : rRenderContext.SetLineColor(COL_BLACK);
327 0 : nPercent = 0;
328 : }
329 : else
330 0 : nPercent = bRoundEdges ? 40 : 20; // selected, pressed or checked ( very dark )
331 : }
332 3 : else if (bChecked || nHighlight == 1)
333 : {
334 6 : if (bDark)
335 0 : aSelectionFillColor = COL_GRAY;
336 3 : else if (bBright)
337 : {
338 0 : aSelectionFillColor = COL_BLACK;
339 0 : rRenderContext.SetLineColor(COL_BLACK);
340 0 : nPercent = 0;
341 : }
342 : else
343 3 : nPercent = bRoundEdges ? 60 : 35; // selected, pressed or checked ( very dark )
344 : }
345 : else
346 : {
347 0 : if (bDark)
348 0 : aSelectionFillColor = COL_LIGHTGRAY;
349 0 : else if (bBright)
350 : {
351 0 : aSelectionFillColor = COL_BLACK;
352 0 : rRenderContext.SetLineColor(COL_BLACK);
353 0 : if (nHighlight == 3)
354 0 : nPercent = 80;
355 : else
356 0 : nPercent = 0;
357 : }
358 : else
359 0 : nPercent = 70; // selected ( dark )
360 : }
361 : }
362 :
363 1061 : if (bDark && bDrawExtBorderOnly)
364 : {
365 0 : rRenderContext.SetFillColor();
366 0 : if (pSelectionTextColor)
367 0 : *pSelectionTextColor = rStyles.GetHighlightTextColor();
368 : }
369 : else
370 : {
371 1061 : rRenderContext.SetFillColor(aSelectionFillColor);
372 1061 : if (pSelectionTextColor)
373 : {
374 0 : Color aTextColor = rWindow.IsControlBackground() ? rWindow.GetControlForeground() : rStyles.GetButtonTextColor();
375 0 : Color aHLTextColor = rStyles.GetHighlightTextColor();
376 0 : int nTextDiff = std::abs(aSelectionFillColor.GetLuminance() - aTextColor.GetLuminance());
377 0 : int nHLDiff = std::abs(aSelectionFillColor.GetLuminance() - aHLTextColor.GetLuminance());
378 0 : *pSelectionTextColor = (nHLDiff >= nTextDiff) ? aHLTextColor : aTextColor;
379 : }
380 : }
381 :
382 1061 : if (bDark)
383 : {
384 0 : rRenderContext.DrawRect(aRect);
385 : }
386 : else
387 : {
388 1061 : if (bRoundEdges)
389 : {
390 1058 : Polygon aPoly(aRect, nCornerRadius, nCornerRadius);
391 2116 : tools::PolyPolygon aPolyPoly(aPoly);
392 2116 : rRenderContext.DrawTransparent(aPolyPoly, nPercent);
393 : }
394 : else
395 : {
396 3 : Polygon aPoly(aRect);
397 6 : tools::PolyPolygon aPolyPoly(aPoly);
398 6 : rRenderContext.DrawTransparent(aPolyPoly, nPercent);
399 : }
400 : }
401 :
402 1061 : rRenderContext.Pop(); // LINECOLOR | FILLCOLOR
403 : }
404 :
405 146054 : void Window::PushPaintHelper(PaintHelper *pHelper, vcl::RenderContext& rRenderContext)
406 : {
407 146054 : pHelper->SetPop();
408 :
409 146054 : if ( mpWindowImpl->mpCursor )
410 12226 : pHelper->SetRestoreCursor(mpWindowImpl->mpCursor->ImplSuspend());
411 :
412 146054 : mbInitClipRegion = true;
413 146054 : mpWindowImpl->mbInPaint = true;
414 :
415 : // restore Paint-Region
416 146054 : vcl::Region &rPaintRegion = pHelper->GetPaintRegion();
417 146054 : rPaintRegion = mpWindowImpl->maInvalidateRegion;
418 146054 : Rectangle aPaintRect = rPaintRegion.GetBoundRect();
419 :
420 : // - RTL - re-mirror paint rect and region at this window
421 146054 : if (ImplIsAntiparallel())
422 : {
423 45 : rRenderContext.ReMirror(aPaintRect);
424 45 : rRenderContext.ReMirror(rPaintRegion);
425 : }
426 146054 : aPaintRect = ImplDevicePixelToLogic(aPaintRect);
427 146054 : mpWindowImpl->mpPaintRegion = &rPaintRegion;
428 146054 : mpWindowImpl->maInvalidateRegion.SetEmpty();
429 :
430 146054 : if ((pHelper->GetPaintFlags() & IMPL_PAINT_ERASE) && rRenderContext.IsBackground())
431 : {
432 92903 : if (rRenderContext.IsClipRegion())
433 : {
434 0 : vcl::Region aOldRegion = rRenderContext.GetClipRegion();
435 0 : rRenderContext.SetClipRegion();
436 0 : Erase(rRenderContext);
437 0 : rRenderContext.SetClipRegion(aOldRegion);
438 : }
439 : else
440 92903 : Erase(rRenderContext);
441 : }
442 :
443 : // #98943# trigger drawing of toolbox selection after all childern are painted
444 146054 : if (mpWindowImpl->mbDrawSelectionBackground)
445 0 : pHelper->SetSelectionRect(aPaintRect);
446 146054 : pHelper->SetPaintRect(aPaintRect);
447 146054 : }
448 :
449 146054 : void Window::PopPaintHelper(PaintHelper *pHelper)
450 : {
451 146054 : if (mpWindowImpl->mpWinData)
452 : {
453 95045 : if (mpWindowImpl->mbFocusVisible)
454 18 : ImplInvertFocus(*(mpWindowImpl->mpWinData->mpFocusRect));
455 : }
456 146054 : mpWindowImpl->mbInPaint = false;
457 146054 : mbInitClipRegion = true;
458 146054 : mpWindowImpl->mpPaintRegion = NULL;
459 146054 : if (mpWindowImpl->mpCursor)
460 12465 : mpWindowImpl->mpCursor->ImplResume(pHelper->GetRestoreCursor());
461 146054 : }
462 :
463 : } /* namespace vcl */
464 :
465 1528068 : PaintHelper::~PaintHelper()
466 : {
467 764034 : WindowImpl* pWindowImpl = m_pWindow->ImplGetWindowImpl();
468 764034 : if (m_bPop)
469 : {
470 146054 : m_pWindow->PopPaintHelper(this);
471 : }
472 :
473 764034 : if ( m_nPaintFlags & (IMPL_PAINT_PAINTALLCHILDREN | IMPL_PAINT_PAINTCHILDREN) )
474 : {
475 : // Paint from the bottom child window and frontward.
476 744899 : vcl::Window* pTempWindow = pWindowImpl->mpLastChild;
477 2608559 : while (pTempWindow)
478 : {
479 1118761 : if (pTempWindow->mpWindowImpl->mbVisible)
480 736889 : pTempWindow->ImplCallPaint(m_pBuffer, m_pChildRegion, m_nPaintFlags);
481 1118761 : pTempWindow = pTempWindow->mpWindowImpl->mpPrev;
482 : }
483 : }
484 :
485 764034 : if ( pWindowImpl->mpWinData && pWindowImpl->mbTrackVisible && (pWindowImpl->mpWinData->mnTrackFlags & SHOWTRACK_WINDOW) )
486 : /* #98602# need to invert the tracking rect AFTER
487 : * the children have painted
488 : */
489 0 : m_pWindow->InvertTracking( *(pWindowImpl->mpWinData->mpTrackRect), pWindowImpl->mpWinData->mnTrackFlags );
490 :
491 : // double-buffering: paint in case we created the buffer, the children are
492 : // already painted inside
493 764034 : if (m_bCreatedBuffer && m_pBuffer)
494 : {
495 0 : PaintBuffer();
496 0 : m_pBuffer.disposeAndClear();
497 : }
498 :
499 : // #98943# draw toolbox selection
500 764034 : if( !m_aSelectionRect.IsEmpty() )
501 0 : m_pWindow->DrawSelectionBackground( m_aSelectionRect, 3, false, true, false );
502 :
503 764034 : delete m_pChildRegion;
504 764034 : }
505 :
506 : namespace vcl {
507 :
508 783423 : void Window::ImplCallPaint(const VclPtr<VirtualDevice>& rBuffer, const vcl::Region* pRegion, sal_uInt16 nPaintFlags)
509 : {
510 : // call PrePaint. PrePaint may add to the invalidate region as well as
511 : // other parameters used below.
512 783423 : PrePaint(*this);
513 :
514 783423 : mpWindowImpl->mbPaintFrame = false;
515 :
516 783423 : if (nPaintFlags & IMPL_PAINT_PAINTALLCHILDREN)
517 226577 : mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINT | IMPL_PAINT_PAINTALLCHILDREN | (nPaintFlags & IMPL_PAINT_PAINTALL);
518 783423 : if (nPaintFlags & IMPL_PAINT_PAINTCHILDREN)
519 753367 : mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINTCHILDREN;
520 783423 : if (nPaintFlags & IMPL_PAINT_ERASE)
521 235179 : mpWindowImpl->mnPaintFlags |= IMPL_PAINT_ERASE;
522 783423 : if (nPaintFlags & IMPL_PAINT_CHECKRTL)
523 33567 : mpWindowImpl->mnPaintFlags |= IMPL_PAINT_CHECKRTL;
524 783423 : if (!mpWindowImpl->mpFirstChild)
525 474899 : mpWindowImpl->mnPaintFlags &= ~IMPL_PAINT_PAINTALLCHILDREN;
526 :
527 783423 : if (mpWindowImpl->mbPaintDisabled)
528 : {
529 19389 : if (mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL)
530 19326 : Invalidate(InvalidateFlags::NoChildren | InvalidateFlags::NoErase | InvalidateFlags::NoTransparent | InvalidateFlags::NoClipChildren);
531 63 : else if ( pRegion )
532 24 : Invalidate(*pRegion, InvalidateFlags::NoChildren | InvalidateFlags::NoErase | InvalidateFlags::NoTransparent | InvalidateFlags::NoClipChildren);
533 802812 : return;
534 : }
535 :
536 764034 : nPaintFlags = mpWindowImpl->mnPaintFlags & ~(IMPL_PAINT_PAINT);
537 :
538 764034 : PaintHelper aHelper(this, rBuffer, nPaintFlags);
539 :
540 764034 : if (mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINT)
541 238364 : aHelper.DoPaint(pRegion);
542 : else
543 525670 : mpWindowImpl->mnPaintFlags = 0;
544 :
545 764034 : PostPaint(*this);
546 : }
547 :
548 16205 : void Window::ImplCallOverlapPaint()
549 : {
550 : // emit overlapping windows first
551 16205 : vcl::Window* pTempWindow = mpWindowImpl->mpFirstOverlap;
552 32410 : while ( pTempWindow )
553 : {
554 0 : if ( pTempWindow->mpWindowImpl->mbReallyVisible )
555 0 : pTempWindow->ImplCallOverlapPaint();
556 0 : pTempWindow = pTempWindow->mpWindowImpl->mpNext;
557 : }
558 :
559 : // only then ourself
560 16205 : if ( mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTCHILDREN) )
561 : {
562 : // - RTL - notify ImplCallPaint to check for re-mirroring (CHECKRTL)
563 : // because we were called from the Sal layer
564 16082 : OutputDevice *pOutDev = GetOutDev();
565 16082 : pOutDev->BeginPaint();
566 16082 : ImplCallPaint(NULL, NULL, mpWindowImpl->mnPaintFlags /*| IMPL_PAINT_CHECKRTL */);
567 16082 : pOutDev->EndPaint();
568 : }
569 16205 : }
570 :
571 448056 : void Window::ImplPostPaint()
572 : {
573 448056 : if ( !ImplDoTiledRendering() && !mpWindowImpl->mpFrameData->maPaintIdle.IsActive() )
574 19405 : mpWindowImpl->mpFrameData->maPaintIdle.Start();
575 448056 : }
576 :
577 32480 : IMPL_LINK_NOARG_TYPED(Window, ImplHandlePaintHdl, Idle *, void)
578 : {
579 : // save paint events until layout is done
580 16240 : if (!ImplDoTiledRendering() && IsSystemWindow() && static_cast<const SystemWindow*>(this)->hasPendingLayout())
581 : {
582 0 : mpWindowImpl->mpFrameData->maPaintIdle.Start();
583 16240 : return;
584 : }
585 :
586 : // save paint events until resizing is done
587 48720 : if( !ImplDoTiledRendering() &&
588 32480 : mpWindowImpl->mbFrame && mpWindowImpl->mpFrameData->maResizeIdle.IsActive() )
589 0 : mpWindowImpl->mpFrameData->maPaintIdle.Start();
590 16240 : else if ( mpWindowImpl->mbReallyVisible )
591 16205 : ImplCallOverlapPaint();
592 : }
593 :
594 6392 : IMPL_LINK_NOARG_TYPED(Window, ImplHandleResizeTimerHdl, Idle *, void)
595 : {
596 3196 : if( mpWindowImpl->mbReallyVisible )
597 : {
598 73 : ImplCallResize();
599 73 : if( ImplDoTiledRendering() )
600 : {
601 0 : ImplHandlePaintHdl(NULL);
602 : }
603 73 : else if( mpWindowImpl->mpFrameData->maPaintIdle.IsActive() )
604 : {
605 73 : mpWindowImpl->mpFrameData->maPaintIdle.Stop();
606 73 : mpWindowImpl->mpFrameData->maPaintIdle.GetIdleHdl().Call( NULL );
607 : }
608 : }
609 3196 : }
610 :
611 448056 : void Window::ImplInvalidateFrameRegion( const vcl::Region* pRegion, InvalidateFlags nFlags )
612 : {
613 : // set PAINTCHILDREN for all parent windows till the first OverlapWindow
614 448056 : if ( !ImplIsOverlapWindow() )
615 : {
616 441940 : vcl::Window* pTempWindow = this;
617 441940 : sal_uInt16 nTranspPaint = IsPaintTransparent() ? IMPL_PAINT_PAINT : 0;
618 148001 : do
619 : {
620 571059 : pTempWindow = pTempWindow->ImplGetParent();
621 571059 : if ( pTempWindow->mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTCHILDREN )
622 423058 : break;
623 148001 : pTempWindow->mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINTCHILDREN | nTranspPaint;
624 148001 : if( ! pTempWindow->IsPaintTransparent() )
625 147921 : nTranspPaint = 0;
626 : }
627 148001 : while ( !pTempWindow->ImplIsOverlapWindow() );
628 : }
629 :
630 : // set Paint-Flags
631 448056 : mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINT;
632 448056 : if ( nFlags & InvalidateFlags::Children )
633 384450 : mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINTALLCHILDREN;
634 448056 : if ( !(nFlags & InvalidateFlags::NoErase) )
635 372268 : mpWindowImpl->mnPaintFlags |= IMPL_PAINT_ERASE;
636 448056 : if ( !pRegion )
637 255749 : mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINTALL;
638 :
639 : // if not everything has to be redrawn, add the region to it
640 448056 : if ( !(mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL) )
641 133735 : mpWindowImpl->maInvalidateRegion.Union( *pRegion );
642 :
643 : // Handle transparent windows correctly: invalidate must be done on the first opaque parent
644 902424 : if( ((IsPaintTransparent() && !(nFlags & InvalidateFlags::NoTransparent)) || (nFlags & InvalidateFlags::Transparent) )
645 902365 : && ImplGetParent() )
646 : {
647 6246 : vcl::Window *pParent = ImplGetParent();
648 12874 : while( pParent && pParent->IsPaintTransparent() )
649 382 : pParent = pParent->ImplGetParent();
650 6246 : if( pParent )
651 : {
652 : vcl::Region *pChildRegion;
653 6246 : if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL )
654 : // invalidate the whole child window region in the parent
655 1206 : pChildRegion = ImplGetWinChildClipRegion();
656 : else
657 : // invalidate the same region in the parent that has to be repainted in the child
658 5040 : pChildRegion = &mpWindowImpl->maInvalidateRegion;
659 :
660 6246 : nFlags |= InvalidateFlags::Children; // paint should also be done on all children
661 6246 : nFlags &= ~InvalidateFlags::NoErase; // parent should paint and erase to create proper background
662 6246 : pParent->ImplInvalidateFrameRegion( pChildRegion, nFlags );
663 : }
664 : }
665 448056 : ImplPostPaint();
666 448056 : }
667 :
668 7820 : void Window::ImplInvalidateOverlapFrameRegion( const vcl::Region& rRegion )
669 : {
670 7820 : vcl::Region aRegion = rRegion;
671 :
672 7820 : ImplClipBoundaries( aRegion, true, true );
673 7820 : if ( !aRegion.IsEmpty() )
674 3103 : ImplInvalidateFrameRegion( &aRegion, InvalidateFlags::Children );
675 :
676 : // now we invalidate the overlapping windows
677 7820 : vcl::Window* pTempWindow = mpWindowImpl->mpFirstOverlap;
678 15640 : while ( pTempWindow )
679 : {
680 0 : if ( pTempWindow->IsVisible() )
681 0 : pTempWindow->ImplInvalidateOverlapFrameRegion( rRegion );
682 :
683 0 : pTempWindow = pTempWindow->mpWindowImpl->mpNext;
684 7820 : }
685 7820 : }
686 :
687 107854 : void Window::ImplInvalidateParentFrameRegion( vcl::Region& rRegion )
688 : {
689 107854 : if ( mpWindowImpl->mbOverlapWin )
690 0 : mpWindowImpl->mpFrameWindow->ImplInvalidateOverlapFrameRegion( rRegion );
691 : else
692 : {
693 107854 : if( ImplGetParent() )
694 107854 : ImplGetParent()->ImplInvalidateFrameRegion( &rRegion, InvalidateFlags::Children );
695 : }
696 107854 : }
697 :
698 241671 : void Window::ImplInvalidate( const vcl::Region* pRegion, InvalidateFlags nFlags )
699 : {
700 : // reset background storage
701 241671 : if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
702 0 : ImplInvalidateAllOverlapBackgrounds();
703 :
704 : // check what has to be redrawn
705 241671 : bool bInvalidateAll = !pRegion;
706 :
707 : // take Transparent-Invalidate into account
708 241671 : vcl::Window* pOpaqueWindow = this;
709 241671 : if ( (mpWindowImpl->mbPaintTransparent && !(nFlags & InvalidateFlags::NoTransparent)) || (nFlags & InvalidateFlags::Transparent) )
710 : {
711 8753 : vcl::Window* pTempWindow = pOpaqueWindow->ImplGetParent();
712 17669 : while ( pTempWindow )
713 : {
714 8916 : if ( !pTempWindow->IsPaintTransparent() )
715 : {
716 8753 : pOpaqueWindow = pTempWindow;
717 8753 : nFlags |= InvalidateFlags::Children;
718 8753 : bInvalidateAll = false;
719 8753 : break;
720 : }
721 :
722 163 : if ( pTempWindow->ImplIsOverlapWindow() )
723 0 : break;
724 :
725 163 : pTempWindow = pTempWindow->ImplGetParent();
726 : }
727 : }
728 :
729 : // assemble region
730 241671 : InvalidateFlags nOrgFlags = nFlags;
731 241671 : if ( !(nFlags & (InvalidateFlags::Children | InvalidateFlags::NoChildren)) )
732 : {
733 160279 : if ( GetStyle() & WB_CLIPCHILDREN )
734 51427 : nFlags |= InvalidateFlags::NoChildren;
735 : else
736 108852 : nFlags |= InvalidateFlags::Children;
737 : }
738 241671 : if ( (nFlags & InvalidateFlags::NoChildren) && mpWindowImpl->mpFirstChild )
739 24396 : bInvalidateAll = false;
740 241671 : if ( bInvalidateAll )
741 164860 : ImplInvalidateFrameRegion( NULL, nFlags );
742 : else
743 : {
744 76811 : Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
745 76811 : vcl::Region aRegion( aRect );
746 76811 : if ( pRegion )
747 : {
748 : // --- RTL --- remirror region before intersecting it
749 56771 : if ( ImplIsAntiparallel() )
750 : {
751 0 : const OutputDevice *pOutDev = GetOutDev();
752 :
753 0 : vcl::Region aRgn( *pRegion );
754 0 : pOutDev->ReMirror( aRgn );
755 0 : aRegion.Intersect( aRgn );
756 : }
757 : else
758 56771 : aRegion.Intersect( *pRegion );
759 : }
760 76811 : ImplClipBoundaries( aRegion, true, true );
761 76811 : if ( nFlags & InvalidateFlags::NoChildren )
762 : {
763 46219 : nFlags &= ~InvalidateFlags::Children;
764 46219 : if ( !(nFlags & InvalidateFlags::NoClipChildren) )
765 : {
766 45825 : if ( nOrgFlags & InvalidateFlags::NoChildren )
767 930 : ImplClipAllChildren( aRegion );
768 : else
769 : {
770 44895 : if ( ImplClipChildren( aRegion ) )
771 1705 : nFlags |= InvalidateFlags::Children;
772 : }
773 : }
774 : }
775 76811 : if ( !aRegion.IsEmpty() )
776 66065 : ImplInvalidateFrameRegion( &aRegion, nFlags ); // transparency is handled here, pOpaqueWindow not required
777 : }
778 :
779 241671 : if ( nFlags & InvalidateFlags::Update )
780 0 : pOpaqueWindow->Update(); // start painting at the opaque parent
781 241671 : }
782 :
783 492 : void Window::ImplMoveInvalidateRegion( const Rectangle& rRect,
784 : long nHorzScroll, long nVertScroll,
785 : bool bChildren )
786 : {
787 492 : if ( (mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTALL)) == IMPL_PAINT_PAINT )
788 : {
789 8 : vcl::Region aTempRegion = mpWindowImpl->maInvalidateRegion;
790 8 : aTempRegion.Intersect( rRect );
791 8 : aTempRegion.Move( nHorzScroll, nVertScroll );
792 8 : mpWindowImpl->maInvalidateRegion.Union( aTempRegion );
793 : }
794 :
795 492 : if ( bChildren && (mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTCHILDREN) )
796 : {
797 31 : vcl::Window* pWindow = mpWindowImpl->mpFirstChild;
798 94 : while ( pWindow )
799 : {
800 32 : pWindow->ImplMoveInvalidateRegion( rRect, nHorzScroll, nVertScroll, true );
801 32 : pWindow = pWindow->mpWindowImpl->mpNext;
802 : }
803 : }
804 492 : }
805 :
806 460 : void Window::ImplMoveAllInvalidateRegions( const Rectangle& rRect,
807 : long nHorzScroll, long nVertScroll,
808 : bool bChildren )
809 : {
810 : // also shift Paint-Region when paints need processing
811 460 : ImplMoveInvalidateRegion( rRect, nHorzScroll, nVertScroll, bChildren );
812 : // Paint-Region should be shifted, as drawn by the parents
813 460 : if ( !ImplIsOverlapWindow() )
814 : {
815 460 : vcl::Region aPaintAllRegion;
816 460 : vcl::Window* pPaintAllWindow = this;
817 2289 : do
818 : {
819 2289 : pPaintAllWindow = pPaintAllWindow->ImplGetParent();
820 2289 : if ( pPaintAllWindow->mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALLCHILDREN )
821 : {
822 0 : if ( pPaintAllWindow->mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL )
823 : {
824 0 : aPaintAllRegion.SetEmpty();
825 0 : break;
826 : }
827 : else
828 0 : aPaintAllRegion.Union( pPaintAllWindow->mpWindowImpl->maInvalidateRegion );
829 : }
830 : }
831 2289 : while ( !pPaintAllWindow->ImplIsOverlapWindow() );
832 460 : if ( !aPaintAllRegion.IsEmpty() )
833 : {
834 0 : aPaintAllRegion.Move( nHorzScroll, nVertScroll );
835 0 : InvalidateFlags nPaintFlags = InvalidateFlags::NONE;
836 0 : if ( bChildren )
837 0 : nPaintFlags |= InvalidateFlags::Children;
838 0 : ImplInvalidateFrameRegion( &aPaintAllRegion, nPaintFlags );
839 460 : }
840 : }
841 460 : }
842 :
843 228 : void Window::ImplValidateFrameRegion( const vcl::Region* pRegion, ValidateFlags nFlags )
844 : {
845 228 : if ( !pRegion )
846 228 : mpWindowImpl->maInvalidateRegion.SetEmpty();
847 : else
848 : {
849 : // when all child windows have to be drawn we need to invalidate them before doing so
850 0 : if ( (mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALLCHILDREN) && mpWindowImpl->mpFirstChild )
851 : {
852 0 : vcl::Region aChildRegion = mpWindowImpl->maInvalidateRegion;
853 0 : if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL )
854 : {
855 0 : Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
856 0 : aChildRegion = aRect;
857 : }
858 0 : vcl::Window* pChild = mpWindowImpl->mpFirstChild;
859 0 : while ( pChild )
860 : {
861 0 : pChild->Invalidate( aChildRegion, InvalidateFlags::Children | InvalidateFlags::NoTransparent );
862 0 : pChild = pChild->mpWindowImpl->mpNext;
863 0 : }
864 : }
865 0 : if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL )
866 : {
867 0 : Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
868 0 : mpWindowImpl->maInvalidateRegion = aRect;
869 : }
870 0 : mpWindowImpl->maInvalidateRegion.Exclude( *pRegion );
871 : }
872 228 : mpWindowImpl->mnPaintFlags &= ~IMPL_PAINT_PAINTALL;
873 :
874 228 : if ( nFlags & ValidateFlags::Children )
875 : {
876 0 : vcl::Window* pChild = mpWindowImpl->mpFirstChild;
877 0 : while ( pChild )
878 : {
879 0 : pChild->ImplValidateFrameRegion( pRegion, nFlags );
880 0 : pChild = pChild->mpWindowImpl->mpNext;
881 : }
882 : }
883 228 : }
884 :
885 228 : void Window::ImplValidate( const vcl::Region* pRegion, ValidateFlags nFlags )
886 : {
887 : // assemble region
888 228 : bool bValidateAll = !pRegion;
889 228 : ValidateFlags nOrgFlags = nFlags;
890 228 : if ( !(nFlags & (ValidateFlags::Children | ValidateFlags::NoChildren)) )
891 : {
892 228 : if ( GetStyle() & WB_CLIPCHILDREN )
893 228 : nFlags |= ValidateFlags::NoChildren;
894 : else
895 0 : nFlags |= ValidateFlags::Children;
896 : }
897 228 : if ( (nFlags & ValidateFlags::NoChildren) && mpWindowImpl->mpFirstChild )
898 0 : bValidateAll = false;
899 228 : if ( bValidateAll )
900 228 : ImplValidateFrameRegion( NULL, nFlags );
901 : else
902 : {
903 0 : Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
904 0 : vcl::Region aRegion( aRect );
905 0 : if ( pRegion )
906 0 : aRegion.Intersect( *pRegion );
907 0 : ImplClipBoundaries( aRegion, true, true );
908 0 : if ( nFlags & ValidateFlags::NoChildren )
909 : {
910 0 : nFlags &= ~ValidateFlags::Children;
911 0 : if ( nOrgFlags & ValidateFlags::NoChildren )
912 0 : ImplClipAllChildren( aRegion );
913 : else
914 : {
915 0 : if ( ImplClipChildren( aRegion ) )
916 0 : nFlags |= ValidateFlags::Children;
917 : }
918 : }
919 0 : if ( !aRegion.IsEmpty() )
920 0 : ImplValidateFrameRegion( &aRegion, nFlags );
921 : }
922 228 : }
923 :
924 0 : void Window::ImplUpdateAll( bool bOverlapWindows )
925 : {
926 0 : if ( !mpWindowImpl->mbReallyVisible )
927 0 : return;
928 :
929 0 : bool bFlush = false;
930 0 : if ( mpWindowImpl->mpFrameWindow->mpWindowImpl->mbPaintFrame )
931 : {
932 0 : Point aPoint( 0, 0 );
933 0 : vcl::Region aRegion( Rectangle( aPoint, Size( mnOutWidth, mnOutHeight ) ) );
934 0 : ImplInvalidateOverlapFrameRegion( aRegion );
935 0 : if ( mpWindowImpl->mbFrame || (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame) )
936 0 : bFlush = true;
937 : }
938 :
939 : // an update changes the OverlapWindow, such that for later paints
940 : // not too much has to be drawn, if ALLCHILDREN etc. is set
941 0 : vcl::Window* pWindow = ImplGetFirstOverlapWindow();
942 0 : if ( bOverlapWindows )
943 0 : pWindow->ImplCallOverlapPaint();
944 : else
945 : {
946 0 : if (pWindow->mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTCHILDREN))
947 0 : pWindow->ImplCallPaint(NULL, NULL, pWindow->mpWindowImpl->mnPaintFlags);
948 : }
949 :
950 0 : if ( bFlush )
951 0 : Flush();
952 : }
953 :
954 747659 : void Window::PrePaint(vcl::RenderContext& /*rRenderContext*/)
955 : {
956 747659 : }
957 :
958 764030 : void Window::PostPaint(vcl::RenderContext& /*rRenderContext*/)
959 : {
960 764030 : }
961 :
962 24300 : void Window::Paint(vcl::RenderContext& /*rRenderContext*/, const Rectangle& rRect)
963 : {
964 24300 : CallEventListeners(VCLEVENT_WINDOW_PAINT, const_cast<Rectangle *>(&rRect));
965 24300 : }
966 :
967 118505 : void Window::SetPaintTransparent( bool bTransparent )
968 : {
969 : // transparency is not useful for frames as the background would have to be provided by a different frame
970 118505 : if( bTransparent && mpWindowImpl->mbFrame )
971 118505 : return;
972 :
973 118505 : if ( mpWindowImpl->mpBorderWindow )
974 171 : mpWindowImpl->mpBorderWindow->SetPaintTransparent( bTransparent );
975 :
976 118505 : mpWindowImpl->mbPaintTransparent = bTransparent;
977 : }
978 :
979 0 : void Window::SetWindowRegionPixel()
980 : {
981 :
982 0 : if ( mpWindowImpl->mpBorderWindow )
983 0 : mpWindowImpl->mpBorderWindow->SetWindowRegionPixel();
984 0 : else if( mpWindowImpl->mbFrame )
985 : {
986 0 : mpWindowImpl->maWinRegion = vcl::Region(true);
987 0 : mpWindowImpl->mbWinRegion = false;
988 0 : mpWindowImpl->mpFrame->ResetClipRegion();
989 : }
990 : else
991 : {
992 0 : if ( mpWindowImpl->mbWinRegion )
993 : {
994 0 : mpWindowImpl->maWinRegion = vcl::Region(true);
995 0 : mpWindowImpl->mbWinRegion = false;
996 0 : ImplSetClipFlag();
997 :
998 0 : if ( IsReallyVisible() )
999 : {
1000 : // restore background storage
1001 0 : if ( mpWindowImpl->mpOverlapData && mpWindowImpl->mpOverlapData->mpSaveBackDev )
1002 0 : ImplDeleteOverlapBackground();
1003 0 : if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
1004 0 : ImplInvalidateAllOverlapBackgrounds();
1005 0 : Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
1006 0 : vcl::Region aRegion( aRect );
1007 0 : ImplInvalidateParentFrameRegion( aRegion );
1008 : }
1009 : }
1010 : }
1011 0 : }
1012 :
1013 0 : void Window::SetWindowRegionPixel( const vcl::Region& rRegion )
1014 : {
1015 :
1016 0 : if ( mpWindowImpl->mpBorderWindow )
1017 0 : mpWindowImpl->mpBorderWindow->SetWindowRegionPixel( rRegion );
1018 0 : else if( mpWindowImpl->mbFrame )
1019 : {
1020 0 : if( !rRegion.IsNull() )
1021 : {
1022 0 : mpWindowImpl->maWinRegion = rRegion;
1023 0 : mpWindowImpl->mbWinRegion = ! rRegion.IsEmpty();
1024 :
1025 0 : if( mpWindowImpl->mbWinRegion )
1026 : {
1027 : // set/update ClipRegion
1028 0 : RectangleVector aRectangles;
1029 0 : mpWindowImpl->maWinRegion.GetRegionRectangles(aRectangles);
1030 0 : mpWindowImpl->mpFrame->BeginSetClipRegion(aRectangles.size());
1031 :
1032 0 : for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter)
1033 : {
1034 : mpWindowImpl->mpFrame->UnionClipRegion(
1035 : aRectIter->Left(),
1036 : aRectIter->Top(),
1037 : aRectIter->GetWidth(), // orig nWidth was ((R - L) + 1), same as GetWidth does
1038 0 : aRectIter->GetHeight()); // same for height
1039 : }
1040 :
1041 0 : mpWindowImpl->mpFrame->EndSetClipRegion();
1042 :
1043 : //long nX;
1044 : //long nY;
1045 : //long nWidth;
1046 : //long nHeight;
1047 : //sal_uLong nRectCount;
1048 : //ImplRegionInfo aInfo;
1049 : //sal_Bool bRegionRect;
1050 :
1051 : //nRectCount = mpWindowImpl->maWinRegion.GetRectCount();
1052 : //mpWindowImpl->mpFrame->BeginSetClipRegion( nRectCount );
1053 : //bRegionRect = mpWindowImpl->maWinRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
1054 : //while ( bRegionRect )
1055 : //{
1056 : // mpWindowImpl->mpFrame->UnionClipRegion( nX, nY, nWidth, nHeight );
1057 : // bRegionRect = mpWindowImpl->maWinRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
1058 : //}
1059 : //mpWindowImpl->mpFrame->EndSetClipRegion();
1060 : }
1061 : else
1062 0 : SetWindowRegionPixel();
1063 : }
1064 : else
1065 0 : SetWindowRegionPixel();
1066 : }
1067 : else
1068 : {
1069 0 : if ( rRegion.IsNull() )
1070 : {
1071 0 : if ( mpWindowImpl->mbWinRegion )
1072 : {
1073 0 : mpWindowImpl->maWinRegion = vcl::Region(true);
1074 0 : mpWindowImpl->mbWinRegion = false;
1075 0 : ImplSetClipFlag();
1076 : }
1077 : }
1078 : else
1079 : {
1080 0 : mpWindowImpl->maWinRegion = rRegion;
1081 0 : mpWindowImpl->mbWinRegion = true;
1082 0 : ImplSetClipFlag();
1083 : }
1084 :
1085 0 : if ( IsReallyVisible() )
1086 : {
1087 : // restore background storage
1088 0 : if ( mpWindowImpl->mpOverlapData && mpWindowImpl->mpOverlapData->mpSaveBackDev )
1089 0 : ImplDeleteOverlapBackground();
1090 0 : if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
1091 0 : ImplInvalidateAllOverlapBackgrounds();
1092 0 : Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
1093 0 : vcl::Region aRegion( aRect );
1094 0 : ImplInvalidateParentFrameRegion( aRegion );
1095 : }
1096 : }
1097 0 : }
1098 :
1099 0 : const vcl::Region& Window::GetWindowRegionPixel() const
1100 : {
1101 :
1102 0 : if ( mpWindowImpl->mpBorderWindow )
1103 0 : return mpWindowImpl->mpBorderWindow->GetWindowRegionPixel();
1104 : else
1105 0 : return mpWindowImpl->maWinRegion;
1106 : }
1107 :
1108 0 : bool Window::IsWindowRegionPixel() const
1109 : {
1110 :
1111 0 : if ( mpWindowImpl->mpBorderWindow )
1112 0 : return mpWindowImpl->mpBorderWindow->IsWindowRegionPixel();
1113 : else
1114 0 : return mpWindowImpl->mbWinRegion;
1115 : }
1116 :
1117 107167 : vcl::Region Window::GetPaintRegion() const
1118 : {
1119 :
1120 107167 : if ( mpWindowImpl->mpPaintRegion )
1121 : {
1122 107167 : vcl::Region aRegion = *mpWindowImpl->mpPaintRegion;
1123 107167 : aRegion.Move( -mnOutOffX, -mnOutOffY );
1124 107167 : return PixelToLogic( aRegion );
1125 : }
1126 : else
1127 : {
1128 0 : vcl::Region aPaintRegion(true);
1129 0 : return aPaintRegion;
1130 : }
1131 : }
1132 :
1133 428169 : void Window::Invalidate( InvalidateFlags nFlags )
1134 : {
1135 428169 : if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
1136 718130 : return;
1137 :
1138 138208 : ImplInvalidate( NULL, nFlags );
1139 138208 : LogicInvalidate(0);
1140 : }
1141 :
1142 93561 : void Window::Invalidate( const Rectangle& rRect, InvalidateFlags nFlags )
1143 : {
1144 93561 : if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
1145 123490 : return;
1146 :
1147 63632 : OutputDevice *pOutDev = GetOutDev();
1148 63632 : Rectangle aRect = pOutDev->ImplLogicToDevicePixel( rRect );
1149 63632 : if ( !aRect.IsEmpty() )
1150 : {
1151 56262 : vcl::Region aRegion( aRect );
1152 56262 : ImplInvalidate( &aRegion, nFlags );
1153 56262 : Rectangle aLogicRectangle(rRect);
1154 56262 : LogicInvalidate(&aLogicRectangle);
1155 : }
1156 : }
1157 :
1158 826 : void Window::Invalidate( const vcl::Region& rRegion, InvalidateFlags nFlags )
1159 : {
1160 826 : if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
1161 826 : return;
1162 :
1163 826 : if ( rRegion.IsNull() )
1164 : {
1165 0 : ImplInvalidate( NULL, nFlags );
1166 0 : LogicInvalidate(0);
1167 : }
1168 : else
1169 : {
1170 826 : vcl::Region aRegion = ImplPixelToDevicePixel( LogicToPixel( rRegion ) );
1171 826 : if ( !aRegion.IsEmpty() )
1172 : {
1173 509 : ImplInvalidate( &aRegion, nFlags );
1174 509 : Rectangle aLogicRectangle = rRegion.GetBoundRect();
1175 509 : LogicInvalidate(&aLogicRectangle);
1176 826 : }
1177 : }
1178 : }
1179 :
1180 228 : void Window::Validate( ValidateFlags nFlags )
1181 : {
1182 :
1183 228 : if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
1184 228 : return;
1185 :
1186 228 : ImplValidate( NULL, nFlags );
1187 228 : LogicInvalidate(0);
1188 : }
1189 :
1190 70065 : bool Window::HasPaintEvent() const
1191 : {
1192 :
1193 70065 : if ( !mpWindowImpl->mbReallyVisible )
1194 14136 : return false;
1195 :
1196 55929 : if ( mpWindowImpl->mpFrameWindow->mpWindowImpl->mbPaintFrame )
1197 2914 : return true;
1198 :
1199 53015 : if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINT )
1200 21757 : return true;
1201 :
1202 31258 : if ( !ImplIsOverlapWindow() )
1203 : {
1204 31258 : const vcl::Window* pTempWindow = this;
1205 10090 : do
1206 : {
1207 39832 : pTempWindow = pTempWindow->ImplGetParent();
1208 39832 : if ( pTempWindow->mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINTCHILDREN | IMPL_PAINT_PAINTALLCHILDREN) )
1209 29742 : return true;
1210 : }
1211 10090 : while ( !pTempWindow->ImplIsOverlapWindow() );
1212 : }
1213 :
1214 1516 : return false;
1215 : }
1216 :
1217 81687 : void Window::Update()
1218 : {
1219 81687 : if ( mpWindowImpl->mpBorderWindow )
1220 : {
1221 71 : mpWindowImpl->mpBorderWindow->Update();
1222 71 : return;
1223 : }
1224 :
1225 81616 : if ( !mpWindowImpl->mbReallyVisible )
1226 14113 : return;
1227 :
1228 67503 : bool bFlush = false;
1229 67503 : if ( mpWindowImpl->mpFrameWindow->mpWindowImpl->mbPaintFrame )
1230 : {
1231 4876 : Point aPoint( 0, 0 );
1232 4876 : vcl::Region aRegion( Rectangle( aPoint, Size( mnOutWidth, mnOutHeight ) ) );
1233 4876 : ImplInvalidateOverlapFrameRegion( aRegion );
1234 4876 : if ( mpWindowImpl->mbFrame || (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame) )
1235 0 : bFlush = true;
1236 : }
1237 :
1238 : // First we should skip all windows which are Paint-Transparent
1239 67503 : vcl::Window* pUpdateWindow = this;
1240 67503 : vcl::Window* pWindow = pUpdateWindow;
1241 135137 : while ( !pWindow->ImplIsOverlapWindow() )
1242 : {
1243 67634 : if ( !pWindow->mpWindowImpl->mbPaintTransparent )
1244 : {
1245 67503 : pUpdateWindow = pWindow;
1246 67503 : break;
1247 : }
1248 131 : pWindow = pWindow->ImplGetParent();
1249 : }
1250 : // In order to limit drawing, an update only draws the window which
1251 : // has PAINTALLCHILDREN set
1252 67503 : pWindow = pUpdateWindow;
1253 208974 : do
1254 : {
1255 276477 : if ( pWindow->mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALLCHILDREN )
1256 49172 : pUpdateWindow = pWindow;
1257 276477 : if ( pWindow->ImplIsOverlapWindow() )
1258 67503 : break;
1259 208974 : pWindow = pWindow->ImplGetParent();
1260 : }
1261 : while ( pWindow );
1262 :
1263 : // if there is something to paint, trigger a Paint
1264 67503 : if ( pUpdateWindow->mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTCHILDREN) )
1265 : {
1266 30452 : ImplDelData aDogTag(this);
1267 :
1268 : // trigger an update also for system windows on top of us,
1269 : // otherwise holes would remain
1270 30452 : vcl::Window* pUpdateOverlapWindow = ImplGetFirstOverlapWindow()->mpWindowImpl->mpFirstOverlap;
1271 60904 : while ( pUpdateOverlapWindow )
1272 : {
1273 0 : pUpdateOverlapWindow->Update();
1274 0 : pUpdateOverlapWindow = pUpdateOverlapWindow->mpWindowImpl->mpNext;
1275 : }
1276 :
1277 30452 : pUpdateWindow->ImplCallPaint(NULL, NULL, pUpdateWindow->mpWindowImpl->mnPaintFlags);
1278 :
1279 30452 : if (aDogTag.IsDead())
1280 0 : return;
1281 30452 : bFlush = true;
1282 : }
1283 :
1284 67503 : if ( bFlush )
1285 30452 : Flush();
1286 : }
1287 :
1288 12783 : void Window::ImplPaintToDevice( OutputDevice* i_pTargetOutDev, const Point& i_rPos )
1289 : {
1290 12783 : bool bRVisible = mpWindowImpl->mbReallyVisible;
1291 12783 : mpWindowImpl->mbReallyVisible = mpWindowImpl->mbVisible;
1292 12783 : bool bDevOutput = mbDevOutput;
1293 12783 : mbDevOutput = true;
1294 :
1295 12783 : const OutputDevice *pOutDev = GetOutDev();
1296 12783 : long nOldDPIX = pOutDev->GetDPIX();
1297 12783 : long nOldDPIY = pOutDev->GetDPIY();
1298 12783 : mnDPIX = i_pTargetOutDev->GetDPIX();
1299 12783 : mnDPIY = i_pTargetOutDev->GetDPIY();
1300 12783 : bool bOutput = IsOutputEnabled();
1301 12783 : EnableOutput();
1302 :
1303 : DBG_ASSERT( GetMapMode().GetMapUnit() == MAP_PIXEL, "MapMode must be PIXEL based" );
1304 12783 : if ( GetMapMode().GetMapUnit() != MAP_PIXEL )
1305 12783 : return;
1306 :
1307 : // preserve graphicsstate
1308 12783 : Push();
1309 12783 : vcl::Region aClipRegion( GetClipRegion() );
1310 12783 : SetClipRegion();
1311 :
1312 12783 : GDIMetaFile* pOldMtf = GetConnectMetaFile();
1313 25566 : GDIMetaFile aMtf;
1314 12783 : SetConnectMetaFile( &aMtf );
1315 :
1316 : // put a push action to metafile
1317 12783 : Push();
1318 : // copy graphics state to metafile
1319 25566 : vcl::Font aCopyFont = GetFont();
1320 12783 : if( nOldDPIX != mnDPIX || nOldDPIY != mnDPIY )
1321 : {
1322 0 : aCopyFont.SetHeight( aCopyFont.GetHeight() * mnDPIY / nOldDPIY );
1323 0 : aCopyFont.SetWidth( aCopyFont.GetWidth() * mnDPIX / nOldDPIX );
1324 : }
1325 12783 : SetFont( aCopyFont );
1326 12783 : SetTextColor( GetTextColor() );
1327 12783 : if( IsLineColor() )
1328 12410 : SetLineColor( GetLineColor() );
1329 : else
1330 373 : SetLineColor();
1331 12783 : if( IsFillColor() )
1332 12782 : SetFillColor( GetFillColor() );
1333 : else
1334 1 : SetFillColor();
1335 12783 : if( IsTextLineColor() )
1336 0 : SetTextLineColor( GetTextLineColor() );
1337 : else
1338 12783 : SetTextLineColor();
1339 12783 : if( IsOverlineColor() )
1340 0 : SetOverlineColor( GetOverlineColor() );
1341 : else
1342 12783 : SetOverlineColor();
1343 12783 : if( IsTextFillColor() )
1344 220 : SetTextFillColor( GetTextFillColor() );
1345 : else
1346 12563 : SetTextFillColor();
1347 12783 : SetTextAlign( GetTextAlign() );
1348 12783 : SetRasterOp( GetRasterOp() );
1349 12783 : if( IsRefPoint() )
1350 0 : SetRefPoint( GetRefPoint() );
1351 : else
1352 12783 : SetRefPoint();
1353 12783 : SetLayoutMode( GetLayoutMode() );
1354 12783 : SetDigitLanguage( GetDigitLanguage() );
1355 12783 : Rectangle aPaintRect( Point( 0, 0 ), GetOutputSizePixel() );
1356 12783 : aClipRegion.Intersect( aPaintRect );
1357 12783 : SetClipRegion( aClipRegion );
1358 :
1359 : // do the actual paint
1360 :
1361 : // background
1362 12783 : if( ! IsPaintTransparent() && IsBackground() && ! (GetParentClipMode() & ParentClipMode::NoClip ) )
1363 5891 : Erase(*this);
1364 : // foreground
1365 12783 : Paint(*this, aPaintRect);
1366 : // put a pop action to metafile
1367 12783 : Pop();
1368 :
1369 12783 : SetConnectMetaFile( pOldMtf );
1370 12783 : EnableOutput( bOutput );
1371 12783 : mpWindowImpl->mbReallyVisible = bRVisible;
1372 :
1373 : // paint metafile to VDev
1374 25566 : VclPtrInstance<VirtualDevice> pMaskedDevice( *i_pTargetOutDev, 0, 0 );
1375 12783 : pMaskedDevice->SetOutputSizePixel( GetOutputSizePixel() );
1376 12783 : pMaskedDevice->EnableRTL( IsRTLEnabled() );
1377 12783 : aMtf.WindStart();
1378 12783 : aMtf.Play( pMaskedDevice );
1379 25566 : BitmapEx aBmpEx( pMaskedDevice->GetBitmapEx( Point( 0, 0 ), pMaskedDevice->GetOutputSizePixel() ) );
1380 12783 : i_pTargetOutDev->DrawBitmapEx( i_rPos, aBmpEx );
1381 : // get rid of virtual device now so they don't pile up during recursive calls
1382 12783 : pMaskedDevice.disposeAndClear();
1383 :
1384 22500 : for( vcl::Window* pChild = mpWindowImpl->mpFirstChild; pChild; pChild = pChild->mpWindowImpl->mpNext )
1385 : {
1386 9717 : if( pChild->mpWindowImpl->mpFrame == mpWindowImpl->mpFrame && pChild->IsVisible() )
1387 : {
1388 8321 : long nDeltaX = pChild->mnOutOffX - mnOutOffX;
1389 :
1390 8321 : if( pOutDev->HasMirroredGraphics() )
1391 0 : nDeltaX = mnOutWidth - nDeltaX - pChild->mnOutWidth;
1392 8321 : long nDeltaY = pChild->GetOutOffYPixel() - GetOutOffYPixel();
1393 8321 : Point aPos( i_rPos );
1394 8321 : Point aDelta( nDeltaX, nDeltaY );
1395 8321 : aPos += aDelta;
1396 8321 : pChild->ImplPaintToDevice( i_pTargetOutDev, aPos );
1397 : }
1398 : }
1399 :
1400 : // restore graphics state
1401 12783 : Pop();
1402 :
1403 12783 : EnableOutput( bOutput );
1404 12783 : mpWindowImpl->mbReallyVisible = bRVisible;
1405 12783 : mbDevOutput = bDevOutput;
1406 12783 : mnDPIX = nOldDPIX;
1407 25566 : mnDPIY = nOldDPIY;
1408 : }
1409 :
1410 4462 : void Window::PaintToDevice( OutputDevice* pDev, const Point& rPos, const Size& /*rSize*/ )
1411 : {
1412 : // FIXME: scaling: currently this is for pixel copying only
1413 :
1414 : DBG_ASSERT( ! pDev->HasMirroredGraphics(), "PaintToDevice to mirroring graphics" );
1415 : DBG_ASSERT( ! pDev->IsRTLEnabled(), "PaintToDevice to mirroring device" );
1416 :
1417 4462 : vcl::Window* pRealParent = NULL;
1418 4462 : if( ! mpWindowImpl->mbVisible )
1419 : {
1420 4462 : vcl::Window* pTempParent = ImplGetDefaultWindow();
1421 4462 : if( pTempParent )
1422 4462 : pTempParent->EnableChildTransparentMode();
1423 4462 : pRealParent = GetParent();
1424 4462 : SetParent( pTempParent );
1425 : // trigger correct visibility flags for children
1426 4462 : Show();
1427 4462 : Hide();
1428 : }
1429 :
1430 4462 : bool bVisible = mpWindowImpl->mbVisible;
1431 4462 : mpWindowImpl->mbVisible = true;
1432 :
1433 4462 : if( mpWindowImpl->mpBorderWindow )
1434 3235 : mpWindowImpl->mpBorderWindow->ImplPaintToDevice( pDev, rPos );
1435 : else
1436 1227 : ImplPaintToDevice( pDev, rPos );
1437 :
1438 4462 : mpWindowImpl->mbVisible = bVisible;
1439 :
1440 4462 : if( pRealParent )
1441 4462 : SetParent( pRealParent );
1442 4462 : }
1443 :
1444 98794 : void Window::Erase(vcl::RenderContext& rRenderContext)
1445 : {
1446 98794 : if (!IsDeviceOutputNecessary() || ImplIsRecordLayout())
1447 98794 : return;
1448 :
1449 98794 : bool bNativeOK = false;
1450 :
1451 98794 : ControlPart aCtrlPart = ImplGetWindowImpl()->mnNativeBackground;
1452 98794 : if (aCtrlPart != 0 && ! IsControlBackground())
1453 : {
1454 0 : Rectangle aCtrlRegion(Point(), rRenderContext.GetOutputSizePixel());
1455 0 : ControlState nState = ControlState::NONE;
1456 :
1457 0 : if (IsEnabled())
1458 0 : nState |= ControlState::ENABLED;
1459 :
1460 : bNativeOK = rRenderContext.DrawNativeControl(CTRL_WINDOW_BACKGROUND, aCtrlPart, aCtrlRegion,
1461 0 : nState, ImplControlValue(), OUString());
1462 : }
1463 :
1464 98794 : if (mbBackground && !bNativeOK)
1465 : {
1466 98794 : RasterOp eRasterOp = GetRasterOp();
1467 98794 : if (eRasterOp != ROP_OVERPAINT)
1468 0 : SetRasterOp(ROP_OVERPAINT);
1469 98794 : rRenderContext.DrawWallpaper(0, 0, mnOutWidth, mnOutHeight, maBackground);
1470 98794 : if (eRasterOp != ROP_OVERPAINT)
1471 0 : rRenderContext.SetRasterOp(eRasterOp);
1472 : }
1473 :
1474 98794 : if (mpAlphaVDev)
1475 0 : mpAlphaVDev->Erase();
1476 : }
1477 :
1478 4777 : void Window::ImplScroll( const Rectangle& rRect,
1479 : long nHorzScroll, long nVertScroll, ScrollFlags nFlags )
1480 : {
1481 4777 : if ( !IsDeviceOutputNecessary() )
1482 8478 : return;
1483 :
1484 627 : nHorzScroll = ImplLogicWidthToDevicePixel( nHorzScroll );
1485 627 : nVertScroll = ImplLogicHeightToDevicePixel( nVertScroll );
1486 :
1487 627 : if ( !nHorzScroll && !nVertScroll )
1488 178 : return;
1489 :
1490 : // restore background storage
1491 449 : if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
1492 0 : ImplInvalidateAllOverlapBackgrounds();
1493 :
1494 449 : if ( mpWindowImpl->mpCursor )
1495 228 : mpWindowImpl->mpCursor->ImplSuspend();
1496 :
1497 449 : ScrollFlags nOrgFlags = nFlags;
1498 449 : if ( !(nFlags & (ScrollFlags::Children | ScrollFlags::NoChildren)) )
1499 : {
1500 111 : if ( GetStyle() & WB_CLIPCHILDREN )
1501 3 : nFlags |= ScrollFlags::NoChildren;
1502 : else
1503 108 : nFlags |= ScrollFlags::Children;
1504 : }
1505 :
1506 449 : vcl::Region aInvalidateRegion;
1507 449 : bool bScrollChildren(nFlags & ScrollFlags::Children);
1508 449 : bool bErase(!(nFlags & ScrollFlags::NoErase));
1509 :
1510 449 : if ( !mpWindowImpl->mpFirstChild )
1511 394 : bScrollChildren = false;
1512 :
1513 449 : OutputDevice *pOutDev = GetOutDev();
1514 :
1515 : // --- RTL --- check if this window requires special action
1516 449 : bool bReMirror = ( ImplIsAntiparallel() );
1517 :
1518 449 : Rectangle aRectMirror( rRect );
1519 449 : if( bReMirror )
1520 : {
1521 : // --- RTL --- make sure the invalidate region of this window is
1522 : // computed in the same coordinate space as the one from the overlap windows
1523 0 : pOutDev->ReMirror( aRectMirror );
1524 : }
1525 :
1526 : // adapt paint areas
1527 449 : ImplMoveAllInvalidateRegions( aRectMirror, nHorzScroll, nVertScroll, bScrollChildren );
1528 :
1529 449 : if ( !(nFlags & ScrollFlags::NoInvalidate) )
1530 : {
1531 449 : ImplCalcOverlapRegion( aRectMirror, aInvalidateRegion, !bScrollChildren, true, false );
1532 :
1533 : // --- RTL ---
1534 : // if the scrolling on the device is performed in the opposite direction
1535 : // then move the overlaps in that direction to compute the invalidate region
1536 : // on the correct side, i.e., revert nHorzScroll
1537 :
1538 449 : if ( !aInvalidateRegion.IsEmpty() )
1539 : {
1540 22 : aInvalidateRegion.Move( bReMirror ? -nHorzScroll : nHorzScroll, nVertScroll );
1541 22 : bErase = true;
1542 : }
1543 449 : if ( !(nFlags & ScrollFlags::NoWindowInvalidate) )
1544 : {
1545 449 : Rectangle aDestRect( aRectMirror );
1546 449 : aDestRect.Move( bReMirror ? -nHorzScroll : nHorzScroll, nVertScroll );
1547 449 : vcl::Region aWinInvalidateRegion( aRectMirror );
1548 449 : aWinInvalidateRegion.Exclude( aDestRect );
1549 :
1550 449 : aInvalidateRegion.Union( aWinInvalidateRegion );
1551 : }
1552 : }
1553 :
1554 449 : Point aPoint( mnOutOffX, mnOutOffY );
1555 898 : vcl::Region aRegion( Rectangle( aPoint, Size( mnOutWidth, mnOutHeight ) ) );
1556 449 : if ( nFlags & ScrollFlags::Clip )
1557 0 : aRegion.Intersect( rRect );
1558 449 : if ( mpWindowImpl->mbWinRegion )
1559 0 : aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
1560 :
1561 449 : aRegion.Exclude( aInvalidateRegion );
1562 :
1563 449 : ImplClipBoundaries( aRegion, false, true );
1564 449 : if ( !bScrollChildren )
1565 : {
1566 397 : if ( nOrgFlags & ScrollFlags::NoChildren )
1567 0 : ImplClipAllChildren( aRegion );
1568 : else
1569 397 : ImplClipChildren( aRegion );
1570 : }
1571 449 : if ( mbClipRegion && (nFlags & ScrollFlags::UseClipRegion) )
1572 0 : aRegion.Intersect( maRegion );
1573 449 : if ( !aRegion.IsEmpty() )
1574 : {
1575 300 : if ( mpWindowImpl->mpWinData )
1576 : {
1577 0 : if ( mpWindowImpl->mbFocusVisible )
1578 0 : ImplInvertFocus( *(mpWindowImpl->mpWinData->mpFocusRect) );
1579 0 : if ( mpWindowImpl->mbTrackVisible && (mpWindowImpl->mpWinData->mnTrackFlags & SHOWTRACK_WINDOW) )
1580 0 : InvertTracking( *(mpWindowImpl->mpWinData->mpTrackRect), mpWindowImpl->mpWinData->mnTrackFlags );
1581 : }
1582 : #ifndef IOS
1583 : // This seems completely unnecessary with tiled rendering, and
1584 : // causes the "AquaSalGraphics::copyArea() for non-layered
1585 : // graphics" message. Presumably we should bypass this on all
1586 : // platforms when dealing with a "window" that uses tiled
1587 : // rendering at the moment. Unclear how to figure that out,
1588 : // though. Also unclear whether we actually could just not
1589 : // create a "frame window", whatever that exactly is, in the
1590 : // tiled rendering case, or at least for platforms where tiles
1591 : // rendering is all there is.
1592 :
1593 300 : SalGraphics* pGraphics = ImplGetFrameGraphics();
1594 300 : if ( pGraphics )
1595 : {
1596 300 : if( bReMirror )
1597 : {
1598 : // --- RTL --- frame coordinates require re-mirroring
1599 0 : pOutDev->ReMirror( aRegion );
1600 : }
1601 :
1602 300 : pOutDev->SelectClipRegion( aRegion, pGraphics );
1603 600 : pGraphics->CopyArea( rRect.Left()+nHorzScroll, rRect.Top()+nVertScroll,
1604 : rRect.Left(), rRect.Top(),
1605 : rRect.GetWidth(), rRect.GetHeight(),
1606 900 : SAL_COPYAREA_WINDOWINVALIDATE, this );
1607 : }
1608 : #endif
1609 300 : if ( mpWindowImpl->mpWinData )
1610 : {
1611 0 : if ( mpWindowImpl->mbFocusVisible )
1612 0 : ImplInvertFocus( *(mpWindowImpl->mpWinData->mpFocusRect) );
1613 0 : if ( mpWindowImpl->mbTrackVisible && (mpWindowImpl->mpWinData->mnTrackFlags & SHOWTRACK_WINDOW) )
1614 0 : InvertTracking( *(mpWindowImpl->mpWinData->mpTrackRect), mpWindowImpl->mpWinData->mnTrackFlags );
1615 : }
1616 : }
1617 :
1618 449 : if ( !aInvalidateRegion.IsEmpty() )
1619 : {
1620 : // --- RTL --- the invalidate region for this windows is already computed in frame coordinates
1621 : // so it has to be re-mirrored before calling the Paint-handler
1622 449 : mpWindowImpl->mnPaintFlags |= IMPL_PAINT_CHECKRTL;
1623 :
1624 449 : InvalidateFlags nPaintFlags = InvalidateFlags::Children;
1625 449 : if ( !bErase )
1626 0 : nPaintFlags |= InvalidateFlags::NoErase;
1627 449 : if ( !bScrollChildren )
1628 : {
1629 397 : if ( nOrgFlags & ScrollFlags::NoChildren )
1630 0 : ImplClipAllChildren( aInvalidateRegion );
1631 : else
1632 397 : ImplClipChildren( aInvalidateRegion );
1633 : }
1634 449 : ImplInvalidateFrameRegion( &aInvalidateRegion, nPaintFlags );
1635 : }
1636 :
1637 449 : if ( bScrollChildren )
1638 : {
1639 52 : vcl::Window* pWindow = mpWindowImpl->mpFirstChild;
1640 159 : while ( pWindow )
1641 : {
1642 55 : Point aPos = pWindow->GetPosPixel();
1643 55 : aPos += Point( nHorzScroll, nVertScroll );
1644 55 : pWindow->SetPosPixel( aPos );
1645 :
1646 55 : pWindow = pWindow->mpWindowImpl->mpNext;
1647 : }
1648 : }
1649 :
1650 449 : if ( nFlags & ScrollFlags::Update )
1651 0 : Update();
1652 :
1653 449 : if ( mpWindowImpl->mpCursor )
1654 677 : mpWindowImpl->mpCursor->ImplResume();
1655 : }
1656 :
1657 801 : } /* namespace vcl */
1658 :
1659 :
1660 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|