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