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