00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "client.h"
00013
00014 #include <qapplication.h>
00015 #include <qpainter.h>
00016 #include <qdatetime.h>
00017 #include <kprocess.h>
00018 #include <unistd.h>
00019 #include <kstandarddirs.h>
00020 #include <qwhatsthis.h>
00021 #include <kwin.h>
00022 #include <kiconloader.h>
00023 #include <stdlib.h>
00024
00025 #include "bridge.h"
00026 #include "group.h"
00027 #include "workspace.h"
00028 #include "atoms.h"
00029 #include "notifications.h"
00030 #include "rules.h"
00031
00032 #include <X11/extensions/shape.h>
00033
00034
00035
00036
00037 extern Atom qt_wm_state;
00038 extern Time qt_x_time;
00039 extern Atom qt_window_role;
00040 extern Atom qt_sm_client_id;
00041
00042 namespace KWinInternal
00043 {
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00069 Client::Client( Workspace *ws )
00070 : QObject( NULL ),
00071 client( None ),
00072 wrapper( None ),
00073 frame( None ),
00074 decoration( NULL ),
00075 wspace( ws ),
00076 bridge( new Bridge( this )),
00077 move_faked_activity( false ),
00078 move_resize_grab_window( None ),
00079 transient_for( NULL ),
00080 transient_for_id( None ),
00081 original_transient_for_id( None ),
00082 in_group( NULL ),
00083 window_group( None ),
00084 in_layer( UnknownLayer ),
00085 ping_timer( NULL ),
00086 process_killer( NULL ),
00087 user_time( CurrentTime ),
00088 allowed_actions( 0 ),
00089 block_geometry( 0 ),
00090 shade_geometry_change( false ),
00091 border_left( 0 ),
00092 border_right( 0 ),
00093 border_top( 0 ),
00094 border_bottom( 0 )
00095
00096 {
00097 autoRaiseTimer = 0;
00098 shadeHoverTimer = 0;
00099
00100
00101 mapping_state = WithdrawnState;
00102 desk = 0;
00103
00104 mode = PositionCenter;
00105 buttonDown = FALSE;
00106 moveResizeMode = FALSE;
00107
00108 info = NULL;
00109
00110 shade_mode = ShadeNone;
00111 active = FALSE;
00112 keep_above = FALSE;
00113 keep_below = FALSE;
00114 is_shape = FALSE;
00115 motif_noborder = false;
00116 motif_may_move = TRUE;
00117 motif_may_resize = TRUE;
00118 motif_may_close = TRUE;
00119 fullscreen_mode = FullScreenNone;
00120 skip_taskbar = FALSE;
00121 original_skip_taskbar = false;
00122 minimized = false;
00123 hidden = false;
00124 modal = false;
00125 noborder = false;
00126 user_noborder = false;
00127 not_obscured = false;
00128 urgency = false;
00129 ignore_focus_stealing = false;
00130 check_active_modal = false;
00131
00132 Pdeletewindow = 0;
00133 Ptakefocus = 0;
00134 Ptakeactivity = 0;
00135 Pcontexthelp = 0;
00136 Pping = 0;
00137 input = FALSE;
00138 skip_pager = FALSE;
00139
00140 max_mode = MaximizeRestore;
00141
00142 cmap = None;
00143
00144 frame_geometry = QRect( 0, 0, 100, 100 );
00145 client_size = QSize( 100, 100 );
00146
00147
00148 }
00149
00153 Client::~Client()
00154 {
00155 assert(!moveResizeMode);
00156 assert( client == None );
00157 assert( frame == None && wrapper == None );
00158 assert( decoration == NULL );
00159 assert( block_geometry == 0 );
00160 assert( !check_active_modal );
00161 delete info;
00162 delete bridge;
00163 }
00164
00165
00166 void Client::deleteClient( Client* c, allowed_t )
00167 {
00168 delete c;
00169 }
00170
00174 void Client::releaseWindow( bool on_shutdown )
00175 {
00176 if (moveResizeMode)
00177 leaveMoveResize();
00178 finishWindowRules();
00179 setModal( false );
00180 hidden = true;
00181 if( !on_shutdown )
00182 workspace()->clientHidden( this );
00183 XUnmapWindow( qt_xdisplay(), frameId());
00184 destroyDecoration();
00185 cleanGrouping();
00186 if( !on_shutdown )
00187 {
00188 workspace()->removeClient( this, Allowed );
00189
00190
00191 info->setDesktop( 0 );
00192 desk = 0;
00193 info->setState( 0, info->state());
00194 }
00195 XDeleteProperty( qt_xdisplay(), client, atoms->kde_net_wm_user_creation_time);
00196
00197 XReparentWindow( qt_xdisplay(), client, workspace()->rootWin(), x(), y());
00198 XRemoveFromSaveSet( qt_xdisplay(), client );
00199 XSelectInput( qt_xdisplay(), client, NoEventMask );
00200 if( on_shutdown )
00201 {
00202 XMapWindow( qt_xdisplay(), client );
00203
00204 }
00205 else
00206 {
00207
00208
00209 XUnmapWindow( qt_xdisplay(), client );
00210 }
00211 setMappingState( WithdrawnState );
00212 client = None;
00213 XDestroyWindow( qt_xdisplay(), wrapper );
00214 wrapper = None;
00215 XDestroyWindow( qt_xdisplay(), frame );
00216 frame = None;
00217 deleteClient( this, Allowed );
00218 }
00219
00220
00221
00222 void Client::destroyClient()
00223 {
00224 if (moveResizeMode)
00225 leaveMoveResize();
00226 finishWindowRules();
00227 ++block_geometry;
00228 setModal( false );
00229 hidden = true;
00230 workspace()->clientHidden( this );
00231 destroyDecoration();
00232 cleanGrouping();
00233 workspace()->removeClient( this, Allowed );
00234 client = None;
00235 XDestroyWindow( qt_xdisplay(), wrapper );
00236 wrapper = None;
00237 XDestroyWindow( qt_xdisplay(), frame );
00238 frame = None;
00239 --block_geometry;
00240 deleteClient( this, Allowed );
00241 }
00242
00243 void Client::updateDecoration( bool check_workspace_pos, bool force )
00244 {
00245 if( !force && (( decoration == NULL && noBorder())
00246 || ( decoration != NULL && !noBorder())))
00247 return;
00248 bool do_show = false;
00249 ++block_geometry;
00250 if( force )
00251 destroyDecoration();
00252 if( !noBorder())
00253 {
00254 decoration = workspace()->createDecoration( bridge );
00255
00256 decoration->init();
00257 decoration->widget()->installEventFilter( this );
00258 XReparentWindow( qt_xdisplay(), decoration->widget()->winId(), frameId(), 0, 0 );
00259 decoration->widget()->lower();
00260 decoration->borders( border_left, border_right, border_top, border_bottom );
00261 int save_workarea_diff_x = workarea_diff_x;
00262 int save_workarea_diff_y = workarea_diff_y;
00263 move( calculateGravitation( false ));
00264 if( !isShade())
00265 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
00266 else
00267 plainResize( sizeForClientSize( QSize( clientSize().width(), 0 ), SizemodeShaded ), ForceGeometrySet );
00268 workarea_diff_x = save_workarea_diff_x;
00269 workarea_diff_y = save_workarea_diff_y;
00270 do_show = true;
00271 }
00272 else
00273 destroyDecoration();
00274 if( check_workspace_pos )
00275 checkWorkspacePosition();
00276 --block_geometry;
00277 setGeometry( geometry(), ForceGeometrySet );
00278 if( do_show )
00279 decoration->widget()->show();
00280 updateFrameStrut();
00281 }
00282
00283 void Client::destroyDecoration()
00284 {
00285 if( decoration != NULL )
00286 {
00287 delete decoration;
00288 decoration = NULL;
00289 QPoint grav = calculateGravitation( true );
00290 border_left = border_right = border_top = border_bottom = 0;
00291 setMask( QRegion());
00292 int save_workarea_diff_x = workarea_diff_x;
00293 int save_workarea_diff_y = workarea_diff_y;
00294 if( !isShade())
00295 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
00296 else
00297 plainResize( sizeForClientSize( QSize( clientSize().width(), 0 ), SizemodeShaded ), ForceGeometrySet );
00298 move( grav );
00299 workarea_diff_x = save_workarea_diff_x;
00300 workarea_diff_y = save_workarea_diff_y;
00301 }
00302 }
00303
00304 void Client::checkBorderSizes()
00305 {
00306 if( decoration == NULL )
00307 return;
00308 int new_left, new_right, new_top, new_bottom;
00309 decoration->borders( new_left, new_right, new_top, new_bottom );
00310 if( new_left == border_left && new_right == border_right
00311 && new_top == border_top && new_bottom == border_bottom )
00312 return;
00313 ++block_geometry;
00314 move( calculateGravitation( true ));
00315 border_left = new_left;
00316 border_right = new_right;
00317 border_top = new_top;
00318 border_bottom = new_bottom;
00319 move( calculateGravitation( false ));
00320 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
00321 checkWorkspacePosition();
00322 --block_geometry;
00323 setGeometry( geometry(), ForceGeometrySet );
00324 }
00325
00326 void Client::detectNoBorder()
00327 {
00328 if( Shape::hasShape( window()))
00329 {
00330 noborder = true;
00331 return;
00332 }
00333 switch( windowType())
00334 {
00335 case NET::Desktop :
00336 case NET::Dock :
00337 case NET::TopMenu :
00338 case NET::Override :
00339 case NET::Splash :
00340 noborder = true;
00341 break;
00342 case NET::Unknown :
00343 case NET::Normal :
00344 case NET::Toolbar :
00345 case NET::Menu :
00346 case NET::Dialog :
00347 case NET::Utility :
00348 noborder = false;
00349 break;
00350 default:
00351 assert( false );
00352 }
00353 }
00354
00355 void Client::updateFrameStrut()
00356 {
00357
00358 NETStrut strut;
00359 strut.left = border_left;
00360 strut.right = border_right;
00361 strut.top = border_top;
00362 strut.bottom = border_bottom;
00363 info->setKDEFrameStrut( strut );
00364 }
00365
00366
00367
00368
00369
00370
00371 void Client::resizeDecoration( const QSize& s )
00372 {
00373 if( decoration == NULL )
00374 return;
00375 QSize oldsize = decoration->widget()->size();
00376 decoration->resize( s );
00377 if( oldsize == s )
00378 {
00379 QResizeEvent e( s, oldsize );
00380 QApplication::sendEvent( decoration->widget(), &e );
00381 }
00382 }
00383
00384 bool Client::noBorder() const
00385 {
00386 return noborder || isFullScreen() || user_noborder || motif_noborder;
00387 }
00388
00389 bool Client::userCanSetNoBorder() const
00390 {
00391 return !noborder && !isFullScreen() && !isShade();
00392 }
00393
00394 bool Client::isUserNoBorder() const
00395 {
00396 return user_noborder;
00397 }
00398
00399 void Client::setUserNoBorder( bool set )
00400 {
00401 if( !userCanSetNoBorder())
00402 return;
00403 set = rules()->checkNoBorder( set );
00404 if( user_noborder == set )
00405 return;
00406 user_noborder = set;
00407 updateDecoration( true, false );
00408 updateWindowRules();
00409 }
00410
00411 void Client::updateShape()
00412 {
00413 if ( shape() )
00414 XShapeCombineShape(qt_xdisplay(), frameId(), ShapeBounding,
00415 clientPos().x(), clientPos().y(),
00416 window(), ShapeBounding, ShapeSet);
00417 else
00418 XShapeCombineMask( qt_xdisplay(), frameId(), ShapeBounding, 0, 0,
00419 None, ShapeSet);
00420
00421 if( shape() && !noBorder())
00422 {
00423 noborder = true;
00424 updateDecoration( true );
00425 }
00426 }
00427
00428 void Client::setMask( const QRegion& reg, int mode )
00429 {
00430 _mask = reg;
00431 if( reg.isNull())
00432 XShapeCombineMask( qt_xdisplay(), frameId(), ShapeBounding, 0, 0,
00433 None, ShapeSet );
00434 else if( mode == X::Unsorted )
00435 XShapeCombineRegion( qt_xdisplay(), frameId(), ShapeBounding, 0, 0,
00436 reg.handle(), ShapeSet );
00437 else
00438 {
00439 QMemArray< QRect > rects = reg.rects();
00440 XRectangle* xrects = new XRectangle[ rects.count() ];
00441 for( unsigned int i = 0;
00442 i < rects.count();
00443 ++i )
00444 {
00445 xrects[ i ].x = rects[ i ].x();
00446 xrects[ i ].y = rects[ i ].y();
00447 xrects[ i ].width = rects[ i ].width();
00448 xrects[ i ].height = rects[ i ].height();
00449 }
00450 XShapeCombineRectangles( qt_xdisplay(), frameId(), ShapeBounding, 0, 0,
00451 xrects, rects.count(), ShapeSet, mode );
00452 delete[] xrects;
00453 }
00454 }
00455
00456 QRegion Client::mask() const
00457 {
00458 if( _mask.isEmpty())
00459 return QRegion( 0, 0, width(), height());
00460 return _mask;
00461 }
00462
00463 void Client::hideClient( bool hide )
00464 {
00465 if( hidden == hide )
00466 return;
00467 hidden = hide;
00468 info->setState( hidden ? NET::Hidden : 0, NET::Hidden );
00469 if( hidden )
00470 {
00471 setMappingState( IconicState );
00472 rawHide();
00473 setSkipTaskbar( true, false );
00474 }
00475 else
00476 {
00477 setSkipTaskbar( original_skip_taskbar, false );
00478 if( isOnCurrentDesktop())
00479 {
00480 if( isShown( false ))
00481 setMappingState( NormalState );
00482 rawShow();
00483 }
00484 }
00485 }
00486
00487
00488
00489
00490 bool Client::isMinimizable() const
00491 {
00492 if( isSpecialWindow() && !isOverride())
00493 return false;
00494 if( isTransient())
00495 {
00496 bool shown_mainwindow = false;
00497 ClientList mainclients = mainClients();
00498 for( ClientList::ConstIterator it = mainclients.begin();
00499 it != mainclients.end();
00500 ++it )
00501 {
00502 if( (*it)->isShown( true ))
00503 shown_mainwindow = true;
00504 }
00505 if( !shown_mainwindow )
00506 return true;
00507 }
00508
00509
00510
00511 if( transientFor() != NULL )
00512 return false;
00513 if( !wantsTabFocus())
00514 return false;
00515 return true;
00516 }
00517
00521 void Client::minimize( bool avoid_animation )
00522 {
00523 if ( !isMinimizable() || isMinimized())
00524 return;
00525
00526 minimized = true;
00527
00528 Notify::raise( Notify::Minimize );
00529
00530
00531 if ( mainClients().isEmpty() && isOnCurrentDesktop() && !avoid_animation )
00532 animateMinimizeOrUnminimize( true );
00533
00534 setMappingState( IconicState );
00535 info->setState( NET::Hidden, NET::Hidden );
00536 rawHide();
00537 updateAllowedActions();
00538 workspace()->updateMinimizedOfTransients( this );
00539 updateWindowRules();
00540 }
00541
00542 void Client::unminimize( bool avoid_animation )
00543 {
00544 if( !isMinimized())
00545 return;
00546
00547 Notify::raise( Notify::UnMinimize );
00548 minimized = false;
00549 info->setState( 0, NET::Hidden );
00550 if( isOnCurrentDesktop())
00551 {
00552 if( mainClients().isEmpty() && !avoid_animation )
00553 animateMinimizeOrUnminimize( FALSE );
00554 if( isShown( false ))
00555 setMappingState( NormalState );
00556 rawShow();
00557 }
00558 updateAllowedActions();
00559 workspace()->updateMinimizedOfTransients( this );
00560 updateWindowRules();
00561 }
00562
00563 extern bool blockAnimation;
00564
00565 void Client::animateMinimizeOrUnminimize( bool minimize )
00566 {
00567 if ( blockAnimation )
00568 return;
00569 if ( !options->animateMinimize )
00570 return;
00571
00572 if( decoration != NULL && decoration->animateMinimize( minimize ))
00573 return;
00574
00575
00576
00577
00578
00579 float lf,rf,tf,bf,step;
00580
00581 int speed = options->animateMinimizeSpeed;
00582 if ( speed > 10 )
00583 speed = 10;
00584 if ( speed < 0 )
00585 speed = 0;
00586
00587 step = 40. * (11 - speed );
00588
00589 NETRect r = info->iconGeometry();
00590 QRect icongeom( r.pos.x, r.pos.y, r.size.width, r.size.height );
00591 if ( !icongeom.isValid() )
00592 return;
00593
00594 QPixmap pm = animationPixmap( minimize ? width() : icongeom.width() );
00595
00596 QRect before, after;
00597 if ( minimize )
00598 {
00599 before = QRect( x(), y(), width(), pm.height() );
00600 after = QRect( icongeom.x(), icongeom.y(), icongeom.width(), pm.height() );
00601 }
00602 else
00603 {
00604 before = QRect( icongeom.x(), icongeom.y(), icongeom.width(), pm.height() );
00605 after = QRect( x(), y(), width(), pm.height() );
00606 }
00607
00608 lf = (after.left() - before.left())/step;
00609 rf = (after.right() - before.right())/step;
00610 tf = (after.top() - before.top())/step;
00611 bf = (after.bottom() - before.bottom())/step;
00612
00613 grabXServer();
00614
00615 QRect area = before;
00616 QRect area2;
00617 QPixmap pm2;
00618
00619 QTime t;
00620 t.start();
00621 float diff;
00622
00623 QPainter p ( workspace()->desktopWidget() );
00624 bool need_to_clear = FALSE;
00625 QPixmap pm3;
00626 do
00627 {
00628 if (area2 != area)
00629 {
00630 pm = animationPixmap( area.width() );
00631 pm2 = QPixmap::grabWindow( qt_xrootwin(), area.x(), area.y(), area.width(), area.height() );
00632 p.drawPixmap( area.x(), area.y(), pm );
00633 if ( need_to_clear )
00634 {
00635 p.drawPixmap( area2.x(), area2.y(), pm3 );
00636 need_to_clear = FALSE;
00637 }
00638 area2 = area;
00639 }
00640 XFlush(qt_xdisplay());
00641 XSync( qt_xdisplay(), FALSE );
00642 diff = t.elapsed();
00643 if (diff > step)
00644 diff = step;
00645 area.setLeft(before.left() + int(diff*lf));
00646 area.setRight(before.right() + int(diff*rf));
00647 area.setTop(before.top() + int(diff*tf));
00648 area.setBottom(before.bottom() + int(diff*bf));
00649 if (area2 != area )
00650 {
00651 if ( area2.intersects( area ) )
00652 p.drawPixmap( area2.x(), area2.y(), pm2 );
00653 else
00654 {
00655 pm3 = pm2;
00656 need_to_clear = TRUE;
00657 }
00658 }
00659 } while ( t.elapsed() < step);
00660 if (area2 == area || need_to_clear )
00661 p.drawPixmap( area2.x(), area2.y(), pm2 );
00662
00663 p.end();
00664 ungrabXServer();
00665 }
00666
00667
00671 QPixmap Client::animationPixmap( int w )
00672 {
00673 QFont font = options->font(isActive());
00674 QFontMetrics fm( font );
00675 QPixmap pm( w, fm.lineSpacing() );
00676 pm.fill( options->color(Options::ColorTitleBar, isActive() || isMinimized() ) );
00677 QPainter p( &pm );
00678 p.setPen(options->color(Options::ColorFont, isActive() || isMinimized() ));
00679 p.setFont(options->font(isActive()));
00680 p.drawText( pm.rect(), AlignLeft|AlignVCenter|SingleLine, caption() );
00681 return pm;
00682 }
00683
00684
00685 bool Client::isShadeable() const
00686 {
00687 return !isSpecialWindow() && !noBorder();
00688 }
00689
00690 void Client::setShade( ShadeMode mode )
00691 {
00692 if( !isShadeable())
00693 return;
00694 mode = rules()->checkShade( mode );
00695 if( shade_mode == mode )
00696 return;
00697 bool was_shade = isShade();
00698 ShadeMode was_shade_mode = shade_mode;
00699 shade_mode = mode;
00700 if( was_shade == isShade())
00701 return;
00702
00703 if( shade_mode == ShadeNormal )
00704 {
00705 if ( isShown( true ) && isOnCurrentDesktop())
00706 Notify::raise( Notify::ShadeUp );
00707 }
00708 else if( shade_mode == ShadeNone )
00709 {
00710 if( isShown( true ) && isOnCurrentDesktop())
00711 Notify::raise( Notify::ShadeDown );
00712 }
00713
00714 assert( decoration != NULL );
00715 ++block_geometry;
00716
00717 decoration->borders( border_left, border_right, border_top, border_bottom );
00718
00719 int as = options->animateShade? 10 : 1;
00720
00721 if ( isShade())
00722 {
00723 int h = height();
00724 shade_geometry_change = true;
00725 QSize s( sizeForClientSize( QSize( clientSize().width(), 0), SizemodeShaded ) );
00726 XSelectInput( qt_xdisplay(), wrapper, ClientWinMask );
00727 XUnmapWindow( qt_xdisplay(), wrapper );
00728 XUnmapWindow( qt_xdisplay(), client );
00729 XSelectInput( qt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
00730
00731
00732
00733 int step = QMAX( 4, QABS( h - s.height() ) / as )+1;
00734 do
00735 {
00736 h -= step;
00737 XResizeWindow( qt_xdisplay(), frameId(), s.width(), h );
00738 resizeDecoration( QSize( s.width(), h ));
00739 QApplication::syncX();
00740 } while ( h > s.height() + step );
00741
00742
00743 shade_geometry_change = false;
00744 plainResize( s );
00745 if( isActive())
00746 {
00747 if( was_shade_mode == ShadeHover )
00748 workspace()->activateNextClient( this );
00749 else
00750 workspace()->focusToNull();
00751 }
00752 }
00753 else
00754 {
00755 int h = height();
00756 shade_geometry_change = true;
00757 QSize s( sizeForClientSize( clientSize(), SizemodeShaded ));
00758
00759
00760 int step = QMAX( 4, QABS( h - s.height() ) / as )+1;
00761 do
00762 {
00763 h += step;
00764 XResizeWindow( qt_xdisplay(), frameId(), s.width(), h );
00765 resizeDecoration( QSize( s.width(), h ));
00766
00767
00768
00769 QApplication::syncX();
00770 } while ( h < s.height() - step );
00771
00772
00773 shade_geometry_change = false;
00774 plainResize( s );
00775 if( shade_mode == ShadeHover || shade_mode == ShadeActivated )
00776 setActive( TRUE );
00777 XMapWindow( qt_xdisplay(), wrapperId());
00778 XMapWindow( qt_xdisplay(), window());
00779 if ( isActive() )
00780 workspace()->requestFocus( this );
00781 }
00782 --block_geometry;
00783 setGeometry( geometry(), ForceGeometrySet );
00784 info->setState( isShade() ? NET::Shaded : 0, NET::Shaded );
00785 info->setState( isShown( false ) ? 0 : NET::Hidden, NET::Hidden );
00786 setMappingState( isShown( false ) && isOnCurrentDesktop() ? NormalState : IconicState );
00787 updateAllowedActions();
00788 workspace()->updateMinimizedOfTransients( this );
00789 decoration->shadeChange();
00790 updateWindowRules();
00791 }
00792
00793 void Client::shadeHover()
00794 {
00795 setShade( ShadeHover );
00796 delete shadeHoverTimer;
00797 shadeHoverTimer = 0;
00798 }
00799
00800 void Client::toggleShade()
00801 {
00802
00803 setShade( shade_mode == ShadeNone ? ShadeNormal : ShadeNone );
00804 }
00805
00806 void Client::virtualDesktopChange()
00807 {
00808 if( hidden || minimized )
00809 return;
00810
00811 if( isOnCurrentDesktop())
00812 {
00813 if( !isShade())
00814 setMappingState( NormalState );
00815 rawShow();
00816 }
00817 else
00818 {
00819 if( !isShade())
00820 setMappingState( IconicState );
00821 rawHide();
00822 }
00823 }
00824
00829 void Client::setMappingState(int s)
00830 {
00831 assert( client != None );
00832 if( mapping_state == s )
00833 return;
00834 bool was_unmanaged = ( mapping_state == WithdrawnState );
00835 mapping_state = s;
00836 if( mapping_state == WithdrawnState )
00837 {
00838 XDeleteProperty( qt_xdisplay(), window(), qt_wm_state );
00839 return;
00840 }
00841 assert( s == NormalState || s == IconicState );
00842
00843 unsigned long data[2];
00844 data[0] = (unsigned long) s;
00845 data[1] = (unsigned long) None;
00846 XChangeProperty(qt_xdisplay(), window(), qt_wm_state, qt_wm_state, 32,
00847 PropModeReplace, (unsigned char *)data, 2);
00848
00849 if( was_unmanaged )
00850 {
00851 assert( block_geometry == 1 );
00852 --block_geometry;
00853 setGeometry( frame_geometry, ForceGeometrySet );
00854 }
00855 }
00856
00861 void Client::rawShow()
00862 {
00863 if( decoration != NULL )
00864 decoration->widget()->show();
00865 XMapWindow( qt_xdisplay(), frame );
00866 if( !isShade())
00867 {
00868 XMapWindow( qt_xdisplay(), wrapper );
00869 XMapWindow( qt_xdisplay(), client );
00870 }
00871 }
00872
00878 void Client::rawHide()
00879 {
00880
00881
00882
00883
00884
00885
00886 XSelectInput( qt_xdisplay(), wrapper, ClientWinMask );
00887 XUnmapWindow( qt_xdisplay(), frame );
00888 XUnmapWindow( qt_xdisplay(), wrapper );
00889 XUnmapWindow( qt_xdisplay(), client );
00890 XSelectInput( qt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
00891 if( decoration != NULL )
00892 decoration->widget()->hide();
00893 workspace()->clientHidden( this );
00894 }
00895
00896 void Client::sendClientMessage(Window w, Atom a, Atom protocol, long data1, long data2, long data3)
00897 {
00898 XEvent ev;
00899 long mask;
00900
00901 memset(&ev, 0, sizeof(ev));
00902 ev.xclient.type = ClientMessage;
00903 ev.xclient.window = w;
00904 ev.xclient.message_type = a;
00905 ev.xclient.format = 32;
00906 ev.xclient.data.l[0] = protocol;
00907 ev.xclient.data.l[1] = qt_x_time;
00908 ev.xclient.data.l[2] = data1;
00909 ev.xclient.data.l[3] = data2;
00910 ev.xclient.data.l[4] = data3;
00911 mask = 0L;
00912 if (w == qt_xrootwin())
00913 mask = SubstructureRedirectMask;
00914 XSendEvent(qt_xdisplay(), w, False, mask, &ev);
00915 }
00916
00917
00918
00919
00920 bool Client::isCloseable() const
00921 {
00922 return rules()->checkCloseable( motif_may_close && ( !isSpecialWindow() || isOverride()));
00923 }
00924
00929 void Client::closeWindow()
00930 {
00931 if( !isCloseable())
00932 return;
00933
00934
00935
00936
00937 group()->updateUserTime();
00938 if ( Pdeletewindow )
00939 {
00940 Notify::raise( Notify::Close );
00941 sendClientMessage( window(), atoms->wm_protocols, atoms->wm_delete_window);
00942 pingWindow();
00943 }
00944 else
00945 {
00946
00947
00948 killWindow();
00949 }
00950 }
00951
00952
00956 void Client::killWindow()
00957 {
00958 kdDebug( 1212 ) << "Client::killWindow():" << caption() << endl;
00959
00960
00961 Notify::raise( Notify::Close );
00962
00963 if( isDialog())
00964 Notify::raise( Notify::TransDelete );
00965 if( isNormalWindow())
00966 Notify::raise( Notify::Delete );
00967 killProcess( false );
00968
00969 XKillClient(qt_xdisplay(), window() );
00970 destroyClient();
00971 }
00972
00973
00974
00975
00976 void Client::pingWindow()
00977 {
00978 if( !Pping )
00979 return;
00980 if( options->killPingTimeout == 0 )
00981 return;
00982 if( ping_timer != NULL )
00983 return;
00984 ping_timer = new QTimer( this );
00985 connect( ping_timer, SIGNAL( timeout()), SLOT( pingTimeout()));
00986 ping_timer->start( options->killPingTimeout, true );
00987 ping_timestamp = qt_x_time;
00988 workspace()->sendPingToWindow( window(), ping_timestamp );
00989 }
00990
00991 void Client::gotPing( Time timestamp )
00992 {
00993 if( timestamp != ping_timestamp )
00994 return;
00995 delete ping_timer;
00996 ping_timer = NULL;
00997 if( process_killer != NULL )
00998 {
00999 process_killer->kill();
01000 delete process_killer;
01001 process_killer = NULL;
01002 }
01003 }
01004
01005 void Client::pingTimeout()
01006 {
01007 kdDebug( 1212 ) << "Ping timeout:" << caption() << endl;
01008 delete ping_timer;
01009 ping_timer = NULL;
01010 killProcess( true, ping_timestamp );
01011 }
01012
01013 void Client::killProcess( bool ask, Time timestamp )
01014 {
01015 if( process_killer != NULL )
01016 return;
01017 Q_ASSERT( !ask || timestamp != CurrentTime );
01018 QCString machine = wmClientMachine( true );
01019 pid_t pid = info->pid();
01020 if( pid <= 0 || machine.isEmpty())
01021 return;
01022 kdDebug( 1212 ) << "Kill process:" << pid << "(" << machine << ")" << endl;
01023 if( !ask )
01024 {
01025 if( machine != "localhost" )
01026 {
01027 KProcess proc;
01028 proc << "xon" << machine << "kill" << pid;
01029 proc.start( KProcess::DontCare );
01030 }
01031 else
01032 ::kill( pid, SIGTERM );
01033 }
01034 else
01035 {
01036 process_killer = new KProcess( this );
01037 *process_killer << KStandardDirs::findExe( "kwin_killer_helper" )
01038 << "--pid" << QCString().setNum( pid ) << "--hostname" << machine
01039 << "--windowname" << caption().utf8()
01040 << "--applicationname" << resourceClass()
01041 << "--wid" << QCString().setNum( window())
01042 << "--timestamp" << QCString().setNum( timestamp );
01043 connect( process_killer, SIGNAL( processExited( KProcess* )),
01044 SLOT( processKillerExited()));
01045 if( !process_killer->start( KProcess::NotifyOnExit ))
01046 {
01047 delete process_killer;
01048 process_killer = NULL;
01049 return;
01050 }
01051 }
01052 }
01053
01054 void Client::processKillerExited()
01055 {
01056 kdDebug( 1212 ) << "Killer exited" << endl;
01057 delete process_killer;
01058 process_killer = NULL;
01059 }
01060
01061 void Client::setSkipTaskbar( bool b, bool from_outside )
01062 {
01063 if( from_outside )
01064 {
01065 b = rules()->checkSkipTaskbar( b );
01066 original_skip_taskbar = b;
01067 }
01068 if ( b == skipTaskbar() )
01069 return;
01070 skip_taskbar = b;
01071 info->setState( b?NET::SkipTaskbar:0, NET::SkipTaskbar );
01072 updateWindowRules();
01073 }
01074
01075 void Client::setSkipPager( bool b )
01076 {
01077 b = rules()->checkSkipPager( b );
01078 if ( b == skipPager() )
01079 return;
01080 skip_pager = b;
01081 info->setState( b?NET::SkipPager:0, NET::SkipPager );
01082 updateWindowRules();
01083 }
01084
01085 void Client::setModal( bool m )
01086 {
01087 if( modal == m )
01088 return;
01089 modal = m;
01090 if( !modal )
01091 return;
01092
01093
01094 }
01095
01096 void Client::setDesktop( int desktop )
01097 {
01098 if( desktop != NET::OnAllDesktops )
01099 desktop = KMAX( 1, KMIN( workspace()->numberOfDesktops(), desktop ));
01100 desktop = rules()->checkDesktop( desktop );
01101 if( desk == desktop )
01102 return;
01103 int was_desk = desk;
01104 desk = desktop;
01105 info->setDesktop( desktop );
01106 if(( was_desk == NET::OnAllDesktops ) != ( desktop == NET::OnAllDesktops ))
01107 {
01108 if ( isShown( true ))
01109 Notify::raise( isOnAllDesktops() ? Notify::OnAllDesktops : Notify::NotOnAllDesktops );
01110 workspace()->updateOnAllDesktopsOfTransients( this );
01111 }
01112 if( decoration != NULL )
01113 decoration->desktopChange();
01114 virtualDesktopChange();
01115 updateWindowRules();
01116 }
01117
01118 void Client::setOnAllDesktops( bool b )
01119 {
01120 if(( b && isOnAllDesktops())
01121 || ( !b && !isOnAllDesktops()))
01122 return;
01123 if( b )
01124 setDesktop( NET::OnAllDesktops );
01125 else
01126 setDesktop( workspace()->currentDesktop());
01127 }
01128
01129 bool Client::isOnCurrentDesktop() const
01130 {
01131 return isOnDesktop( workspace()->currentDesktop());
01132 }
01133
01134
01135 void Client::takeActivity( int flags, bool handled, allowed_t )
01136 {
01137 if( !handled || !Ptakeactivity )
01138 {
01139 if( flags & ActivityFocus )
01140 takeFocus( Allowed );
01141 if( flags & ActivityRaise )
01142 workspace()->raiseClient( this );
01143 return;
01144 }
01145
01146 #ifndef NDEBUG
01147 static Time previous_activity_timestamp;
01148 static Client* previous_client;
01149 if( previous_activity_timestamp == qt_x_time && previous_client != this )
01150 {
01151 kdWarning( 1212 ) << "Repeated use of the same X timestamp for activity" << endl;
01152 kdDebug( 1212 ) << kdBacktrace() << endl;
01153 }
01154 previous_activity_timestamp = qt_x_time;
01155 previous_client = this;
01156 #endif
01157 workspace()->sendTakeActivity( this, qt_x_time, flags );
01158 }
01159
01160
01161 void Client::takeFocus( allowed_t )
01162 {
01163 #ifndef NDEBUG
01164 static Time previous_focus_timestamp;
01165 static Client* previous_client;
01166 if( previous_focus_timestamp == qt_x_time && previous_client != this )
01167 {
01168 kdWarning( 1212 ) << "Repeated use of the same X timestamp for focus" << endl;
01169 kdDebug( 1212 ) << kdBacktrace() << endl;
01170 }
01171 previous_focus_timestamp = qt_x_time;
01172 previous_client = this;
01173 #endif
01174 if ( rules()->checkAcceptFocus( input ))
01175 {
01176 XSetInputFocus( qt_xdisplay(), window(), RevertToPointerRoot, qt_x_time );
01177 }
01178 if ( Ptakefocus )
01179 sendClientMessage(window(), atoms->wm_protocols, atoms->wm_take_focus);
01180 workspace()->setShouldGetFocus( this );
01181 }
01182
01190 bool Client::providesContextHelp() const
01191 {
01192 return Pcontexthelp;
01193 }
01194
01195
01202 void Client::showContextHelp()
01203 {
01204 if ( Pcontexthelp )
01205 {
01206 sendClientMessage(window(), atoms->wm_protocols, atoms->net_wm_context_help);
01207 QWhatsThis::enterWhatsThisMode();
01208 }
01209 }
01210
01211
01216 void Client::fetchName()
01217 {
01218 setCaption( readName());
01219 }
01220
01221 QString Client::readName() const
01222 {
01223 if ( info->name() && info->name()[ 0 ] != '\0' )
01224 return QString::fromUtf8( info->name() );
01225 else
01226 return KWin::readNameProperty( window(), XA_WM_NAME );
01227 }
01228
01229 KWIN_COMPARE_PREDICATE( FetchNameInternalPredicate, const Client*, (!cl->isSpecialWindow() || cl->isToolbar()) && cl != value && cl->caption() == value->caption());
01230
01231 void Client::setCaption( const QString& s, bool force )
01232 {
01233 if ( s != cap_normal || force )
01234 {
01235 bool reset_name = force;
01236 for( unsigned int i = 0;
01237 i < s.length();
01238 ++i )
01239 if( !s[ i ].isPrint())
01240 s[ i ] = ' ';
01241 cap_normal = s;
01242 bool was_suffix = ( !cap_suffix.isEmpty());
01243 cap_suffix = QString::null;
01244 if ( ( !isSpecialWindow() || isToolbar()) && workspace()->findClient( FetchNameInternalPredicate( this )))
01245 {
01246 int i = 2;
01247 do
01248 {
01249 cap_suffix = " <" + QString::number(i) + ">";
01250 i++;
01251 } while ( workspace()->findClient( FetchNameInternalPredicate( this )));
01252 info->setVisibleName( caption().utf8() );
01253 reset_name = false;
01254 }
01255 if(( was_suffix && cap_suffix.isEmpty()
01256 || reset_name ))
01257 {
01258 info->setVisibleName( "" );
01259 info->setVisibleIconName( "" );
01260 }
01261 else if( !cap_suffix.isEmpty() && !cap_iconic.isEmpty())
01262 info->setVisibleIconName( ( cap_iconic + cap_suffix ).utf8() );
01263
01264 if( isManaged() && decoration != NULL )
01265 decoration->captionChange();
01266 }
01267 }
01268
01269 void Client::fetchIconicName()
01270 {
01271 QString s;
01272 if ( info->iconName() && info->iconName()[ 0 ] != '\0' )
01273 s = QString::fromUtf8( info->iconName() );
01274 else
01275 s = KWin::readNameProperty( window(), XA_WM_ICON_NAME );
01276 if ( s != cap_iconic )
01277 {
01278 bool was_set = !cap_iconic.isEmpty();
01279 cap_iconic = s;
01280 if( !cap_suffix.isEmpty())
01281 {
01282 if( !cap_iconic.isEmpty())
01283 info->setVisibleIconName( ( s + cap_suffix ).utf8() );
01284 else if( was_set )
01285 info->setVisibleIconName( "" );
01286 }
01287 }
01288 }
01289
01292 QString Client::caption( bool full ) const
01293 {
01294 return full ? cap_normal + cap_suffix : cap_normal;
01295 }
01296
01297 void Client::getWMHints()
01298 {
01299 XWMHints *hints = XGetWMHints(qt_xdisplay(), window() );
01300 input = true;
01301 window_group = None;
01302 urgency = false;
01303 if ( hints )
01304 {
01305 if( hints->flags & InputHint )
01306 input = hints->input;
01307 if( hints->flags & WindowGroupHint )
01308 window_group = hints->window_group;
01309 urgency = ( hints->flags & UrgencyHint ) ? true : false;
01310 XFree( (char*)hints );
01311 }
01312 checkGroup();
01313 updateUrgency();
01314 updateAllowedActions();
01315 }
01316
01317 void Client::getMotifHints()
01318 {
01319 bool mnoborder, mresize, mmove, mminimize, mmaximize, mclose;
01320 Motif::readFlags( client, mnoborder, mresize, mmove, mminimize, mmaximize, mclose );
01321 motif_noborder = mnoborder;
01322 if( !hasNETSupport())
01323 {
01324 motif_may_resize = mresize;
01325 motif_may_move = mmove;
01326 }
01327
01328
01329 motif_may_close = mclose;
01330 if( isManaged())
01331 updateDecoration( true );
01332 }
01333
01334 void Client::readIcons( Window win, QPixmap* icon, QPixmap* miniicon )
01335 {
01336
01337 if( icon != NULL )
01338 *icon = KWin::icon( win, 32, 32, TRUE, KWin::NETWM | KWin::WMHints );
01339 if( miniicon != NULL )
01340 if( icon == NULL || !icon->isNull())
01341 *miniicon = KWin::icon( win, 16, 16, TRUE, KWin::NETWM | KWin::WMHints );
01342 else
01343 *miniicon = QPixmap();
01344 }
01345
01346 void Client::getIcons()
01347 {
01348
01349 readIcons( window(), &icon_pix, &miniicon_pix );
01350 if( icon_pix.isNull())
01351 {
01352 icon_pix = group()->icon();
01353 miniicon_pix = group()->miniIcon();
01354 }
01355 if( icon_pix.isNull() && isTransient())
01356 {
01357 ClientList mainclients = mainClients();
01358 for( ClientList::ConstIterator it = mainclients.begin();
01359 it != mainclients.end() && icon_pix.isNull();
01360 ++it )
01361 {
01362 icon_pix = (*it)->icon();
01363 miniicon_pix = (*it)->miniIcon();
01364 }
01365 }
01366 if( icon_pix.isNull())
01367 {
01368 icon_pix = KWin::icon( window(), 32, 32, TRUE, KWin::ClassHint | KWin::XApp );
01369 miniicon_pix = KWin::icon( window(), 16, 16, TRUE, KWin::ClassHint | KWin::XApp );
01370 }
01371 if( isManaged() && decoration != NULL )
01372 decoration->iconChange();
01373 }
01374
01375 void Client::getWindowProtocols()
01376 {
01377 Atom *p;
01378 int i,n;
01379
01380 Pdeletewindow = 0;
01381 Ptakefocus = 0;
01382 Ptakeactivity = 0;
01383 Pcontexthelp = 0;
01384 Pping = 0;
01385
01386 if (XGetWMProtocols(qt_xdisplay(), window(), &p, &n))
01387 {
01388 for (i = 0; i < n; i++)
01389 if (p[i] == atoms->wm_delete_window)
01390 Pdeletewindow = 1;
01391 else if (p[i] == atoms->wm_take_focus)
01392 Ptakefocus = 1;
01393 else if (p[i] == atoms->net_wm_take_activity)
01394 Ptakeactivity = 1;
01395 else if (p[i] == atoms->net_wm_context_help)
01396 Pcontexthelp = 1;
01397 else if (p[i] == atoms->net_wm_ping)
01398 Pping = 1;
01399 if (n>0)
01400 XFree(p);
01401 }
01402 }
01403
01404 static int nullErrorHandler(Display *, XErrorEvent *)
01405 {
01406 return 0;
01407 }
01408
01412 QCString Client::staticWindowRole(WId w)
01413 {
01414 return getStringProperty(w, qt_window_role).lower();
01415 }
01416
01420 QCString Client::staticSessionId(WId w)
01421 {
01422 return getStringProperty(w, qt_sm_client_id);
01423 }
01424
01428 QCString Client::staticWmCommand(WId w)
01429 {
01430 return getStringProperty(w, XA_WM_COMMAND, ' ');
01431 }
01432
01436 QCString Client::staticWmClientMachine(WId w)
01437 {
01438 QCString result = getStringProperty(w, XA_WM_CLIENT_MACHINE);
01439 if (result.isEmpty())
01440 result = "localhost";
01441 return result;
01442 }
01443
01447 Window Client::staticWmClientLeader(WId w)
01448 {
01449 Atom type;
01450 int format, status;
01451 unsigned long nitems = 0;
01452 unsigned long extra = 0;
01453 unsigned char *data = 0;
01454 Window result = w;
01455 XErrorHandler oldHandler = XSetErrorHandler(nullErrorHandler);
01456 status = XGetWindowProperty( qt_xdisplay(), w, atoms->wm_client_leader, 0, 10000,
01457 FALSE, XA_WINDOW, &type, &format,
01458 &nitems, &extra, &data );
01459 XSetErrorHandler(oldHandler);
01460 if (status == Success )
01461 {
01462 if (data && nitems > 0)
01463 result = *((Window*) data);
01464 XFree(data);
01465 }
01466 return result;
01467 }
01468
01469
01470 void Client::getWmClientLeader()
01471 {
01472 wmClientLeaderWin = staticWmClientLeader(window());
01473 }
01474
01479 QCString Client::sessionId()
01480 {
01481 QCString result = staticSessionId(window());
01482 if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
01483 result = staticSessionId(wmClientLeaderWin);
01484 return result;
01485 }
01486
01491 QCString Client::wmCommand()
01492 {
01493 QCString result = staticWmCommand(window());
01494 if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
01495 result = staticWmCommand(wmClientLeaderWin);
01496 return result;
01497 }
01498
01503 QCString Client::wmClientMachine( bool use_localhost ) const
01504 {
01505 QCString result = staticWmClientMachine(window());
01506 if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
01507 result = staticWmClientMachine(wmClientLeaderWin);
01508 if( use_localhost )
01509 {
01510 if( result != "localhost" && isLocalMachine( result ))
01511 result = "localhost";
01512 }
01513 return result;
01514 }
01515
01520 Window Client::wmClientLeader() const
01521 {
01522 if (wmClientLeaderWin)
01523 return wmClientLeaderWin;
01524 return window();
01525 }
01526
01527 bool Client::wantsTabFocus() const
01528 {
01529 return ( isNormalWindow() || isDialog() || isOverride())
01530 && wantsInput() && !skip_taskbar;
01531 }
01532
01533
01534 bool Client::wantsInput() const
01535 {
01536 return rules()->checkAcceptFocus( input || Ptakefocus );
01537 }
01538
01539 bool Client::isDesktop() const
01540 {
01541 return windowType() == NET::Desktop;
01542 }
01543
01544 bool Client::isDock() const
01545 {
01546 return windowType() == NET::Dock;
01547 }
01548
01549 bool Client::isTopMenu() const
01550 {
01551 return windowType() == NET::TopMenu;
01552 }
01553
01554
01555 bool Client::isMenu() const
01556 {
01557 return windowType() == NET::Menu && !isTopMenu();
01558 }
01559
01560 bool Client::isToolbar() const
01561 {
01562 return windowType() == NET::Toolbar;
01563 }
01564
01565 bool Client::isOverride() const
01566 {
01567 return windowType() == NET::Override;
01568 }
01569
01570 bool Client::isSplash() const
01571 {
01572 return windowType() == NET::Splash;
01573 }
01574
01575 bool Client::isUtility() const
01576 {
01577 return windowType() == NET::Utility;
01578 }
01579
01580 bool Client::isDialog() const
01581 {
01582 return windowType() == NET::Dialog;
01583 }
01584
01585 bool Client::isNormalWindow() const
01586 {
01587 return windowType() == NET::Normal;
01588 }
01589
01590 bool Client::isSpecialWindow() const
01591 {
01592 return isDesktop() || isDock() || isSplash() || isTopMenu()
01593 || ( isOverride() && !isFullScreen())
01594 || isToolbar();
01595 }
01596
01597 NET::WindowType Client::windowType( bool direct, int supported_types ) const
01598 {
01599 NET::WindowType wt = info->windowType( supported_types );
01600 if( direct )
01601 return wt;
01602 NET::WindowType wt2 = rules()->checkType( wt );
01603 if( wt != wt2 )
01604 {
01605 wt = wt2;
01606 info->setWindowType( wt );
01607 }
01608
01609 if( wt == NET::Menu )
01610 {
01611
01612
01613
01614 if( x() == 0 && y() < 0 && y() > -10 && height() < 100
01615 && abs( width() - workspace()->clientArea( FullArea, this ).width()) < 10 )
01616 wt = NET::TopMenu;
01617 }
01618
01619 const char* const oo_prefix = "openoffice.org";
01620
01621 if( qstrncmp( resourceClass(), oo_prefix, strlen( oo_prefix )) == 0 && wt == NET::Dialog )
01622 wt = NET::Normal;
01623 if( wt == NET::Unknown )
01624 wt = isTransient() ? NET::Dialog : NET::Normal;
01625 return wt;
01626 }
01627
01632 void Client::setCursor( Position m )
01633 {
01634 if( !isResizable() || isShade())
01635 {
01636 m = PositionCenter;
01637 }
01638 switch ( m )
01639 {
01640 case PositionTopLeft:
01641 case PositionBottomRight:
01642 setCursor( sizeFDiagCursor );
01643 break;
01644 case PositionBottomLeft:
01645 case PositionTopRight:
01646 setCursor( sizeBDiagCursor );
01647 break;
01648 case PositionTop:
01649 case PositionBottom:
01650 setCursor( sizeVerCursor );
01651 break;
01652 case PositionLeft:
01653 case PositionRight:
01654 setCursor( sizeHorCursor );
01655 break;
01656 default:
01657 if( buttonDown && isMovable())
01658 setCursor( sizeAllCursor );
01659 else
01660 setCursor( arrowCursor );
01661 break;
01662 }
01663 }
01664
01665
01666 void Client::setCursor( const QCursor& c )
01667 {
01668 if( c.handle() == cursor.handle())
01669 return;
01670 cursor = c;
01671 if( decoration != NULL )
01672 decoration->widget()->setCursor( cursor );
01673 XDefineCursor( qt_xdisplay(), frameId(), cursor.handle());
01674 }
01675
01676 Client::Position Client::mousePosition( const QPoint& p ) const
01677 {
01678 if( decoration != NULL )
01679 return decoration->mousePosition( p );
01680 return PositionCenter;
01681 }
01682
01683 void Client::updateAllowedActions( bool force )
01684 {
01685 if( !isManaged() && !force )
01686 return;
01687 unsigned long old_allowed_actions = allowed_actions;
01688 allowed_actions = 0;
01689 if( isMovable())
01690 allowed_actions |= NET::ActionMove;
01691 if( isResizable())
01692 allowed_actions |= NET::ActionResize;
01693 if( isMinimizable())
01694 allowed_actions |= NET::ActionMinimize;
01695 if( isShadeable())
01696 allowed_actions |= NET::ActionShade;
01697
01698 if( isMaximizable())
01699 allowed_actions |= NET::ActionMax;
01700 if( userCanSetFullScreen())
01701 allowed_actions |= NET::ActionFullScreen;
01702 allowed_actions |= NET::ActionChangeDesktop;
01703 if( isCloseable())
01704 allowed_actions |= NET::ActionClose;
01705 if( old_allowed_actions == allowed_actions )
01706 return;
01707
01708 info->setAllowedActions( allowed_actions );
01709
01710 }
01711
01712 void Client::autoRaise()
01713 {
01714 workspace()->raiseClient( this );
01715 cancelAutoRaise();
01716 }
01717
01718 void Client::cancelAutoRaise()
01719 {
01720 delete autoRaiseTimer;
01721 autoRaiseTimer = 0;
01722 }
01723
01724 #ifndef NDEBUG
01725 kdbgstream& operator<<( kdbgstream& stream, const Client* cl )
01726 {
01727 if( cl == NULL )
01728 return stream << "\'NULL_CLIENT\'";
01729 return stream << "\'ID:" << cl->window() << ";WMCLASS:" << cl->resourceClass() << ":" << cl->resourceName() << ";Caption:" << cl->caption() << "\'";
01730 }
01731 kdbgstream& operator<<( kdbgstream& stream, const ClientList& list )
01732 {
01733 stream << "LIST:(";
01734 bool first = true;
01735 for( ClientList::ConstIterator it = list.begin();
01736 it != list.end();
01737 ++it )
01738 {
01739 if( !first )
01740 stream << ":";
01741 first = false;
01742 stream << *it;
01743 }
01744 stream << ")";
01745 return stream;
01746 }
01747 kdbgstream& operator<<( kdbgstream& stream, const ConstClientList& list )
01748 {
01749 stream << "LIST:(";
01750 bool first = true;
01751 for( ConstClientList::ConstIterator it = list.begin();
01752 it != list.end();
01753 ++it )
01754 {
01755 if( !first )
01756 stream << ":";
01757 first = false;
01758 stream << *it;
01759 }
01760 stream << ")";
01761 return stream;
01762 }
01763 #endif
01764
01765 QPixmap * kwin_get_menu_pix_hack()
01766 {
01767 static QPixmap p;
01768 if ( p.isNull() )
01769 p = SmallIcon( "bx2" );
01770 return &p;
01771 }
01772
01773 }
01774
01775 #include "client.moc"