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