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