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