00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
#include "client.h"
00019
00020
#include <kstartupinfo.h>
00021
#include <kglobal.h>
00022
#include <X11/extensions/shape.h>
00023
00024
#include "notifications.h"
00025
#include "rules.h"
00026
00027
extern Time qt_x_time;
00028
00029
namespace KWinInternal
00030 {
00031
00037 bool Client::manage( Window w,
bool isMapped )
00038 {
00039 XWindowAttributes attr;
00040
if( !XGetWindowAttributes(qt_xdisplay(), w, &attr))
00041
return false;
00042
00043 grabXServer();
00044
00045
00046 block_geometry = 1;
00047
00048 embedClient( w, attr );
00049
00050
00051
00052
bool init_minimize =
false;
00053 XWMHints * hints = XGetWMHints(qt_xdisplay(), w );
00054
if (hints && (hints->flags & StateHint) && hints->initial_state == IconicState)
00055 init_minimize =
true;
00056
if (hints)
00057 XFree(hints);
00058
if( isMapped )
00059 init_minimize =
false;
00060
00061
unsigned long properties[ 2 ];
00062 properties[ WinInfo::PROTOCOLS ] =
00063 NET::WMDesktop |
00064 NET::WMState |
00065 NET::WMWindowType |
00066 NET::WMStrut |
00067 NET::WMName |
00068 NET::WMIconGeometry |
00069 NET::WMIcon |
00070 NET::WMPid |
00071 NET::WMIconName |
00072 0;
00073 properties[ WinInfo::PROTOCOLS2 ] =
00074 NET::WM2UserTime |
00075 NET::WM2StartupId |
00076 NET::WM2ExtendedStrut |
00077 0;
00078
00079 info =
new WinInfo(
this, qt_xdisplay(), client, qt_xrootwin(), properties, 2 );
00080
00081 cmap = attr.colormap;
00082
00083 XClassHint classHint;
00084
if ( XGetClassHint( qt_xdisplay(), client, &classHint ) )
00085 {
00086
00087
00088 resource_name = QCString( classHint.res_name ).lower();
00089 resource_class = QCString( classHint.res_class ).lower();
00090 XFree( classHint.res_name );
00091 XFree( classHint.res_class );
00092 }
00093 ignore_focus_stealing = options->checkIgnoreFocusStealing(
this );
00094
00095 window_role =
staticWindowRole( w );
00096
00097
00098
00099 cap_normal = readName();
00100 setupWindowRules(
false );
00101 setCaption( cap_normal,
true );
00102
00103 detectNoBorder();
00104 fetchIconicName();
00105 getWMHints();
00106 getWmClientLeader();
00107 modal = ( info->state() & NET::Modal ) != 0;
00108 readTransient();
00109 getIcons();
00110 getWindowProtocols();
00111 getWmNormalHints();
00112 getMotifHints();
00113
00114
00115
00116 original_skip_taskbar = skip_taskbar = ( info->state() & NET::SkipTaskbar) != 0;
00117 skip_pager = ( info->state() & NET::SkipPager) != 0;
00118
00119 KStartupInfoId asn_id;
00120 KStartupInfoData asn_data;
00121
bool asn_valid = workspace()->checkStartupNotification( window(), asn_id, asn_data );
00122
00123 workspace()->updateClientLayer(
this );
00124
00125 SessionInfo* session = workspace()->takeSessionInfo(
this );
00126
00127
if ( session )
00128 {
00129
if ( session->minimized )
00130 init_minimize =
true;
00131
if( session->userNoBorder )
00132 setUserNoBorder(
true );
00133 }
00134
00135 init_minimize = rules()->checkMinimize( init_minimize, !isMapped );
00136
if( rules()->checkNoBorder(
false, !isMapped ))
00137 setUserNoBorder(
true );
00138
00139
00140
if ( info->desktop() )
00141 desk = info->desktop();
00142
else if( asn_valid && asn_data.desktop() != 0 )
00143 desk = asn_data.desktop();
00144
if ( session )
00145 {
00146 desk = session->desktop;
00147
if( session->onAllDesktops )
00148 desk = NET::OnAllDesktops;
00149 }
00150
else if ( desk == 0 )
00151 {
00152
00153
00154
00155
if( isTransient())
00156 {
00157 ClientList mainclients = mainClients();
00158
bool on_current =
false;
00159
Client* maincl = NULL;
00160
00161
for( ClientList::ConstIterator it = mainclients.begin();
00162 it != mainclients.end();
00163 ++it )
00164 {
00165
if( (*it)->isSpecialWindow() && !(*it)->isOverride())
00166
continue;
00167 maincl = *it;
00168
if( (*it)->isOnCurrentDesktop())
00169 on_current =
true;
00170 }
00171
if( on_current )
00172 desk = workspace()->currentDesktop();
00173
else if( maincl != NULL )
00174 desk = maincl->
desktop();
00175 }
00176 }
00177
if ( desk == 0 )
00178 desk = workspace()->currentDesktop();
00179 desk = rules()->checkDesktop( desk, !isMapped );
00180
if( desk != NET::OnAllDesktops )
00181 desk = KMAX( 1, KMIN( workspace()->numberOfDesktops(), desk ));
00182 info->setDesktop( desk );
00183 workspace()->updateOnAllDesktopsOfTransients(
this );
00184
00185
00186 QRect geom( attr.x, attr.y, attr.width, attr.height );
00187
bool placementDone = FALSE;
00188
00189
if ( session )
00190 geom = session->geometry;
00191
00192 QRect area;
00193
if( isMapped || session )
00194 area = workspace()->clientArea( FullArea, geom.center(),
desktop());
00195
else if( options->xineramaPlacementEnabled )
00196 area = workspace()->clientArea( PlacementArea, QCursor::pos(),
desktop());
00197
else
00198 area = workspace()->clientArea( PlacementArea, geom.center(),
desktop());
00199
00200
if( checkFullScreenHack( geom ))
00201 {
00202 fullscreen_mode = FullScreenHack;
00203 geom = workspace()->clientArea( FullScreenArea, geom.center(),
desktop());
00204 placementDone =
true;
00205 }
00206
00207
if ( isDesktop() )
00208 {
00209
00210 geom = workspace()->clientArea( FullArea, geom.center(),
desktop());
00211 placementDone =
true;
00212 }
00213
00214
bool usePosition =
false;
00215
if ( isMapped || session || placementDone )
00216 placementDone =
true;
00217
else if( isTransient() && !isUtility() && !isDialog() && !isSplash())
00218 usePosition =
true;
00219
else if( isTransient() && !hasNETSupport())
00220 usePosition =
true;
00221
else if( isDialog() && hasNETSupport())
00222
00223
00224 ;
00225
else if( isSplash())
00226 ;
00227
else
00228 usePosition =
true;
00229
if( !rules()->checkIgnorePosition( !usePosition ))
00230 {
00231
bool ignorePPosition = ( options->ignorePositionClasses.contains(QString::fromLatin1(resourceClass())));
00232
00233
if ( ( (xSizeHint.flags & PPosition) && !ignorePPosition ) ||
00234 (xSizeHint.flags & USPosition) )
00235 {
00236 placementDone = TRUE;
00237
00238 area = workspace()->clientArea( PlacementArea, geom.center(),
desktop());
00239 }
00240 }
00241
if(
true )
00242
if ( (xSizeHint.flags & USSize) || (xSizeHint.flags & PSize) )
00243 {
00244
00245 }
00246
00247
if (xSizeHint.flags & PMaxSize)
00248 geom.setSize( geom.size().boundedTo(
00249 rules()->checkMaxSize( QSize(xSizeHint.max_width, xSizeHint.max_height ) ) ) );
00250
if (xSizeHint.flags & PMinSize)
00251 geom.setSize( geom.size().expandedTo(
00252 rules()->checkMinSize( QSize(xSizeHint.min_width, xSizeHint.min_height ) ) ) );
00253
00254
if(
isMovable())
00255 {
00256
if( geom.x() > area.right() || geom.y() > area.bottom())
00257 placementDone = FALSE;
00258 }
00259
00260
if ( placementDone )
00261
move( geom.x(), geom.y() );
00262
00263 updateDecoration(
false );
00264
00265 plainResize( rules()->checkSize( sizeForClientSize( geom.size()), !isMapped ));
00266
00267 QPoint forced_pos = rules()->checkPosition( invalidPoint, !isMapped );
00268
if( forced_pos != invalidPoint )
00269 {
00270
move( forced_pos );
00271 placementDone =
true;
00272 }
00273
if( !placementDone )
00274 {
00275 workspace()->place(
this, area );
00276 placementDone = TRUE;
00277 }
00278
00279
if( !isMapped && !session
00280 && ( !isSpecialWindow() || isToolbar()) &&
isMovable())
00281 keepInArea( area );
00282
00283 XShapeSelectInput( qt_xdisplay(), window(), ShapeNotifyMask );
00284
if ( (is_shape = Shape::hasShape( window())) )
00285 {
00286 updateShape();
00287 }
00288
00289
00290
00291
00292
if( init_minimize && isTransient())
00293 {
00294 ClientList mainclients = mainClients();
00295
for( ClientList::ConstIterator it = mainclients.begin();
00296 it != mainclients.end();
00297 ++it )
00298
if( (*it)->isShown(
true ))
00299 init_minimize =
false;
00300 }
00301
00302
if( init_minimize )
00303
minimize(
true );
00304
00305
00306
00307
bool doNotShow =
false;
00308
if ( workspace()->isNotManaged(
caption() ) )
00309 doNotShow = TRUE;
00310
00311
00312
if ( session )
00313 {
00314
00315
00316 setKeepAbove( session->keepAbove );
00317 setKeepBelow( session->keepBelow );
00318 setSkipTaskbar( session->skipTaskbar,
true );
00319 setSkipPager( session->skipPager );
00320 setShade( session->shaded ? ShadeNormal : ShadeNone );
00321
if( session->maximized != MaximizeRestore )
00322 {
00323 maximize( (MaximizeMode) session->maximized );
00324 geom_restore = session->restore;
00325 }
00326
if( session->fullscreen == FullScreenHack )
00327 ;
00328
else if( session->fullscreen != FullScreenNone )
00329 {
00330 setFullScreen(
true,
false );
00331 geom_fs_restore = session->fsrestore;
00332 }
00333 }
00334
else
00335 {
00336 geom_restore = geometry();
00337
if ( isMaximizable()
00338 && ( width() >= area.width() || height() >= area.height() ) )
00339 {
00340
00341
00342
if ( width() >= area.width() && height() >= area.height() )
00343 {
00344 maximize( Client::MaximizeFull );
00345 geom_restore = QRect();
00346 }
00347
else if ( width() >= area.width() )
00348 {
00349 maximize( Client::MaximizeHorizontal );
00350 geom_restore = QRect();
00351 geom_restore.setY( y());
00352 geom_restore.setHeight( height());
00353 }
00354
else if ( height() >= area.height() )
00355 {
00356 maximize( Client::MaximizeVertical );
00357 geom_restore = QRect();
00358 geom_restore.setX( x());
00359 geom_restore.setWidth( width());
00360 }
00361 }
00362
00363
00364
00365
00366 MaximizeMode maxmode = static_cast< MaximizeMode >
00367 ((( info->state() & NET::MaxVert ) ? MaximizeVertical : 0 )
00368 | (( info->state() & NET::MaxHoriz ) ? MaximizeHorizontal : 0 ));
00369 MaximizeMode forced_maxmode = rules()->checkMaximize( maxmode, !isMapped );
00370
00371
00372
if( forced_maxmode != MaximizeRestore || maxmode != MaximizeRestore )
00373 maximize( forced_maxmode );
00374
00375
00376 setShade( rules()->checkShade( info->state() & NET::Shaded ? ShadeNormal : ShadeNone, !isMapped ));
00377 setKeepAbove( rules()->checkKeepAbove( info->state() & NET::KeepAbove, !isMapped ));
00378 setKeepBelow( rules()->checkKeepBelow( info->state() & NET::KeepBelow, !isMapped ));
00379 setSkipTaskbar( rules()->checkSkipTaskbar( info->state() & NET::SkipTaskbar, !isMapped ),
true );
00380 setSkipPager( rules()->checkSkipPager( info->state() & NET::SkipPager, !isMapped ));
00381
if( info->state() & NET::DemandsAttention )
00382 demandAttention();
00383
if( info->state() & NET::Modal )
00384 setModal(
true );
00385
if( fullscreen_mode != FullScreenHack && isFullScreenable())
00386 setFullScreen( rules()->checkFullScreen( info->state() & NET::FullScreen, !isMapped ),
false );
00387 }
00388
00389 updateAllowedActions(
true );
00390
00391
00392
00393
00394 XLowerWindow( qt_xdisplay(), frameId());
00395
00396 user_time = readUserTimeMapTimestamp( asn_valid ? &asn_id : NULL, asn_valid ? &asn_data : NULL, session );
00397
00398
if( isTopMenu())
00399 hideClient(
true );
00400
00401
if ( isShown(
true ) && !doNotShow )
00402 {
00403
if( isDialog())
00404 Notify::raise( Notify::TransNew );
00405
if( isNormalWindow())
00406 Notify::raise( Notify::New );
00407
00408
bool allow;
00409
if( session )
00410 allow = session->active && !workspace()->wasUserInteraction();
00411
else
00412 allow = workspace()->allowClientActivation(
this, userTime(),
false );
00413
00414
00415
00416
if( !isOnCurrentDesktop() && !isMapped && !session && ( allow || workspace()->sessionSaving()))
00417 workspace()->setCurrentDesktop(
desktop());
00418
00419
if( isOnCurrentDesktop())
00420 {
00421 setMappingState( NormalState );
00422
00423
if( isMapped )
00424 {
00425 workspace()->raiseClient(
this );
00426 rawShow();
00427 }
00428
else
00429 {
00430
if( allow )
00431 {
00432 workspace()->raiseClient(
this );
00433 rawShow();
00434
if( !isSpecialWindow() || isOverride())
00435
if ( options->focusPolicyIsReasonable() && wantsTabFocus() )
00436 workspace()->requestFocus(
this );
00437 }
00438
else
00439 {
00440 workspace()->restackClientUnderActive(
this );
00441 rawShow();
00442
if( !session && ( !isSpecialWindow() || isOverride()))
00443 demandAttention();
00444 }
00445 }
00446 }
00447
else
00448 {
00449 virtualDesktopChange();
00450 workspace()->raiseClient(
this );
00451
if( !session && !isMapped )
00452 demandAttention();
00453 }
00454 }
00455
else if( !doNotShow )
00456 {
00457 rawHide();
00458 setMappingState( IconicState );
00459 }
00460
else
00461 {
00462 hideClient(
true );
00463 setMappingState( IconicState );
00464 }
00465 assert( mappingState() != WithdrawnState );
00466
00467
if( user_time == CurrentTime || user_time == -1U )
00468 {
00469 user_time = qt_x_time - 1000000;
00470
if( user_time == CurrentTime || user_time == -1U )
00471 user_time = qt_x_time - 1000000 + 10;
00472 }
00473
00474 updateWorkareaDiffs();
00475
00476
00477
00478
delete session;
00479
00480 checkActiveModal();
00481
00482 ungrabXServer();
00483
00484 client_rules.discardTemporary();
00485 updateWindowRules();
00486
00487
return true;
00488 }
00489
00490
00491
void Client::embedClient( Window w,
const XWindowAttributes &attr )
00492 {
00493 assert( client == None );
00494 assert( frame == None );
00495 assert( wrapper == None );
00496 client = w;
00497
00498 XAddToSaveSet( qt_xdisplay(), client );
00499 XSelectInput( qt_xdisplay(), client, NoEventMask );
00500 XUnmapWindow( qt_xdisplay(), client );
00501 XWindowChanges wc;
00502 wc.border_width = 0;
00503 XConfigureWindow( qt_xdisplay(), client, CWBorderWidth, &wc );
00504
00505 XSetWindowAttributes swa;
00506 swa.colormap = attr.colormap;
00507 swa.background_pixmap = None;
00508 swa.border_pixel = 0;
00509
00510 frame = XCreateWindow( qt_xdisplay(), qt_xrootwin(), 0, 0, 1, 1, 0,
00511 attr.depth, InputOutput, attr.visual,
00512 CWColormap | CWBackPixmap | CWBorderPixel, &swa );
00513 wrapper = XCreateWindow( qt_xdisplay(), frame, 0, 0, 1, 1, 0,
00514 attr.depth, InputOutput, attr.visual,
00515 CWColormap | CWBackPixmap | CWBorderPixel, &swa );
00516
00517 XDefineCursor( qt_xdisplay(), frame, arrowCursor.handle());
00518
00519 XDefineCursor( qt_xdisplay(), wrapper, arrowCursor.handle());
00520 XReparentWindow( qt_xdisplay(), client, wrapper, 0, 0 );
00521 XSelectInput( qt_xdisplay(), frame,
00522 KeyPressMask | KeyReleaseMask |
00523 ButtonPressMask | ButtonReleaseMask |
00524 KeymapStateMask |
00525 ButtonMotionMask |
00526 PointerMotionMask |
00527 EnterWindowMask | LeaveWindowMask |
00528 FocusChangeMask |
00529 ExposureMask |
00530 PropertyChangeMask |
00531 StructureNotifyMask | SubstructureRedirectMask |
00532 VisibilityChangeMask );
00533 XSelectInput( qt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
00534 XSelectInput( qt_xdisplay(), client,
00535 FocusChangeMask |
00536 PropertyChangeMask |
00537 ColormapChangeMask |
00538 EnterWindowMask | LeaveWindowMask |
00539 KeyPressMask | KeyReleaseMask
00540 );
00541 updateMouseGrab();
00542 }
00543
00544 }