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