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 if( mainClients().count() >= 1 )
00226 ;
00227 else
00228 usePosition = true;
00229 }
00230 else if( isSplash())
00231 ;
00232 else
00233 usePosition = true;
00234 if( !rules()->checkIgnorePosition( !usePosition ))
00235 {
00236 bool ignorePPosition = ( options->ignorePositionClasses.contains(QString::fromLatin1(resourceClass())));
00237
00238 if ( ( (xSizeHint.flags & PPosition) && !ignorePPosition ) ||
00239 (xSizeHint.flags & USPosition) )
00240 {
00241 placementDone = TRUE;
00242
00243 area = workspace()->clientArea( PlacementArea, geom.center(), desktop());
00244 }
00245 }
00246 if( true )
00247 if ( (xSizeHint.flags & USSize) || (xSizeHint.flags & PSize) )
00248 {
00249
00250 }
00251
00252 if (xSizeHint.flags & PMaxSize)
00253 geom.setSize( geom.size().boundedTo(
00254 rules()->checkMaxSize( QSize(xSizeHint.max_width, xSizeHint.max_height ) ) ) );
00255 if (xSizeHint.flags & PMinSize)
00256 geom.setSize( geom.size().expandedTo(
00257 rules()->checkMinSize( QSize(xSizeHint.min_width, xSizeHint.min_height ) ) ) );
00258
00259 if( isMovable())
00260 {
00261 if( geom.x() > area.right() || geom.y() > area.bottom())
00262 placementDone = FALSE;
00263 }
00264
00265 if ( placementDone )
00266 move( geom.x(), geom.y() );
00267
00268 updateDecoration( false );
00269
00270 plainResize( rules()->checkSize( sizeForClientSize( geom.size()), !isMapped ));
00271
00272 QPoint forced_pos = rules()->checkPosition( invalidPoint, !isMapped );
00273 if( forced_pos != invalidPoint )
00274 {
00275 move( forced_pos );
00276 placementDone = true;
00277 }
00278 if( !placementDone )
00279 {
00280 workspace()->place( this, area );
00281 placementDone = TRUE;
00282 }
00283
00284 if( !isMapped && !session
00285 && ( !isSpecialWindow() || isToolbar()) && isMovable())
00286 keepInArea( area );
00287
00288 XShapeSelectInput( qt_xdisplay(), window(), ShapeNotifyMask );
00289 if ( (is_shape = Shape::hasShape( window())) )
00290 {
00291 updateShape();
00292 }
00293
00294
00295
00296
00297 if( init_minimize && isTransient())
00298 {
00299 ClientList mainclients = mainClients();
00300 for( ClientList::ConstIterator it = mainclients.begin();
00301 it != mainclients.end();
00302 ++it )
00303 if( (*it)->isShown( true ))
00304 init_minimize = false;
00305 }
00306
00307 if( init_minimize )
00308 minimize( true );
00309
00310
00311
00312 bool doNotShow = false;
00313 if ( workspace()->isNotManaged( caption() ) )
00314 doNotShow = TRUE;
00315
00316
00317 if ( session )
00318 {
00319
00320
00321 setKeepAbove( session->keepAbove );
00322 setKeepBelow( session->keepBelow );
00323 setSkipTaskbar( session->skipTaskbar, true );
00324 setSkipPager( session->skipPager );
00325 setShade( session->shaded ? ShadeNormal : ShadeNone );
00326 if( session->maximized != MaximizeRestore )
00327 {
00328 maximize( (MaximizeMode) session->maximized );
00329 geom_restore = session->restore;
00330 }
00331 if( session->fullscreen == FullScreenHack )
00332 ;
00333 else if( session->fullscreen != FullScreenNone )
00334 {
00335 setFullScreen( true, false );
00336 geom_fs_restore = session->fsrestore;
00337 }
00338 }
00339 else
00340 {
00341 geom_restore = geometry();
00342 if ( isMaximizable()
00343 && ( width() >= area.width() || height() >= area.height() ) )
00344 {
00345
00346
00347 if ( width() >= area.width() && height() >= area.height() )
00348 {
00349 maximize( Client::MaximizeFull );
00350 geom_restore = QRect();
00351 }
00352 else if ( width() >= area.width() )
00353 {
00354 maximize( Client::MaximizeHorizontal );
00355 geom_restore = QRect();
00356 geom_restore.setY( y());
00357 geom_restore.setHeight( height());
00358 }
00359 else if ( height() >= area.height() )
00360 {
00361 maximize( Client::MaximizeVertical );
00362 geom_restore = QRect();
00363 geom_restore.setX( x());
00364 geom_restore.setWidth( width());
00365 }
00366 }
00367
00368
00369
00370
00371 MaximizeMode maxmode = static_cast< MaximizeMode >
00372 ((( info->state() & NET::MaxVert ) ? MaximizeVertical : 0 )
00373 | (( info->state() & NET::MaxHoriz ) ? MaximizeHorizontal : 0 ));
00374 MaximizeMode forced_maxmode = rules()->checkMaximize( maxmode, !isMapped );
00375
00376
00377 if( forced_maxmode != MaximizeRestore || maxmode != MaximizeRestore )
00378 maximize( forced_maxmode );
00379
00380
00381 setShade( rules()->checkShade( info->state() & NET::Shaded ? ShadeNormal : ShadeNone, !isMapped ));
00382 setKeepAbove( rules()->checkKeepAbove( info->state() & NET::KeepAbove, !isMapped ));
00383 setKeepBelow( rules()->checkKeepBelow( info->state() & NET::KeepBelow, !isMapped ));
00384 setSkipTaskbar( rules()->checkSkipTaskbar( info->state() & NET::SkipTaskbar, !isMapped ), true );
00385 setSkipPager( rules()->checkSkipPager( info->state() & NET::SkipPager, !isMapped ));
00386 if( info->state() & NET::DemandsAttention )
00387 demandAttention();
00388 if( info->state() & NET::Modal )
00389 setModal( true );
00390 if( fullscreen_mode != FullScreenHack && isFullScreenable())
00391 setFullScreen( rules()->checkFullScreen( info->state() & NET::FullScreen, !isMapped ), false );
00392 }
00393
00394 updateAllowedActions( true );
00395
00396
00397
00398
00399 XLowerWindow( qt_xdisplay(), frameId());
00400
00401 user_time = readUserTimeMapTimestamp( asn_valid ? &asn_id : NULL, asn_valid ? &asn_data : NULL, session );
00402
00403 if( isTopMenu())
00404 hideClient( true );
00405
00406 if ( isShown( true ) && !doNotShow )
00407 {
00408 if( isDialog())
00409 Notify::raise( Notify::TransNew );
00410 if( isNormalWindow())
00411 Notify::raise( Notify::New );
00412
00413 bool allow;
00414 if( session )
00415 allow = session->active && !workspace()->wasUserInteraction();
00416 else
00417 allow = workspace()->allowClientActivation( this, userTime(), false );
00418
00419
00420
00421 if( !isOnCurrentDesktop() && !isMapped && !session && ( allow || workspace()->sessionSaving()))
00422 workspace()->setCurrentDesktop( desktop());
00423
00424 if( isOnCurrentDesktop())
00425 {
00426 setMappingState( NormalState );
00427
00428 if( isMapped )
00429 {
00430 workspace()->raiseClient( this );
00431 rawShow();
00432 }
00433 else
00434 {
00435 if( allow )
00436 {
00437 workspace()->raiseClient( this );
00438 rawShow();
00439 if( !isSpecialWindow() || isOverride())
00440 if ( options->focusPolicyIsReasonable() && wantsTabFocus() )
00441 workspace()->requestFocus( this );
00442 }
00443 else
00444 {
00445 workspace()->restackClientUnderActive( this );
00446 rawShow();
00447 if( !session && ( !isSpecialWindow() || isOverride()))
00448 demandAttention();
00449 }
00450 }
00451 }
00452 else
00453 {
00454 virtualDesktopChange();
00455 workspace()->raiseClient( this );
00456 if( !session && !isMapped )
00457 demandAttention();
00458 }
00459 }
00460 else if( !doNotShow )
00461 {
00462 rawHide();
00463 setMappingState( IconicState );
00464 }
00465 else
00466 {
00467 hideClient( true );
00468 setMappingState( IconicState );
00469 }
00470 assert( mappingState() != WithdrawnState );
00471
00472 if( user_time == CurrentTime || user_time == -1U )
00473 {
00474 user_time = qt_x_time - 1000000;
00475 if( user_time == CurrentTime || user_time == -1U )
00476 user_time = qt_x_time - 1000000 + 10;
00477 }
00478
00479 updateWorkareaDiffs();
00480
00481
00482
00483 delete session;
00484
00485 checkActiveModal();
00486
00487 ungrabXServer();
00488
00489 client_rules.discardTemporary();
00490 updateWindowRules();
00491
00492 return true;
00493 }
00494
00495
00496 void Client::embedClient( Window w, const XWindowAttributes &attr )
00497 {
00498 assert( client == None );
00499 assert( frame == None );
00500 assert( wrapper == None );
00501 client = w;
00502
00503 XAddToSaveSet( qt_xdisplay(), client );
00504 XSelectInput( qt_xdisplay(), client, NoEventMask );
00505 XUnmapWindow( qt_xdisplay(), client );
00506 XWindowChanges wc;
00507 wc.border_width = 0;
00508 XConfigureWindow( qt_xdisplay(), client, CWBorderWidth, &wc );
00509
00510 XSetWindowAttributes swa;
00511 swa.colormap = attr.colormap;
00512 swa.background_pixmap = None;
00513 swa.border_pixel = 0;
00514
00515 frame = XCreateWindow( qt_xdisplay(), qt_xrootwin(), 0, 0, 1, 1, 0,
00516 attr.depth, InputOutput, attr.visual,
00517 CWColormap | CWBackPixmap | CWBorderPixel, &swa );
00518 wrapper = XCreateWindow( qt_xdisplay(), frame, 0, 0, 1, 1, 0,
00519 attr.depth, InputOutput, attr.visual,
00520 CWColormap | CWBackPixmap | CWBorderPixel, &swa );
00521
00522 XDefineCursor( qt_xdisplay(), frame, arrowCursor.handle());
00523
00524 XDefineCursor( qt_xdisplay(), wrapper, arrowCursor.handle());
00525 XReparentWindow( qt_xdisplay(), client, wrapper, 0, 0 );
00526 XSelectInput( qt_xdisplay(), frame,
00527 KeyPressMask | KeyReleaseMask |
00528 ButtonPressMask | ButtonReleaseMask |
00529 KeymapStateMask |
00530 ButtonMotionMask |
00531 PointerMotionMask |
00532 EnterWindowMask | LeaveWindowMask |
00533 FocusChangeMask |
00534 ExposureMask |
00535 PropertyChangeMask |
00536 StructureNotifyMask | SubstructureRedirectMask |
00537 VisibilityChangeMask );
00538 XSelectInput( qt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
00539 XSelectInput( qt_xdisplay(), client,
00540 FocusChangeMask |
00541 PropertyChangeMask |
00542 ColormapChangeMask |
00543 EnterWindowMask | LeaveWindowMask |
00544 KeyPressMask | KeyReleaseMask
00545 );
00546 updateMouseGrab();
00547 }
00548
00549 }