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