00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <config-X11.h>
00042
00043 #include "utils.h"
00044 #include <QTextStream>
00045 #include "workspace.h"
00046 #include "client.h"
00047 #include "unmanaged.h"
00048 #include "deleted.h"
00049 #include "effects.h"
00050 #include "scene.h"
00051 #include "scene_basic.h"
00052 #include "scene_xrender.h"
00053 #include "scene_opengl.h"
00054 #include "compositingprefs.h"
00055 #include "notifications.h"
00056
00057 #include <stdio.h>
00058
00059 #include <QMenu>
00060 #include <kaction.h>
00061 #include <kactioncollection.h>
00062 #include <klocale.h>
00063 #include <kxerrorhandler.h>
00064
00065 #include <X11/extensions/shape.h>
00066
00067 #ifdef HAVE_XCOMPOSITE
00068 #include <X11/extensions/Xcomposite.h>
00069 #if XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR >= 3
00070 #define HAVE_XCOMPOSITE_OVERLAY
00071 #endif
00072 #endif
00073 #ifdef HAVE_XRANDR
00074 #include <X11/extensions/Xrandr.h>
00075 #endif
00076
00077 namespace KWin
00078 {
00079
00080
00081
00082
00083
00084 void Workspace::setupCompositing()
00085 {
00086 #ifdef KWIN_HAVE_COMPOSITING
00087 if( scene != NULL )
00088 return;
00089 if( !options->useCompositing && getenv( "KWIN_COMPOSE") == NULL )
00090 {
00091 kDebug( 1212 ) << "Compositing is turned off in options or disabled";
00092 return;
00093 }
00094 else if( compositingSuspended )
00095 {
00096 kDebug( 1212 ) << "Compositing is suspended";
00097 return;
00098 }
00099 else if( !CompositingPrefs::compositingPossible() )
00100 {
00101 kError( 1212 ) << "Compositing is not possible";
00102 return;
00103 }
00104 CompositingType type = options->compositingMode;
00105 if( getenv( "KWIN_COMPOSE" ))
00106 {
00107 char c = getenv( "KWIN_COMPOSE" )[ 0 ];
00108 switch( c )
00109 {
00110 case 'O':
00111 type = OpenGLCompositing;
00112 break;
00113 case 'X':
00114 type = XRenderCompositing;
00115 break;
00116 default:
00117 kDebug( 1212 ) << "No compositing";
00118 return;
00119 }
00120 }
00121
00122 char selection_name[ 100 ];
00123 sprintf( selection_name, "_NET_WM_CM_S%d", DefaultScreen( display()));
00124 cm_selection = new KSelectionOwner( selection_name );
00125 connect( cm_selection, SIGNAL( lostOwnership()), SLOT( lostCMSelection()));
00126 cm_selection->claim( true );
00127
00128 switch( type )
00129 {
00130
00131
00132
00133
00134 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00135 case OpenGLCompositing:
00136 kDebug( 1212 ) << "OpenGL compositing";
00137 scene = new SceneOpenGL( this );
00138 if( !scene->initFailed())
00139 break;
00140 delete scene;
00141 scene = NULL;
00142 break;
00143 #endif
00144 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
00145 case XRenderCompositing:
00146 kDebug( 1212 ) << "XRender compositing";
00147 scene = new SceneXrender( this );
00148 break;
00149 #endif
00150 default:
00151 #ifndef KWIN_HAVE_COMPOSITING
00152 kDebug( 1212 ) << "Compositing was not available at compile time";
00153 #else
00154 kDebug( 1212 ) << "No compositing";
00155 #endif
00156 delete cm_selection;
00157 return;
00158 }
00159 if( scene == NULL || scene->initFailed())
00160 {
00161 kError( 1212 ) << "Failed to initialize compositing, compositing disabled";
00162 kError( 1212 ) << "Consult http://techbase.kde.org/Projects/KWin/4.0-release-notes#Setting_up";
00163 delete scene;
00164 scene = NULL;
00165 delete cm_selection;
00166 return;
00167 }
00168 int rate = 0;
00169 if( options->refreshRate > 0 )
00170 {
00171 rate = options->refreshRate;
00172 }
00173 #ifdef HAVE_XRANDR
00174 else
00175 {
00176 if( Extensions::randrAvailable() )
00177 {
00178 XRRScreenConfiguration *config;
00179
00180 config = XRRGetScreenInfo( display(), rootWindow() );
00181 rate = XRRConfigCurrentRate( config );
00182 XRRFreeScreenConfigInfo( config );
00183 }
00184 }
00185 #endif
00186
00187 if( rate <= 0 )
00188 rate = 50;
00189
00190
00191 else if( rate > 1000 )
00192 rate = 1000;
00193 kDebug( 1212 ) << "Refresh rate " << rate << "Hz";
00194 compositeRate = 1000 / rate;
00195 lastCompositePaint.start();
00196
00197 nextPaintReference = QTime::currentTime().addMSecs( -compositeRate );
00198 compositeTimer.setSingleShot( true );
00199 checkCompositeTimer();
00200 composite_paint_times.clear();
00201 XCompositeRedirectSubwindows( display(), rootWindow(), CompositeRedirectManual );
00202 new EffectsHandlerImpl( scene->compositingType() );
00203 addRepaintFull();
00204 foreach( Client* c, clients )
00205 c->setupCompositing();
00206 foreach( Client* c, desktops )
00207 c->setupCompositing();
00208 foreach( Unmanaged* c, unmanaged )
00209 c->setupCompositing();
00210 foreach( Client* c, clients )
00211 scene->windowAdded( c );
00212 foreach( Client* c, desktops )
00213 scene->windowAdded( c );
00214 foreach( Unmanaged* c, unmanaged )
00215 scene->windowAdded( c );
00216 discardPopup();
00217 #else
00218 kDebug( 1212 ) << "Compositing was not available at compile time";
00219 #endif
00220 }
00221
00222 void Workspace::finishCompositing()
00223 {
00224 #ifdef KWIN_HAVE_COMPOSITING
00225 if( scene == NULL )
00226 return;
00227 delete cm_selection;
00228 foreach( Client* c, clients )
00229 scene->windowClosed( c, NULL );
00230 foreach( Client* c, desktops )
00231 scene->windowClosed( c, NULL );
00232 foreach( Unmanaged* c, unmanaged )
00233 scene->windowClosed( c, NULL );
00234 foreach( Deleted* c, deleted )
00235 scene->windowDeleted( c );
00236 foreach( Client* c, clients )
00237 c->finishCompositing();
00238 foreach( Client* c, desktops )
00239 c->finishCompositing();
00240 foreach( Unmanaged* c, unmanaged )
00241 c->finishCompositing();
00242 foreach( Deleted* c, deleted )
00243 c->finishCompositing();
00244 XCompositeUnredirectSubwindows( display(), rootWindow(), CompositeRedirectManual );
00245 delete effects;
00246 effects = NULL;
00247 delete scene;
00248 scene = NULL;
00249 compositeTimer.stop();
00250 repaints_region = QRegion();
00251 for( ClientList::ConstIterator it = clients.constBegin();
00252 it != clients.constEnd();
00253 ++it )
00254 {
00255 if( (*it)->opacity() != 1.0 )
00256 {
00257 NETWinInfo2 i( display(), (*it)->frameId(), rootWindow(), 0 );
00258 i.setOpacity( static_cast< unsigned long >((*it)->opacity() * 0xffffffff ));
00259 }
00260 }
00261 discardPopup();
00262
00263 while( !deleted.isEmpty())
00264 deleted.first()->discard( Allowed );
00265 #endif
00266 }
00267
00268 void Workspace::lostCMSelection()
00269 {
00270 kDebug( 1212 ) << "Lost compositing manager selection";
00271 finishCompositing();
00272 }
00273
00274
00275 void Workspace::slotToggleCompositing()
00276 {
00277 suspendCompositing( !compositingSuspended );
00278 }
00279
00280 void Workspace::suspendCompositing()
00281 {
00282 suspendCompositing( true );
00283 }
00284
00285 void Workspace::suspendCompositing( bool suspend )
00286 {
00287 compositingSuspended = suspend;
00288 finishCompositing();
00289 setupCompositing();
00290 }
00291
00292 void Workspace::addRepaint( int x, int y, int w, int h )
00293 {
00294 if( !compositing())
00295 return;
00296 repaints_region += QRegion( x, y, w, h );
00297 checkCompositeTimer();
00298 }
00299
00300 void Workspace::addRepaint( const QRect& r )
00301 {
00302 if( !compositing())
00303 return;
00304 repaints_region += r;
00305 checkCompositeTimer();
00306 }
00307
00308 void Workspace::addRepaint( const QRegion& r )
00309 {
00310 if( !compositing())
00311 return;
00312 repaints_region += r;
00313 checkCompositeTimer();
00314 }
00315
00316 void Workspace::addRepaintFull()
00317 {
00318 if( !compositing())
00319 return;
00320 repaints_region = QRegion( 0, 0, displayWidth(), displayHeight());
00321 checkCompositeTimer();
00322 }
00323
00324 void Workspace::performCompositing()
00325 {
00326 #ifdef KWIN_HAVE_COMPOSITING
00327
00328
00329
00330
00331
00332 if( lastCompositePaint.elapsed() < 1 )
00333 {
00334 compositeTimer.start( 1 );
00335 return;
00336 }
00337 if( !scene->waitSyncAvailable())
00338 nextPaintReference = QTime::currentTime();
00339 checkCursorPos();
00340 if((( repaints_region.isEmpty() && !windowRepaintsPending())
00341 || !overlay_visible )
00342
00343 && !static_cast< EffectsHandlerImpl* >( effects )->activeFullScreenEffect() )
00344 {
00345 scene->idle();
00346
00347
00348
00349
00350 return;
00351 }
00352
00353 ToplevelList windows = xStackingOrder();
00354 foreach( EffectWindow* c, static_cast< EffectsHandlerImpl* >( effects )->elevatedWindows())
00355 {
00356 Toplevel* t = static_cast< EffectWindowImpl* >( c )->window();
00357 windows.removeAll( t );
00358 windows.append( t );
00359 }
00360
00361 ToplevelList tmp = windows;
00362 windows.clear();
00363 #if 0
00364
00365
00366
00367 foreach( Toplevel* c, tmp )
00368 if( c->readyForPainting())
00369 windows.append( c );
00370 #else
00371 foreach( Toplevel* c, tmp )
00372 windows.append( c );
00373 #endif
00374 foreach( Toplevel* c, windows )
00375 {
00376
00377
00378
00379 repaints_region |= c->repaints().translated( c->pos());
00380 c->resetRepaints( c->rect());
00381 }
00382 QRegion repaints = repaints_region;
00383
00384 repaints_region = QRegion();
00385 QTime t = QTime::currentTime();
00386 scene->paint( repaints, windows );
00387 if( scene->waitSyncAvailable())
00388 {
00389
00390
00391
00392
00393
00394 int reserve = compositeRate <= 10 ? compositeRate - 1 : 10;
00395 nextPaintReference = QTime::currentTime().addMSecs( -reserve );
00396 }
00397
00398
00399
00400
00401 checkCompositeTimer();
00402 checkCompositePaintTime( t.elapsed());
00403 lastCompositePaint.start();
00404 #endif
00405 }
00406
00407 bool Workspace::windowRepaintsPending() const
00408 {
00409 foreach( Toplevel* c, clients )
00410 if( !c->repaints().isEmpty())
00411 return true;
00412 foreach( Toplevel* c, desktops )
00413 if( !c->repaints().isEmpty())
00414 return true;
00415 foreach( Toplevel* c, unmanaged )
00416 if( !c->repaints().isEmpty())
00417 return true;
00418 foreach( Toplevel* c, deleted )
00419 if( !c->repaints().isEmpty())
00420 return true;
00421 return false;
00422 }
00423
00424 void Workspace::setCompositeTimer()
00425 {
00426 if( !compositing())
00427 return;
00428
00429
00430 compositeTimer.start( qBound( 0, nextPaintReference.msecsTo( QTime::currentTime() ), 250 ) % compositeRate );
00431 }
00432
00433 bool Workspace::createOverlay()
00434 {
00435 assert( overlay == None );
00436 if( !Extensions::compositeOverlayAvailable())
00437 return false;
00438 if( !Extensions::shapeInputAvailable())
00439 return false;
00440 #ifdef HAVE_XCOMPOSITE_OVERLAY
00441 overlay = XCompositeGetOverlayWindow( display(), rootWindow());
00442 if( overlay == None )
00443 return false;
00444 return true;
00445 #else
00446 return false;
00447 #endif
00448 }
00449
00450 void Workspace::checkCompositePaintTime( int msec )
00451 {
00452 if( options->disableCompositingChecks )
00453 return;
00454 composite_paint_times.prepend( msec );
00455 bool tooslow = false;
00456
00457
00458
00459 const int MAX_LONG_PAINT = 1000;
00460 if( composite_paint_times.count() >= 3 && composite_paint_times[ 0 ] > MAX_LONG_PAINT
00461 && composite_paint_times[ 1 ] > MAX_LONG_PAINT && composite_paint_times[ 2 ] > MAX_LONG_PAINT )
00462 {
00463 kDebug( 1212 ) << "Too long paint times, suspending";
00464 tooslow = true;
00465 }
00466
00467
00468
00469 const int MAX_SHORT_PAINT = 100;
00470 const int SHORT_TIME = 15000;
00471 int time = 0;
00472 foreach( int t, composite_paint_times )
00473 {
00474 if( t < MAX_SHORT_PAINT )
00475 break;
00476 time += t;
00477 if( time > SHORT_TIME )
00478 {
00479 kDebug( 1212 ) << "Long paint times for long time, suspending";
00480 tooslow = true;
00481 break;
00482 }
00483 }
00484 if( composite_paint_times.count() > 1000 )
00485 composite_paint_times.removeLast();
00486 if( tooslow )
00487 {
00488 QTimer::singleShot( 0, this, SLOT( suspendCompositing()));
00489 QString shortcut, message;
00490 if( KAction* action = qobject_cast<KAction*>( keys->action("Suspend Compositing")))
00491 shortcut = action->globalShortcut().primary().toString(QKeySequence::NativeText);
00492 if (shortcut.isEmpty())
00493 message = i18n( "Compositing was too slow and has been suspended.\n"
00494 "You can disable functionality checks in advanced compositing settings." );
00495 else
00496 message = i18n( "Compositing was too slow and has been suspended.\n"
00497 "If this was only a temporary problem, you can resume using the '%1' shortcut.\n"
00498 "You can also disable functionality checks in advanced compositing settings.", shortcut );
00499 Notify::raise( Notify::CompositingSlow, message );
00500 compositeTimer.start( 1000 );
00501 }
00502 }
00503
00504 void Workspace::setupOverlay( Window w )
00505 {
00506 assert( overlay != None );
00507 assert( Extensions::shapeInputAvailable());
00508 XSetWindowBackgroundPixmap( display(), overlay, None );
00509 overlay_shape = QRegion();
00510 setOverlayShape( QRect( 0, 0, displayWidth(), displayHeight()));
00511 if( w != None )
00512 {
00513 XSetWindowBackgroundPixmap( display(), w, None );
00514 XShapeCombineRectangles( display(), w, ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted );
00515 }
00516 XSelectInput( display(), overlay, VisibilityChangeMask );
00517 }
00518
00519 void Workspace::showOverlay()
00520 {
00521 assert( overlay != None );
00522 if( overlay_shown )
00523 return;
00524 XMapSubwindows( display(), overlay );
00525 XMapWindow( display(), overlay );
00526 overlay_shown = true;
00527 }
00528
00529 void Workspace::hideOverlay()
00530 {
00531 assert( overlay != None );
00532 XUnmapWindow( display(), overlay );
00533 overlay_shown = false;
00534 setOverlayShape( QRect( 0, 0, displayWidth(), displayHeight()));
00535 }
00536
00537 void Workspace::setOverlayShape( const QRegion& reg )
00538 {
00539
00540
00541 if( reg == overlay_shape )
00542 return;
00543 QVector< QRect > rects = reg.rects();
00544 XRectangle* xrects = new XRectangle[ rects.count() ];
00545 for( int i = 0;
00546 i < rects.count();
00547 ++i )
00548 {
00549 xrects[ i ].x = rects[ i ].x();
00550 xrects[ i ].y = rects[ i ].y();
00551 xrects[ i ].width = rects[ i ].width();
00552 xrects[ i ].height = rects[ i ].height();
00553 }
00554 XShapeCombineRectangles( display(), overlay, ShapeBounding, 0, 0,
00555 xrects, rects.count(), ShapeSet, Unsorted );
00556 delete[] xrects;
00557 XShapeCombineRectangles( display(), overlay, ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted );
00558 overlay_shape = reg;
00559 }
00560
00561 void Workspace::destroyOverlay()
00562 {
00563 if( overlay == None )
00564 return;
00565
00566 XRectangle rec = { 0, 0, displayWidth(), displayHeight() };
00567 XShapeCombineRectangles( display(), overlay, ShapeBounding, 0, 0, &rec, 1, ShapeSet, Unsorted );
00568 XShapeCombineRectangles( display(), overlay, ShapeInput, 0, 0, &rec, 1, ShapeSet, Unsorted );
00569 #ifdef HAVE_XCOMPOSITE_OVERLAY
00570 XCompositeReleaseOverlayWindow( display(), overlay );
00571 #endif
00572 overlay = None;
00573 overlay_shown = false;
00574 }
00575
00576 bool Workspace::compositingActive()
00577 {
00578 return compositing();
00579 }
00580
00581
00582 void Workspace::checkUnredirect( bool force )
00583 {
00584 if( !compositing() || overlay == None || !options->unredirectFullscreen )
00585 return;
00586 if( force )
00587 forceUnredirectCheck = true;
00588 if( !unredirectTimer.isActive())
00589 unredirectTimer.start( 0 );
00590 }
00591
00592 void Workspace::delayedCheckUnredirect()
00593 {
00594 if( !compositing() || overlay == None || !options->unredirectFullscreen )
00595 return;
00596 ToplevelList list;
00597 bool changed = forceUnredirectCheck;
00598 foreach( Client* c, clients )
00599 list.append( c );
00600 foreach( Unmanaged* c, unmanaged )
00601 list.append( c );
00602 foreach( Toplevel* c, list )
00603 {
00604 if( c->updateUnredirectedState())
00605 changed = true;
00606 }
00607
00608 if( !changed )
00609 return;
00610 forceUnredirectCheck = false;
00611
00612
00613 QRegion reg( 0, 0, displayWidth(), displayHeight());
00614 foreach( Toplevel* c, list )
00615 {
00616 if( c->unredirected())
00617 reg -= c->geometry();
00618 }
00619 setOverlayShape( reg );
00620 }
00621
00622
00623
00624
00625
00626 void Toplevel::setupCompositing()
00627 {
00628 #ifdef KWIN_HAVE_COMPOSITING
00629 if( !compositing())
00630 return;
00631 if( damage_handle != None )
00632 return;
00633 damage_handle = XDamageCreate( display(), frameId(), XDamageReportRawRectangles );
00634 damage_region = QRegion( 0, 0, width(), height());
00635 effect_window = new EffectWindowImpl();
00636 effect_window->setWindow( this );
00637 unredirect = false;
00638 workspace()->checkUnredirect( true );
00639 #endif
00640 }
00641
00642 void Toplevel::finishCompositing()
00643 {
00644 #ifdef KWIN_HAVE_COMPOSITING
00645 if( damage_handle == None )
00646 return;
00647 workspace()->checkUnredirect( true );
00648 if( effect_window->window() == this )
00649 {
00650 discardWindowPixmap();
00651 delete effect_window;
00652 }
00653 XDamageDestroy( display(), damage_handle );
00654 damage_handle = None;
00655 damage_region = QRegion();
00656 repaints_region = QRegion();
00657 effect_window = NULL;
00658 #endif
00659 }
00660
00661 void Toplevel::discardWindowPixmap()
00662 {
00663 addDamageFull();
00664 if( window_pix == None )
00665 return;
00666 XFreePixmap( display(), window_pix );
00667 window_pix = None;
00668 if( effectWindow() != NULL && effectWindow()->sceneWindow() != NULL )
00669 effectWindow()->sceneWindow()->pixmapDiscarded();
00670 }
00671
00672 Pixmap Toplevel::createWindowPixmap()
00673 {
00674 #ifdef KWIN_HAVE_COMPOSITING
00675 assert( compositing());
00676 if( unredirected())
00677 return None;
00678 grabXServer();
00679 KXErrorHandler err;
00680 Pixmap pix = XCompositeNameWindowPixmap( display(), frameId());
00681
00682
00683 XWindowAttributes attrs;
00684 if( !XGetWindowAttributes( display(), frameId(), &attrs )
00685 || err.error( false )
00686 || attrs.width != width() || attrs.height != height() || attrs.map_state != IsViewable )
00687 {
00688 kDebug( 1212 ) << "Creating window pixmap failed: " << this;
00689 XFreePixmap( display(), pix );
00690 pix = None;
00691 }
00692 ungrabXServer();
00693 return pix;
00694 #else
00695 return None;
00696 #endif
00697 }
00698
00699 #ifdef HAVE_XDAMAGE
00700 void Toplevel::damageNotifyEvent( XDamageNotifyEvent* e )
00701 {
00702 QRegion damage( e->area.x, e->area.y, e->area.width, e->area.height );
00703
00704 int cnt = 1;
00705 while( XPending( display()))
00706 {
00707 XEvent e2;
00708 if( XPeekEvent( display(), &e2 ) && e2.type == Extensions::damageNotifyEvent()
00709 && e2.xany.window == frameId())
00710 {
00711 XNextEvent( display(), &e2 );
00712 if( cnt > 200 )
00713 {
00714
00715
00716
00717
00718 damage = rect();
00719 continue;
00720 }
00721 XDamageNotifyEvent* e = reinterpret_cast< XDamageNotifyEvent* >( &e2 );
00722 QRect r( e->area.x, e->area.y, e->area.width, e->area.height );
00723 ++cnt;
00724
00725
00726
00727
00728
00729 if( cnt > 50 )
00730 {
00731 r.setLeft( r.left() / 100 * 100 );
00732 r.setRight(( r.right() + 99 ) / 100 * 100 );
00733 r.setTop( r.top() / 100 * 100 );
00734 r.setBottom(( r.bottom() + 99 ) / 100 * 100 );
00735 }
00736 damage += r;
00737 continue;
00738 }
00739 break;
00740 }
00741 foreach( const QRect& r, damage.rects())
00742 addDamage( r );
00743 }
00744
00745 void Client::damageNotifyEvent( XDamageNotifyEvent* e )
00746 {
00747 Toplevel::damageNotifyEvent( e );
00748 #ifdef HAVE_XSYNC
00749 if( sync_counter == None )
00750 ready_for_painting = true;
00751 #else
00752 ready_for_painting = true;
00753 #endif
00754 }
00755 #endif
00756
00757 void Toplevel::addDamage( const QRect& r )
00758 {
00759 addDamage( r.x(), r.y(), r.width(), r.height());
00760 }
00761
00762 void Toplevel::addDamage( int x, int y, int w, int h )
00763 {
00764 if( !compositing())
00765 return;
00766 QRect r( x, y, w, h );
00767
00768
00769 r &= rect();
00770 damage_region += r;
00771 repaints_region += r;
00772 static_cast<EffectsHandlerImpl*>(effects)->windowDamaged( effectWindow(), r );
00773 workspace()->checkCompositeTimer();
00774 }
00775
00776 void Toplevel::addDamageFull()
00777 {
00778 if( !compositing())
00779 return;
00780 damage_region = rect();
00781 repaints_region = rect();
00782 static_cast<EffectsHandlerImpl*>(effects)->windowDamaged( effectWindow(), rect());
00783 workspace()->checkCompositeTimer();
00784 }
00785
00786 void Toplevel::resetDamage( const QRect& r )
00787 {
00788 damage_region -= r;
00789 }
00790
00791 void Toplevel::addRepaint( const QRect& r )
00792 {
00793 addRepaint( r.x(), r.y(), r.width(), r.height());
00794 }
00795
00796 void Toplevel::addRepaint( int x, int y, int w, int h )
00797 {
00798 if( !compositing())
00799 return;
00800 QRect r( x, y, w, h );
00801 r &= rect();
00802 repaints_region += r;
00803 workspace()->checkCompositeTimer();
00804 }
00805
00806 void Toplevel::addRepaintFull()
00807 {
00808 repaints_region = rect();
00809 workspace()->checkCompositeTimer();
00810 }
00811
00812 void Toplevel::resetRepaints( const QRect& r )
00813 {
00814 repaints_region -= r;
00815 }
00816
00817 void Toplevel::addWorkspaceRepaint( int x, int y, int w, int h )
00818 {
00819 addWorkspaceRepaint( QRect( x, y, w, h ));
00820 }
00821
00822 void Toplevel::addWorkspaceRepaint( const QRect& r2 )
00823 {
00824 if( !compositing())
00825 return;
00826 if( effectWindow() == NULL )
00827 return workspace()->addRepaint( r2 );
00828 QRect r = effects->transformWindowDamage( effectWindow(), r2 );
00829 workspace()->addRepaint( r );
00830 }
00831
00832 bool Toplevel::updateUnredirectedState()
00833 {
00834 assert( compositing());
00835 bool should = shouldUnredirect() && !unredirectSuspend && !shape() && !hasAlpha() && opacity() == 1.0 &&
00836 !static_cast<EffectsHandlerImpl*>( effects )->activeFullScreenEffect();
00837 if( should && !unredirect )
00838 {
00839 unredirect = true;
00840 kDebug( 1212 ) << "Unredirecting:" << this;
00841 #ifdef HAVE_XCOMPOSITE
00842 XCompositeUnredirectWindow( display(), frameId(), CompositeRedirectManual );
00843 #endif
00844 return true;
00845 }
00846 else if( !should && unredirect )
00847 {
00848 unredirect = false;
00849 kDebug( 1212 ) << "Redirecting:" << this;
00850 #ifdef HAVE_XCOMPOSITE
00851 XCompositeRedirectWindow( display(), frameId(), CompositeRedirectManual );
00852 #endif
00853 discardWindowPixmap();
00854 return true;
00855 }
00856 return false;
00857 }
00858
00859 void Toplevel::suspendUnredirect( bool suspend )
00860 {
00861 if( unredirectSuspend == suspend )
00862 return;
00863 unredirectSuspend = suspend;
00864 workspace()->checkUnredirect();
00865 }
00866
00867
00868
00869
00870
00871 void Client::setupCompositing()
00872 {
00873 Toplevel::setupCompositing();
00874 updateVisibility();
00875 }
00876
00877 void Client::finishCompositing()
00878 {
00879 Toplevel::finishCompositing();
00880 updateVisibility();
00881 }
00882
00883 bool Client::shouldUnredirect() const
00884 {
00885 if( isActiveFullScreen())
00886 {
00887 ToplevelList stacking = workspace()->xStackingOrder();
00888 for( int pos = stacking.count() - 1;
00889 pos >= 0;
00890 --pos )
00891 {
00892 Toplevel* c = stacking.at( pos );
00893 if( c == this )
00894 return true;
00895 if( c->geometry().intersects( geometry()))
00896 return false;
00897 }
00898 abort();
00899 }
00900 return false;
00901 }
00902
00903
00904
00905
00906
00907 bool Unmanaged::shouldUnredirect() const
00908 {
00909
00910
00911 if( resourceClass() == "ksplashx" || resourceClass() == "ksplashsimple" )
00912 return false;
00913
00914 if( geometry() == workspace()->clientArea( FullArea, geometry().center(), workspace()->currentDesktop())
00915 || geometry() == workspace()->clientArea( ScreenArea, geometry().center(), workspace()->currentDesktop()))
00916 {
00917 ToplevelList stacking = workspace()->xStackingOrder();
00918 for( int pos = stacking.count() - 1;
00919 pos >= 0;
00920 --pos )
00921 {
00922 Toplevel* c = stacking.at( pos );
00923 if( c == this )
00924 return true;
00925 if( c->geometry().intersects( geometry()))
00926 return false;
00927 }
00928 abort();
00929 }
00930 return false;
00931 }
00932
00933
00934
00935
00936
00937 bool Deleted::shouldUnredirect() const
00938 {
00939 return false;
00940 }
00941
00942 }