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 <vcl/window.hxx>
21 : #include <vcl/virdev.hxx>
22 :
23 : #include <sal/types.h>
24 :
25 : #include <salobj.hxx>
26 : #include <window.h>
27 :
28 : #define IMPL_MAXSAVEBACKSIZE (640*480)
29 : #define IMPL_MAXALLSAVEBACKSIZE (800*600*2)
30 :
31 : namespace vcl {
32 :
33 568949 : void Window::InitClipRegion()
34 : {
35 : DBG_TESTSOLARMUTEX();
36 :
37 568949 : vcl::Region aRegion;
38 :
39 : // Put back backed up background
40 568949 : if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
41 0 : ImplInvalidateAllOverlapBackgrounds();
42 568949 : if ( mpWindowImpl->mbInPaint )
43 544668 : aRegion = *(mpWindowImpl->mpPaintRegion);
44 : else
45 : {
46 24281 : aRegion = *(ImplGetWinChildClipRegion());
47 : // --- RTL -- only this region is in frame coordinates, so re-mirror it
48 : // the mpWindowImpl->mpPaintRegion above is already correct (see ImplCallPaint()) !
49 24281 : if( ImplIsAntiparallel() )
50 1405 : ReMirror ( aRegion );
51 : }
52 568949 : if ( mbClipRegion )
53 342124 : aRegion.Intersect( ImplPixelToDevicePixel( maRegion ) );
54 568949 : if ( aRegion.IsEmpty() )
55 96511 : mbOutputClipped = true;
56 : else
57 : {
58 472438 : mbOutputClipped = false;
59 472438 : SelectClipRegion( aRegion );
60 : }
61 568949 : mbClipRegionSet = true;
62 :
63 568949 : mbInitClipRegion = false;
64 568949 : }
65 :
66 93864 : void Window::SetParentClipMode( ParentClipMode nMode )
67 : {
68 93864 : if ( mpWindowImpl->mpBorderWindow )
69 170 : mpWindowImpl->mpBorderWindow->SetParentClipMode( nMode );
70 : else
71 : {
72 93694 : if ( !ImplIsOverlapWindow() )
73 : {
74 93689 : mpWindowImpl->mnParentClipMode = nMode;
75 93689 : if ( nMode & ParentClipMode::Clip )
76 17 : mpWindowImpl->mpParent->mpWindowImpl->mbClipChildren = true;
77 : }
78 : }
79 93864 : }
80 :
81 190251 : ParentClipMode Window::GetParentClipMode() const
82 : {
83 190251 : if ( mpWindowImpl->mpBorderWindow )
84 2349 : return mpWindowImpl->mpBorderWindow->GetParentClipMode();
85 : else
86 187902 : return mpWindowImpl->mnParentClipMode;
87 : }
88 :
89 0 : void Window::ExpandPaintClipRegion( const vcl::Region& rRegion )
90 : {
91 0 : if( mpWindowImpl->mpPaintRegion )
92 : {
93 0 : vcl::Region aPixRegion = LogicToPixel( rRegion );
94 0 : vcl::Region aDevPixRegion = ImplPixelToDevicePixel( aPixRegion );
95 :
96 0 : vcl::Region aWinChildRegion = *ImplGetWinChildClipRegion();
97 : // --- RTL -- only this region is in frame coordinates, so re-mirror it
98 0 : if( ImplIsAntiparallel() )
99 : {
100 0 : const OutputDevice *pOutDev = GetOutDev();
101 0 : pOutDev->ReMirror( aWinChildRegion );
102 : }
103 :
104 0 : aDevPixRegion.Intersect( aWinChildRegion );
105 0 : if( ! aDevPixRegion.IsEmpty() )
106 : {
107 0 : mpWindowImpl->mpPaintRegion->Union( aDevPixRegion );
108 0 : mbInitClipRegion = true;
109 0 : }
110 : }
111 0 : }
112 :
113 275 : vcl::Region Window::GetWindowClipRegionPixel() const
114 : {
115 275 : vcl::Region aWinClipRegion;
116 :
117 275 : if ( mpWindowImpl->mbInitWinClipRegion )
118 0 : const_cast<vcl::Window*>(this)->ImplInitWinClipRegion();
119 275 : aWinClipRegion = mpWindowImpl->maWinClipRegion;
120 :
121 275 : Rectangle aWinRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
122 550 : vcl::Region aWinRegion( aWinRect );
123 :
124 275 : if ( aWinRegion == aWinClipRegion )
125 275 : aWinClipRegion.SetNull();
126 :
127 275 : aWinClipRegion.Move( -mnOutOffX, -mnOutOffY );
128 :
129 550 : return aWinClipRegion;
130 : }
131 :
132 :
133 86377 : vcl::Region Window::GetActiveClipRegion() const
134 : {
135 86377 : vcl::Region aRegion(true);
136 :
137 86377 : if ( mpWindowImpl->mbInPaint )
138 : {
139 86377 : aRegion = *(mpWindowImpl->mpPaintRegion);
140 86377 : aRegion.Move( -mnOutOffX, -mnOutOffY );
141 : }
142 :
143 86377 : if ( mbClipRegion )
144 0 : aRegion.Intersect( maRegion );
145 :
146 86377 : return PixelToLogic( aRegion );
147 : }
148 :
149 62870 : void Window::ClipToPaintRegion(Rectangle& rDstRect)
150 : {
151 62870 : const vcl::Region aPaintRgn(GetPaintRegion());
152 :
153 62870 : if (!aPaintRgn.IsNull())
154 62870 : rDstRect.Intersection(LogicToPixel(aPaintRgn.GetBoundRect()));
155 62870 : }
156 :
157 0 : void Window::EnableClipSiblings( bool bClipSiblings )
158 : {
159 :
160 0 : if ( mpWindowImpl->mpBorderWindow )
161 0 : mpWindowImpl->mpBorderWindow->EnableClipSiblings( bClipSiblings );
162 :
163 0 : mpWindowImpl->mbClipSiblings = bClipSiblings;
164 0 : }
165 :
166 507070 : void Window::ImplClipBoundaries( vcl::Region& rRegion, bool bThis, bool bOverlaps )
167 : {
168 507070 : if ( bThis )
169 84631 : ImplIntersectWindowClipRegion( rRegion );
170 422439 : else if ( ImplIsOverlapWindow() )
171 : {
172 : // clip to frame if required
173 4003 : if ( !mpWindowImpl->mbFrame )
174 0 : rRegion.Intersect( Rectangle( Point( 0, 0 ), Size( mpWindowImpl->mpFrameWindow->mnOutWidth, mpWindowImpl->mpFrameWindow->mnOutHeight ) ) );
175 :
176 4003 : if ( bOverlaps && !rRegion.IsEmpty() )
177 : {
178 : // Clip Overlap Siblings
179 3964 : vcl::Window* pStartOverlapWindow = this;
180 7928 : while ( !pStartOverlapWindow->mpWindowImpl->mbFrame )
181 : {
182 0 : vcl::Window* pOverlapWindow = pStartOverlapWindow->mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap;
183 0 : while ( pOverlapWindow && (pOverlapWindow != pStartOverlapWindow) )
184 : {
185 0 : pOverlapWindow->ImplExcludeOverlapWindows2( rRegion );
186 0 : pOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
187 : }
188 0 : pStartOverlapWindow = pStartOverlapWindow->mpWindowImpl->mpOverlapWindow;
189 : }
190 :
191 : // Clip Child Overlap Windows
192 3964 : ImplExcludeOverlapWindows( rRegion );
193 : }
194 : }
195 : else
196 418436 : ImplGetParent()->ImplIntersectWindowClipRegion( rRegion );
197 507070 : }
198 :
199 99073 : bool Window::ImplClipChildren( vcl::Region& rRegion )
200 : {
201 99073 : bool bOtherClip = false;
202 99073 : vcl::Window* pWindow = mpWindowImpl->mpFirstChild;
203 559442 : while ( pWindow )
204 : {
205 361296 : if ( pWindow->mpWindowImpl->mbReallyVisible )
206 : {
207 : // read-out ParentClipMode-Flags
208 182011 : ParentClipMode nClipMode = pWindow->GetParentClipMode();
209 892679 : if ( !(nClipMode & ParentClipMode::NoClip) &&
210 710668 : ((nClipMode & ParentClipMode::Clip) || (GetStyle() & WB_CLIPCHILDREN)) )
211 176219 : pWindow->ImplExcludeWindowRegion( rRegion );
212 : else
213 5792 : bOtherClip = true;
214 : }
215 :
216 361296 : pWindow = pWindow->mpWindowImpl->mpNext;
217 : }
218 :
219 99073 : return bOtherClip;
220 : }
221 :
222 930 : void Window::ImplClipAllChildren( vcl::Region& rRegion )
223 : {
224 930 : vcl::Window* pWindow = mpWindowImpl->mpFirstChild;
225 2850 : while ( pWindow )
226 : {
227 990 : if ( pWindow->mpWindowImpl->mbReallyVisible )
228 704 : pWindow->ImplExcludeWindowRegion( rRegion );
229 990 : pWindow = pWindow->mpWindowImpl->mpNext;
230 : }
231 930 : }
232 :
233 0 : void Window::ImplClipSiblings( vcl::Region& rRegion )
234 : {
235 0 : vcl::Window* pWindow = ImplGetParent()->mpWindowImpl->mpFirstChild;
236 0 : while ( pWindow )
237 : {
238 0 : if ( pWindow == this )
239 0 : break;
240 :
241 0 : if ( pWindow->mpWindowImpl->mbReallyVisible )
242 0 : pWindow->ImplExcludeWindowRegion( rRegion );
243 :
244 0 : pWindow = pWindow->mpWindowImpl->mpNext;
245 : }
246 0 : }
247 :
248 269247 : void Window::ImplInitWinClipRegion()
249 : {
250 : // Build Window Region
251 538494 : mpWindowImpl->maWinClipRegion = Rectangle( Point( mnOutOffX, mnOutOffY ),
252 269247 : Size( mnOutWidth, mnOutHeight ) );
253 269247 : if ( mpWindowImpl->mbWinRegion )
254 0 : mpWindowImpl->maWinClipRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
255 :
256 : // ClipSiblings
257 269247 : if ( mpWindowImpl->mbClipSiblings && !ImplIsOverlapWindow() )
258 0 : ImplClipSiblings( mpWindowImpl->maWinClipRegion );
259 :
260 : // Clip Parent Boundaries
261 269247 : ImplClipBoundaries( mpWindowImpl->maWinClipRegion, false, true );
262 :
263 : // Clip Children
264 269247 : if ( (GetStyle() & WB_CLIPCHILDREN) || mpWindowImpl->mbClipChildren )
265 113850 : mpWindowImpl->mbInitChildRegion = true;
266 :
267 269247 : mpWindowImpl->mbInitWinClipRegion = false;
268 269247 : }
269 :
270 80525 : void Window::ImplInitWinChildClipRegion()
271 : {
272 80525 : if ( !mpWindowImpl->mpFirstChild )
273 : {
274 27141 : if ( mpWindowImpl->mpChildClipRegion )
275 : {
276 31 : delete mpWindowImpl->mpChildClipRegion;
277 31 : mpWindowImpl->mpChildClipRegion = NULL;
278 : }
279 : }
280 : else
281 : {
282 53384 : if ( !mpWindowImpl->mpChildClipRegion )
283 18282 : mpWindowImpl->mpChildClipRegion = new vcl::Region( mpWindowImpl->maWinClipRegion );
284 : else
285 35102 : *mpWindowImpl->mpChildClipRegion = mpWindowImpl->maWinClipRegion;
286 :
287 53384 : ImplClipChildren( *mpWindowImpl->mpChildClipRegion );
288 : }
289 :
290 80525 : mpWindowImpl->mbInitChildRegion = false;
291 80525 : }
292 :
293 263851 : Region* Window::ImplGetWinChildClipRegion()
294 : {
295 263851 : if ( mpWindowImpl->mbInitWinClipRegion )
296 143401 : ImplInitWinClipRegion();
297 263851 : if ( mpWindowImpl->mbInitChildRegion )
298 80525 : ImplInitWinChildClipRegion();
299 263851 : if ( mpWindowImpl->mpChildClipRegion )
300 58146 : return mpWindowImpl->mpChildClipRegion;
301 : else
302 205705 : return &mpWindowImpl->maWinClipRegion;
303 : }
304 :
305 :
306 56 : bool Window::ImplSysObjClip( const vcl::Region* pOldRegion )
307 : {
308 56 : bool bUpdate = true;
309 :
310 56 : if ( mpWindowImpl->mpSysObj )
311 : {
312 56 : bool bVisibleState = mpWindowImpl->mbReallyVisible;
313 :
314 56 : if ( bVisibleState )
315 : {
316 0 : vcl::Region* pWinChildClipRegion = ImplGetWinChildClipRegion();
317 :
318 0 : if ( !pWinChildClipRegion->IsEmpty() )
319 : {
320 0 : if ( pOldRegion )
321 : {
322 0 : vcl::Region aNewRegion = *pWinChildClipRegion;
323 0 : pWinChildClipRegion->Intersect( *pOldRegion );
324 0 : bUpdate = aNewRegion == *pWinChildClipRegion;
325 : }
326 :
327 0 : if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
328 0 : ImplInvalidateAllOverlapBackgrounds();
329 :
330 0 : vcl::Region aRegion = *pWinChildClipRegion;
331 0 : Rectangle aWinRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
332 0 : vcl::Region aWinRectRegion( aWinRect );
333 0 : sal_uInt16 nClipFlags = mpWindowImpl->mpSysObj->GetClipRegionType();
334 :
335 0 : if ( aRegion == aWinRectRegion )
336 0 : mpWindowImpl->mpSysObj->ResetClipRegion();
337 : else
338 : {
339 0 : if ( nClipFlags & SAL_OBJECT_CLIP_EXCLUDERECTS )
340 : {
341 0 : aWinRectRegion.Exclude( aRegion );
342 0 : aRegion = aWinRectRegion;
343 : }
344 0 : if ( !(nClipFlags & SAL_OBJECT_CLIP_ABSOLUTE) )
345 0 : aRegion.Move( -mnOutOffX, -mnOutOffY );
346 :
347 : // set/update clip region
348 0 : RectangleVector aRectangles;
349 0 : aRegion.GetRegionRectangles(aRectangles);
350 0 : mpWindowImpl->mpSysObj->BeginSetClipRegion(aRectangles.size());
351 :
352 0 : for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter)
353 : {
354 : mpWindowImpl->mpSysObj->UnionClipRegion(
355 : aRectIter->Left(),
356 : aRectIter->Top(),
357 : aRectIter->GetWidth(), // orig nWidth was ((R - L) + 1), same as GetWidth does
358 0 : aRectIter->GetHeight()); // same for height
359 : }
360 :
361 0 : mpWindowImpl->mpSysObj->EndSetClipRegion();
362 0 : }
363 : }
364 : else
365 0 : bVisibleState = false;
366 : }
367 :
368 : // update visible status
369 56 : mpWindowImpl->mpSysObj->Show( bVisibleState );
370 : }
371 :
372 56 : return bUpdate;
373 : }
374 :
375 0 : void Window::ImplUpdateSysObjChildrenClip()
376 : {
377 0 : if ( mpWindowImpl->mpSysObj && mpWindowImpl->mbInitWinClipRegion )
378 0 : ImplSysObjClip( NULL );
379 :
380 0 : vcl::Window* pWindow = mpWindowImpl->mpFirstChild;
381 0 : while ( pWindow )
382 : {
383 0 : pWindow->ImplUpdateSysObjChildrenClip();
384 0 : pWindow = pWindow->mpWindowImpl->mpNext;
385 : }
386 0 : }
387 :
388 0 : void Window::ImplUpdateSysObjOverlapsClip()
389 : {
390 0 : ImplUpdateSysObjChildrenClip();
391 :
392 0 : vcl::Window* pWindow = mpWindowImpl->mpFirstOverlap;
393 0 : while ( pWindow )
394 : {
395 0 : pWindow->ImplUpdateSysObjOverlapsClip();
396 0 : pWindow = pWindow->mpWindowImpl->mpNext;
397 : }
398 0 : }
399 :
400 0 : void Window::ImplUpdateSysObjClip()
401 : {
402 0 : if ( !ImplIsOverlapWindow() )
403 : {
404 0 : ImplUpdateSysObjChildrenClip();
405 :
406 : // siblings should recalculate their clip region
407 0 : if ( mpWindowImpl->mbClipSiblings )
408 : {
409 0 : vcl::Window* pWindow = mpWindowImpl->mpNext;
410 0 : while ( pWindow )
411 : {
412 0 : pWindow->ImplUpdateSysObjChildrenClip();
413 0 : pWindow = pWindow->mpWindowImpl->mpNext;
414 : }
415 : }
416 : }
417 : else
418 0 : mpWindowImpl->mpFrameWindow->ImplUpdateSysObjOverlapsClip();
419 0 : }
420 :
421 1799568 : bool Window::ImplSetClipFlagChildren( bool bSysObjOnlySmaller )
422 : {
423 1799568 : bool bUpdate = true;
424 1799568 : if ( mpWindowImpl->mpSysObj )
425 : {
426 56 : vcl::Region* pOldRegion = NULL;
427 56 : if ( bSysObjOnlySmaller && !mpWindowImpl->mbInitWinClipRegion )
428 0 : pOldRegion = new vcl::Region( mpWindowImpl->maWinClipRegion );
429 :
430 56 : mbInitClipRegion = true;
431 56 : mpWindowImpl->mbInitWinClipRegion = true;
432 :
433 56 : vcl::Window* pWindow = mpWindowImpl->mpFirstChild;
434 112 : while ( pWindow )
435 : {
436 0 : if ( !pWindow->ImplSetClipFlagChildren( bSysObjOnlySmaller ) )
437 0 : bUpdate = false;
438 0 : pWindow = pWindow->mpWindowImpl->mpNext;
439 : }
440 :
441 56 : if ( !ImplSysObjClip( pOldRegion ) )
442 : {
443 0 : mbInitClipRegion = true;
444 0 : mpWindowImpl->mbInitWinClipRegion = true;
445 0 : bUpdate = false;
446 : }
447 :
448 56 : delete pOldRegion;
449 : }
450 : else
451 : {
452 1799512 : mbInitClipRegion = true;
453 1799512 : mpWindowImpl->mbInitWinClipRegion = true;
454 :
455 1799512 : vcl::Window* pWindow = mpWindowImpl->mpFirstChild;
456 5127128 : while ( pWindow )
457 : {
458 1528104 : if ( !pWindow->ImplSetClipFlagChildren( bSysObjOnlySmaller ) )
459 0 : bUpdate = false;
460 1528104 : pWindow = pWindow->mpWindowImpl->mpNext;
461 : }
462 : }
463 1799568 : return bUpdate;
464 : }
465 :
466 6462 : bool Window::ImplSetClipFlagOverlapWindows( bool bSysObjOnlySmaller )
467 : {
468 6462 : bool bUpdate = ImplSetClipFlagChildren( bSysObjOnlySmaller );
469 :
470 6462 : vcl::Window* pWindow = mpWindowImpl->mpFirstOverlap;
471 12924 : while ( pWindow )
472 : {
473 0 : if ( !pWindow->ImplSetClipFlagOverlapWindows( bSysObjOnlySmaller ) )
474 0 : bUpdate = false;
475 0 : pWindow = pWindow->mpWindowImpl->mpNext;
476 : }
477 :
478 6462 : return bUpdate;
479 : }
480 :
481 271464 : bool Window::ImplSetClipFlag( bool bSysObjOnlySmaller )
482 : {
483 271464 : if ( !ImplIsOverlapWindow() )
484 : {
485 265002 : bool bUpdate = ImplSetClipFlagChildren( bSysObjOnlySmaller );
486 :
487 265002 : vcl::Window* pParent = ImplGetParent();
488 1223976 : if ( pParent &&
489 631038 : ((pParent->GetStyle() & WB_CLIPCHILDREN) || (mpWindowImpl->mnParentClipMode & ParentClipMode::Clip)) )
490 : {
491 214485 : pParent->mbInitClipRegion = true;
492 214485 : pParent->mpWindowImpl->mbInitChildRegion = true;
493 : }
494 :
495 : // siblings should recalculate their clip region
496 265002 : if ( mpWindowImpl->mbClipSiblings )
497 : {
498 0 : vcl::Window* pWindow = mpWindowImpl->mpNext;
499 0 : while ( pWindow )
500 : {
501 0 : if ( !pWindow->ImplSetClipFlagChildren( bSysObjOnlySmaller ) )
502 0 : bUpdate = false;
503 0 : pWindow = pWindow->mpWindowImpl->mpNext;
504 : }
505 : }
506 :
507 265002 : return bUpdate;
508 : }
509 : else
510 6462 : return mpWindowImpl->mpFrameWindow->ImplSetClipFlagOverlapWindows( bSysObjOnlySmaller );
511 : }
512 :
513 503067 : void Window::ImplIntersectWindowClipRegion( vcl::Region& rRegion )
514 : {
515 503067 : if ( mpWindowImpl->mbInitWinClipRegion )
516 98369 : ImplInitWinClipRegion();
517 :
518 503067 : rRegion.Intersect( mpWindowImpl->maWinClipRegion );
519 503067 : }
520 :
521 22 : void Window::ImplIntersectWindowRegion( vcl::Region& rRegion )
522 : {
523 : rRegion.Intersect( Rectangle( Point( mnOutOffX, mnOutOffY ),
524 22 : Size( mnOutWidth, mnOutHeight ) ) );
525 22 : if ( mpWindowImpl->mbWinRegion )
526 0 : rRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
527 22 : }
528 :
529 321834 : void Window::ImplExcludeWindowRegion( vcl::Region& rRegion )
530 : {
531 321834 : if ( mpWindowImpl->mbWinRegion )
532 : {
533 0 : Point aPoint( mnOutOffX, mnOutOffY );
534 : vcl::Region aRegion( Rectangle( aPoint,
535 0 : Size( mnOutWidth, mnOutHeight ) ) );
536 0 : aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
537 0 : rRegion.Exclude( aRegion );
538 : }
539 : else
540 : {
541 321834 : Point aPoint( mnOutOffX, mnOutOffY );
542 : rRegion.Exclude( Rectangle( aPoint,
543 321834 : Size( mnOutWidth, mnOutHeight ) ) );
544 : }
545 321834 : }
546 :
547 3964 : void Window::ImplExcludeOverlapWindows( vcl::Region& rRegion )
548 : {
549 3964 : vcl::Window* pWindow = mpWindowImpl->mpFirstOverlap;
550 7928 : while ( pWindow )
551 : {
552 0 : if ( pWindow->mpWindowImpl->mbReallyVisible )
553 : {
554 0 : pWindow->ImplExcludeWindowRegion( rRegion );
555 0 : pWindow->ImplExcludeOverlapWindows( rRegion );
556 : }
557 :
558 0 : pWindow = pWindow->mpWindowImpl->mpNext;
559 : }
560 3964 : }
561 :
562 0 : void Window::ImplExcludeOverlapWindows2( vcl::Region& rRegion )
563 : {
564 0 : if ( mpWindowImpl->mbReallyVisible )
565 0 : ImplExcludeWindowRegion( rRegion );
566 :
567 0 : ImplExcludeOverlapWindows( rRegion );
568 0 : }
569 :
570 460 : void Window::ImplIntersectAndUnionOverlapWindows( const vcl::Region& rInterRegion, vcl::Region& rRegion )
571 : {
572 460 : vcl::Window* pWindow = mpWindowImpl->mpFirstOverlap;
573 920 : while ( pWindow )
574 : {
575 0 : if ( pWindow->mpWindowImpl->mbReallyVisible )
576 : {
577 0 : vcl::Region aTempRegion( rInterRegion );
578 0 : pWindow->ImplIntersectWindowRegion( aTempRegion );
579 0 : rRegion.Union( aTempRegion );
580 0 : pWindow->ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
581 : }
582 :
583 0 : pWindow = pWindow->mpWindowImpl->mpNext;
584 : }
585 460 : }
586 :
587 0 : void Window::ImplIntersectAndUnionOverlapWindows2( const vcl::Region& rInterRegion, vcl::Region& rRegion )
588 : {
589 0 : if ( mpWindowImpl->mbReallyVisible )
590 : {
591 0 : vcl::Region aTempRegion( rInterRegion );
592 0 : ImplIntersectWindowRegion( aTempRegion );
593 0 : rRegion.Union( aTempRegion );
594 : }
595 :
596 0 : ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
597 0 : }
598 :
599 460 : void Window::ImplCalcOverlapRegionOverlaps( const vcl::Region& rInterRegion, vcl::Region& rRegion )
600 : {
601 : // Clip Overlap Siblings
602 : vcl::Window* pStartOverlapWindow;
603 460 : if ( !ImplIsOverlapWindow() )
604 460 : pStartOverlapWindow = mpWindowImpl->mpOverlapWindow;
605 : else
606 0 : pStartOverlapWindow = this;
607 920 : while ( !pStartOverlapWindow->mpWindowImpl->mbFrame )
608 : {
609 0 : vcl::Window* pOverlapWindow = pStartOverlapWindow->mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap;
610 0 : while ( pOverlapWindow && (pOverlapWindow != pStartOverlapWindow) )
611 : {
612 0 : pOverlapWindow->ImplIntersectAndUnionOverlapWindows2( rInterRegion, rRegion );
613 0 : pOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
614 : }
615 0 : pStartOverlapWindow = pStartOverlapWindow->mpWindowImpl->mpOverlapWindow;
616 : }
617 :
618 : // Clip Child Overlap Windows
619 460 : if ( !ImplIsOverlapWindow() )
620 460 : mpWindowImpl->mpOverlapWindow->ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
621 : else
622 0 : ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
623 460 : }
624 :
625 460 : void Window::ImplCalcOverlapRegion( const Rectangle& rSourceRect, vcl::Region& rRegion,
626 : bool bChildren, bool bParent, bool bSiblings )
627 : {
628 460 : vcl::Region aRegion( rSourceRect );
629 460 : if ( mpWindowImpl->mbWinRegion )
630 0 : rRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
631 920 : vcl::Region aTempRegion;
632 : vcl::Window* pWindow;
633 :
634 460 : ImplCalcOverlapRegionOverlaps( aRegion, rRegion );
635 :
636 : // Parent-Boundaries
637 460 : if ( bParent )
638 : {
639 460 : pWindow = this;
640 460 : if ( !ImplIsOverlapWindow() )
641 : {
642 460 : pWindow = ImplGetParent();
643 1829 : do
644 : {
645 2289 : aTempRegion = aRegion;
646 2289 : pWindow->ImplExcludeWindowRegion( aTempRegion );
647 2289 : rRegion.Union( aTempRegion );
648 2289 : if ( pWindow->ImplIsOverlapWindow() )
649 460 : break;
650 1829 : pWindow = pWindow->ImplGetParent();
651 : }
652 : while ( pWindow );
653 : }
654 460 : if ( pWindow && !pWindow->mpWindowImpl->mbFrame )
655 : {
656 0 : aTempRegion = aRegion;
657 0 : aTempRegion.Exclude( Rectangle( Point( 0, 0 ), Size( mpWindowImpl->mpFrameWindow->mnOutWidth, mpWindowImpl->mpFrameWindow->mnOutHeight ) ) );
658 0 : rRegion.Union( aTempRegion );
659 : }
660 : }
661 :
662 : // Siblings
663 460 : if ( bSiblings && !ImplIsOverlapWindow() )
664 : {
665 11 : pWindow = mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild;
666 76 : do
667 : {
668 76 : if ( pWindow->mpWindowImpl->mbReallyVisible && (pWindow != this) )
669 : {
670 19 : aTempRegion = aRegion;
671 19 : pWindow->ImplIntersectWindowRegion( aTempRegion );
672 19 : rRegion.Union( aTempRegion );
673 : }
674 76 : pWindow = pWindow->mpWindowImpl->mpNext;
675 : }
676 : while ( pWindow );
677 : }
678 :
679 460 : if ( bChildren )
680 : {
681 397 : pWindow = mpWindowImpl->mpFirstChild;
682 803 : while ( pWindow )
683 : {
684 9 : if ( pWindow->mpWindowImpl->mbReallyVisible )
685 : {
686 3 : aTempRegion = aRegion;
687 3 : pWindow->ImplIntersectWindowRegion( aTempRegion );
688 3 : rRegion.Union( aTempRegion );
689 : }
690 9 : pWindow = pWindow->mpWindowImpl->mpNext;
691 : }
692 460 : }
693 460 : }
694 :
695 0 : bool Window::ImplIsWindowInFront( const vcl::Window* pTestWindow ) const
696 : {
697 : // check for overlapping window
698 0 : pTestWindow = pTestWindow->ImplGetFirstOverlapWindow();
699 0 : const vcl::Window* pTempWindow = pTestWindow;
700 0 : const vcl::Window* pThisWindow = ImplGetFirstOverlapWindow();
701 0 : if ( pTempWindow == pThisWindow )
702 0 : return false;
703 0 : do
704 : {
705 0 : if ( pTempWindow == pThisWindow )
706 0 : return true;
707 0 : if ( pTempWindow->mpWindowImpl->mbFrame )
708 0 : break;
709 0 : pTempWindow = pTempWindow->mpWindowImpl->mpOverlapWindow;
710 : }
711 : while ( pTempWindow );
712 0 : pTempWindow = pThisWindow;
713 0 : do
714 : {
715 0 : if ( pTempWindow == pTestWindow )
716 0 : return false;
717 0 : if ( pTempWindow->mpWindowImpl->mbFrame )
718 0 : break;
719 0 : pTempWindow = pTempWindow->mpWindowImpl->mpOverlapWindow;
720 : }
721 : while ( pTempWindow );
722 :
723 : // move window to same level
724 0 : if ( pThisWindow->mpWindowImpl->mpOverlapWindow != pTestWindow->mpWindowImpl->mpOverlapWindow )
725 : {
726 0 : sal_uInt16 nThisLevel = 0;
727 0 : sal_uInt16 nTestLevel = 0;
728 0 : pTempWindow = pThisWindow;
729 0 : do
730 : {
731 0 : nThisLevel++;
732 0 : pTempWindow = pTempWindow->mpWindowImpl->mpOverlapWindow;
733 : }
734 0 : while ( !pTempWindow->mpWindowImpl->mbFrame );
735 0 : pTempWindow = pTestWindow;
736 0 : do
737 : {
738 0 : nTestLevel++;
739 0 : pTempWindow = pTempWindow->mpWindowImpl->mpOverlapWindow;
740 : }
741 0 : while ( !pTempWindow->mpWindowImpl->mbFrame );
742 :
743 0 : if ( nThisLevel < nTestLevel )
744 : {
745 0 : do
746 : {
747 0 : if ( pTestWindow->mpWindowImpl->mpOverlapWindow == pThisWindow->mpWindowImpl->mpOverlapWindow )
748 0 : break;
749 0 : if ( pTestWindow->mpWindowImpl->mbFrame )
750 0 : break;
751 0 : pTestWindow = pTestWindow->mpWindowImpl->mpOverlapWindow;
752 : }
753 : while ( pTestWindow );
754 : }
755 : else
756 : {
757 0 : do
758 : {
759 0 : if ( pThisWindow->mpWindowImpl->mpOverlapWindow == pTempWindow->mpWindowImpl->mpOverlapWindow )
760 0 : break;
761 0 : if ( pThisWindow->mpWindowImpl->mbFrame )
762 0 : break;
763 0 : pThisWindow = pThisWindow->mpWindowImpl->mpOverlapWindow;
764 : }
765 : while ( pThisWindow );
766 : }
767 : }
768 :
769 : // if TestWindow is before ThisWindow, it is in front
770 0 : pTempWindow = pTestWindow;
771 0 : while ( pTempWindow )
772 : {
773 0 : if ( pTempWindow == pThisWindow )
774 0 : return true;
775 0 : pTempWindow = pTempWindow->mpWindowImpl->mpNext;
776 : }
777 :
778 0 : return false;
779 : }
780 :
781 0 : void Window::SaveBackground( const Point& rPos, const Size& rSize,
782 : const Point& rDestOff, VirtualDevice& rSaveDevice )
783 : {
784 0 : if ( mpWindowImpl->mpPaintRegion )
785 : {
786 0 : vcl::Region aClip( *mpWindowImpl->mpPaintRegion );
787 0 : const Point aPixPos( LogicToPixel( rPos ) );
788 :
789 0 : aClip.Move( -mnOutOffX, -mnOutOffY );
790 0 : aClip.Intersect( Rectangle( aPixPos, LogicToPixel( rSize ) ) );
791 :
792 0 : if ( !aClip.IsEmpty() )
793 : {
794 0 : const vcl::Region aOldClip( rSaveDevice.GetClipRegion() );
795 0 : const Point aPixOffset( rSaveDevice.LogicToPixel( rDestOff ) );
796 0 : const bool bMap = rSaveDevice.IsMapModeEnabled();
797 :
798 : // move clip region to have the same distance to DestOffset
799 0 : aClip.Move( aPixOffset.X() - aPixPos.X(), aPixOffset.Y() - aPixPos.Y() );
800 :
801 : // set pixel clip region
802 0 : rSaveDevice.EnableMapMode( false );
803 0 : rSaveDevice.SetClipRegion( aClip );
804 0 : rSaveDevice.EnableMapMode( bMap );
805 0 : rSaveDevice.DrawOutDev( rDestOff, rSize, rPos, rSize, *this );
806 0 : rSaveDevice.SetClipRegion( aOldClip );
807 0 : }
808 : }
809 : else
810 0 : rSaveDevice.DrawOutDev( rDestOff, rSize, rPos, rSize, *this );
811 0 : }
812 :
813 0 : void Window::ImplSaveOverlapBackground()
814 : {
815 : DBG_ASSERT( !mpWindowImpl->mpOverlapData->mpSaveBackDev, "Window::ImplSaveOverlapBackground() - Background already saved" );
816 :
817 0 : if ( !mpWindowImpl->mbFrame )
818 : {
819 0 : sal_uLong nSaveBackSize = mnOutWidth*mnOutHeight;
820 0 : if ( nSaveBackSize <= IMPL_MAXSAVEBACKSIZE )
821 : {
822 0 : if ( nSaveBackSize+mpWindowImpl->mpFrameData->mnAllSaveBackSize <= IMPL_MAXALLSAVEBACKSIZE )
823 : {
824 0 : Size aOutSize( mnOutWidth, mnOutHeight );
825 0 : mpWindowImpl->mpOverlapData->mpSaveBackDev = VclPtr<VirtualDevice>::Create( *mpWindowImpl->mpFrameWindow );
826 0 : if ( mpWindowImpl->mpOverlapData->mpSaveBackDev->SetOutputSizePixel( aOutSize ) )
827 : {
828 0 : mpWindowImpl->mpFrameWindow->ImplUpdateAll();
829 :
830 0 : if ( mpWindowImpl->mbInitWinClipRegion )
831 0 : ImplInitWinClipRegion();
832 :
833 0 : mpWindowImpl->mpOverlapData->mnSaveBackSize = nSaveBackSize;
834 0 : mpWindowImpl->mpFrameData->mnAllSaveBackSize += nSaveBackSize;
835 0 : Point aDevPt;
836 :
837 0 : Window* pWin = mpWindowImpl->mpFrameWindow;
838 : pWin->getFrameDev( Point( mnOutOffX, mnOutOffY ),
839 : aDevPt, aOutSize,
840 0 : *(mpWindowImpl->mpOverlapData->mpSaveBackDev) );
841 0 : mpWindowImpl->mpOverlapData->mpNextBackWin = mpWindowImpl->mpFrameData->mpFirstBackWin;
842 0 : mpWindowImpl->mpFrameData->mpFirstBackWin = this;
843 : }
844 : else
845 : {
846 0 : mpWindowImpl->mpOverlapData->mpSaveBackDev.disposeAndClear();
847 : }
848 : }
849 : }
850 : }
851 0 : }
852 :
853 0 : bool Window::ImplRestoreOverlapBackground( vcl::Region& rInvRegion )
854 : {
855 0 : if ( mpWindowImpl->mpOverlapData->mpSaveBackDev )
856 : {
857 0 : if ( mpWindowImpl->mbInitWinClipRegion )
858 0 : ImplInitWinClipRegion();
859 :
860 0 : if ( mpWindowImpl->mpOverlapData->mpSaveBackDev )
861 : {
862 0 : Point aDevPt;
863 0 : Point aDestPt( mnOutOffX, mnOutOffY );
864 0 : Size aDevSize = mpWindowImpl->mpOverlapData->mpSaveBackDev->GetOutputSizePixel();
865 :
866 0 : Window *pWin = mpWindowImpl->mpFrameWindow;
867 :
868 0 : if ( mpWindowImpl->mpOverlapData->mpSaveBackRgn )
869 : {
870 0 : mpWindowImpl->mpOverlapData->mpSaveBackRgn->Intersect( mpWindowImpl->maWinClipRegion );
871 0 : rInvRegion = mpWindowImpl->maWinClipRegion;
872 0 : rInvRegion.Exclude( *mpWindowImpl->mpOverlapData->mpSaveBackRgn );
873 : pWin->drawFrameDev( aDestPt, aDevPt, aDevSize,
874 0 : *(mpWindowImpl->mpOverlapData->mpSaveBackDev),
875 0 : *mpWindowImpl->mpOverlapData->mpSaveBackRgn );
876 : }
877 : else
878 : {
879 : pWin->drawFrameDev( aDestPt, aDevPt, aDevSize,
880 0 : *(mpWindowImpl->mpOverlapData->mpSaveBackDev),
881 0 : mpWindowImpl->maWinClipRegion );
882 : }
883 0 : ImplDeleteOverlapBackground();
884 : }
885 :
886 0 : return true;
887 : }
888 :
889 0 : return false;
890 : }
891 :
892 0 : void Window::ImplDeleteOverlapBackground()
893 : {
894 0 : if ( mpWindowImpl->mpOverlapData->mpSaveBackDev )
895 : {
896 0 : mpWindowImpl->mpFrameData->mnAllSaveBackSize -= mpWindowImpl->mpOverlapData->mnSaveBackSize;
897 0 : mpWindowImpl->mpOverlapData->mpSaveBackDev.disposeAndClear();
898 0 : if ( mpWindowImpl->mpOverlapData->mpSaveBackRgn )
899 : {
900 0 : delete mpWindowImpl->mpOverlapData->mpSaveBackRgn;
901 0 : mpWindowImpl->mpOverlapData->mpSaveBackRgn = NULL;
902 : }
903 :
904 : // remove window from the list
905 0 : if ( mpWindowImpl->mpFrameData->mpFirstBackWin == this )
906 0 : mpWindowImpl->mpFrameData->mpFirstBackWin = mpWindowImpl->mpOverlapData->mpNextBackWin;
907 : else
908 : {
909 0 : vcl::Window* pTemp = mpWindowImpl->mpFrameData->mpFirstBackWin;
910 0 : while ( pTemp->mpWindowImpl->mpOverlapData->mpNextBackWin.get() != this )
911 0 : pTemp = pTemp->mpWindowImpl->mpOverlapData->mpNextBackWin;
912 0 : pTemp->mpWindowImpl->mpOverlapData->mpNextBackWin = mpWindowImpl->mpOverlapData->mpNextBackWin;
913 : }
914 0 : mpWindowImpl->mpOverlapData->mpNextBackWin = NULL;
915 : }
916 0 : }
917 :
918 0 : void Window::ImplInvalidateAllOverlapBackgrounds()
919 : {
920 0 : vcl::Window* pWindow = mpWindowImpl->mpFrameData->mpFirstBackWin;
921 0 : while ( pWindow )
922 : {
923 : // remember next window here already, as this window could
924 : // be removed within the next if clause from the list
925 0 : vcl::Window* pNext = pWindow->mpWindowImpl->mpOverlapData->mpNextBackWin;
926 :
927 0 : if ( ImplIsWindowInFront( pWindow ) )
928 : {
929 : Rectangle aRect1( Point( mnOutOffX, mnOutOffY ),
930 0 : Size( mnOutWidth, mnOutHeight ) );
931 : Rectangle aRect2( Point( pWindow->mnOutOffX, pWindow->mnOutOffY ),
932 0 : Size( pWindow->mnOutWidth, pWindow->mnOutHeight ) );
933 0 : aRect1.Intersection( aRect2 );
934 0 : if ( !aRect1.IsEmpty() )
935 : {
936 0 : if ( !pWindow->mpWindowImpl->mpOverlapData->mpSaveBackRgn )
937 0 : pWindow->mpWindowImpl->mpOverlapData->mpSaveBackRgn = new vcl::Region( aRect2 );
938 0 : pWindow->mpWindowImpl->mpOverlapData->mpSaveBackRgn->Exclude( aRect1 );
939 0 : if ( pWindow->mpWindowImpl->mpOverlapData->mpSaveBackRgn->IsEmpty() )
940 0 : pWindow->ImplDeleteOverlapBackground();
941 : }
942 :
943 : }
944 :
945 0 : pWindow = pNext;
946 : }
947 0 : }
948 :
949 : } /* namespace vcl */
950 :
951 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|