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
00026 extern Time qt_x_time;
00027 extern Atom qt_window_role;
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 0;
00077
00078 info = new WinInfo( this, qt_xdisplay(), client, qt_xrootwin(), properties, 2 );
00079
00080 cmap = attr.colormap;
00081
00082 bool mresize, mmove, mminimize, mmaximize, mclose;
00083 if( Motif::funcFlags( client, mresize, mmove, mminimize, mmaximize, mclose ))
00084 {
00085 if( !hasNETSupport())
00086 {
00087 motif_may_resize = mresize;
00088 motif_may_move = mmove;
00089 }
00090
00091
00092 motif_may_close = mclose;
00093 }
00094
00095 XClassHint classHint;
00096 if ( XGetClassHint( qt_xdisplay(), client, &classHint ) )
00097 {
00098
00099
00100 resource_name = QCString( classHint.res_name ).lower();
00101 resource_class = QCString( classHint.res_class ).lower();
00102 XFree( classHint.res_name );
00103 XFree( classHint.res_class );
00104 }
00105 ignore_focus_stealing = options->checkIgnoreFocusStealing( this );
00106
00107 detectNoBorder();
00108 fetchName();
00109 fetchIconicName();
00110 getWMHints();
00111 getWmClientLeader();
00112 readTransient();
00113 getIcons();
00114 getWindowProtocols();
00115 getWmNormalHints();
00116 window_role = getStringProperty( w, qt_window_role );
00117
00118
00119
00120 original_skip_taskbar = skip_taskbar = ( info->state() & NET::SkipTaskbar) != 0;
00121 skip_pager = ( info->state() & NET::SkipPager) != 0;
00122 modal = ( info->state() & NET::Modal ) != 0;
00123
00124
00125 keep_above = ( info->state() & NET::KeepAbove ) != 0;
00126
00127 keep_below = ( info->state() & NET::KeepBelow ) != 0;
00128 if( keep_above && keep_below )
00129 keep_above = keep_below = false;
00130
00131 KStartupInfoData asn_data;
00132 bool asn_valid = workspace()->checkStartupNotification( window(), asn_data );
00133
00134 workspace()->updateClientLayer( this );
00135
00136 SessionInfo* session = workspace()->takeSessionInfo( this );
00137 if ( session )
00138 {
00139 if ( session->minimized )
00140 init_minimize = true;
00141 if( session->userNoBorder )
00142 setUserNoBorder( true );
00143 }
00144
00145
00146 if ( info->desktop() )
00147 desk = info->desktop();
00148 else if( asn_valid && asn_data.desktop() != 0 )
00149 desk = asn_data.desktop();
00150 if ( session )
00151 {
00152 desk = session->desktop;
00153 if( session->onAllDesktops )
00154 desk = NET::OnAllDesktops;
00155 }
00156 else if ( desk == 0 )
00157 {
00158
00159
00160
00161 if( isTransient())
00162 {
00163 ClientList mainclients = mainClients();
00164 bool on_current = false;
00165 Client* maincl = NULL;
00166
00167 for( ClientList::ConstIterator it = mainclients.begin();
00168 it != mainclients.end();
00169 ++it )
00170 {
00171 if( (*it)->isSpecialWindow() && !(*it)->isOverride())
00172 continue;
00173 maincl = *it;
00174 if( (*it)->isOnCurrentDesktop())
00175 on_current = true;
00176 }
00177 if( on_current )
00178 desk = workspace()->currentDesktop();
00179 else if( maincl != NULL )
00180 desk = maincl->desktop();
00181 }
00182 }
00183 if ( desk == 0 )
00184 desk = workspace()->currentDesktop();
00185 if( desk != NET::OnAllDesktops )
00186 desk = KMAX( 1, KMIN( workspace()->numberOfDesktops(), desk ));
00187 info->setDesktop( desk );
00188 workspace()->updateOnAllDesktopsOfTransients( this );
00189
00190
00191 QRect geom( attr.x, attr.y, attr.width, attr.height );
00192 bool placementDone = FALSE;
00193
00194 if ( session )
00195 geom = session->geometry;
00196
00197 QRect area;
00198 if( isMapped || session )
00199 area = workspace()->clientArea( WorkArea, geom.center(), desktop());
00200 else if( options->xineramaPlacementEnabled )
00201 area = workspace()->clientArea( PlacementArea, QCursor::pos(), desktop());
00202 else
00203 area = workspace()->clientArea( PlacementArea, geom.center(), desktop());
00204
00205
00206 if( ( geom.size() == workspace()->clientArea( FullArea, geom.center(), desktop()).size()
00207 || geom.size() == workspace()->clientArea( ScreenArea, geom.center(), desktop()).size())
00208 && noBorder() && !isUserNoBorder() && isFullScreenable( true ))
00209 {
00210 fullscreen_mode = FullScreenHack;
00211 geom = workspace()->clientArea( MaximizeFullArea, 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 if ( isMapped || session || placementDone
00223 || ( isTransient() && !isUtility() && !isDialog() && !isSplash()))
00224 {
00225 placementDone = TRUE;
00226 }
00227 else if( isTransient() && !hasNETSupport())
00228 placementDone = true;
00229 else if( isDialog() && hasNETSupport())
00230 ;
00231 else if( isSplash())
00232 ;
00233 else
00234 {
00235 bool ignorePPosition = ( options->ignorePositionClasses.contains(QString::fromLatin1(resourceClass())));
00236
00237 if ((xSizeHint.flags & PPosition) && ! ignorePPosition)
00238 {
00239 int tx = geom.x();
00240 int ty = geom.y();
00241
00242
00243 if (tx < 0)
00244 tx = area.right() + tx;
00245 if (ty < 0)
00246 ty = area.bottom() + ty;
00247 geom.moveTopLeft(QPoint(tx, ty));
00248 }
00249
00250 if ( ( (xSizeHint.flags & PPosition) && !ignorePPosition ) ||
00251 (xSizeHint.flags & USPosition) )
00252 {
00253 placementDone = TRUE;
00254
00255 area = workspace()->clientArea( PlacementArea, geom.center(), desktop());
00256 }
00257 if ( (xSizeHint.flags & USSize) || (xSizeHint.flags & PSize) )
00258 {
00259
00260 }
00261 }
00262
00263 if (xSizeHint.flags & PMaxSize)
00264 geom.setSize( geom.size().boundedTo( QSize(xSizeHint.max_width, xSizeHint.max_height ) ) );
00265 if (xSizeHint.flags & PMinSize)
00266 geom.setSize( geom.size().expandedTo( QSize(xSizeHint.min_width, xSizeHint.min_height ) ) );
00267
00268 if( isMovable())
00269 {
00270 if( geom.x() > area.right() || geom.y() > area.bottom())
00271 placementDone = FALSE;
00272 }
00273
00274 if ( placementDone )
00275 move( geom.x(), geom.y() );
00276
00277 updateDecoration( false );
00278
00279 plainResize( sizeForClientSize( geom.size()));
00280
00281 if( !placementDone )
00282 {
00283 workspace()->place( this, area );
00284 placementDone = TRUE;
00285 }
00286
00287 if( !isMapped && !session
00288 && ( !isSpecialWindow() || isToolbar()) && isMovable())
00289 keepInArea( area );
00290
00291 XShapeSelectInput( qt_xdisplay(), window(), ShapeNotifyMask );
00292 if ( (is_shape = Shape::hasShape( window())) )
00293 {
00294 updateShape();
00295 }
00296
00297
00298
00299
00300 if( init_minimize && isTransient())
00301 {
00302 ClientList mainclients = mainClients();
00303 for( ClientList::ConstIterator it = mainclients.begin();
00304 it != mainclients.end();
00305 ++it )
00306 if( (*it)->isShown( true ))
00307 init_minimize = false;
00308 }
00309
00310 if( init_minimize )
00311 minimize();
00312
00313
00314
00315 bool doNotShow = false;
00316 if ( workspace()->isNotManaged( caption() ) )
00317 doNotShow = TRUE;
00318
00319
00320 if ( session )
00321 {
00322 setKeepAbove( session->keepAbove );
00323 setKeepBelow( session->keepBelow );
00324 setSkipTaskbar( session->skipTaskbar, true );
00325 setSkipPager( session->skipPager );
00326 setShade( session->shaded ? ShadeNormal : ShadeNone );
00327 if( session->maximized != MaximizeRestore )
00328 {
00329 maximize( (MaximizeMode) session->maximized );
00330 geom_restore = session->restore;
00331 }
00332 if( session->fullscreen == FullScreenHack )
00333 ;
00334 else if( session->fullscreen != FullScreenNone )
00335 {
00336 setFullScreen( true, false );
00337 geom_fs_restore = session->fsrestore;
00338 }
00339 }
00340 else
00341 {
00342 geom_restore = geometry();
00343 if ( isMaximizable()
00344 && ( width() >= area.width() || height() >= area.height() ) )
00345 {
00346
00347
00348 if ( width() >= area.width() && height() >= area.height() )
00349 {
00350 maximize( Client::MaximizeFull );
00351 geom_restore = QRect();
00352 }
00353 else if ( width() >= area.width() )
00354 {
00355 maximize( Client::MaximizeHorizontal );
00356 geom_restore = QRect();
00357 geom_restore.setY( y());
00358 geom_restore.setHeight( height());
00359 }
00360 else if ( height() >= area.height() )
00361 {
00362 maximize( Client::MaximizeVertical );
00363 geom_restore = QRect();
00364 geom_restore.setX( x());
00365 geom_restore.setWidth( width());
00366 }
00367 }
00368
00369
00370
00371
00372 if ( (info->state() & NET::Max) == NET::Max )
00373 maximize( Client::MaximizeFull );
00374 else if ( info->state() & NET::MaxVert )
00375 maximize( Client::MaximizeVertical );
00376 else if ( info->state() & NET::MaxHoriz )
00377 maximize( Client::MaximizeHorizontal );
00378
00379
00380 if( info->state() & NET::Shaded )
00381 setShade( ShadeNormal );
00382 if( info->state() & NET::KeepAbove )
00383 setKeepAbove( true );
00384 if( info->state() & NET::KeepBelow )
00385 setKeepBelow( true );
00386 if( info->state() & NET::SkipTaskbar )
00387 setSkipTaskbar( true, true );
00388 if( info->state() & NET::SkipPager )
00389 setSkipPager( true );
00390 if( info->state() & NET::DemandsAttention )
00391 demandAttention();
00392 if( info->state() & NET::Modal )
00393 setModal( true );
00394 if( fullscreen_mode != FullScreenHack )
00395 {
00396 if(( info->state() & NET::FullScreen ) != 0 && isFullScreenable())
00397 setFullScreen( true, false );
00398 }
00399 }
00400
00401 updateAllowedActions( true );
00402
00403
00404
00405
00406 XLowerWindow( qt_xdisplay(), frameId());
00407
00408 user_time = readUserTimeMapTimestamp( asn_valid ? &asn_data : NULL, session );
00409
00410 if( isTopMenu())
00411 hideClient( true );
00412
00413 if ( isShown( true ) && !doNotShow )
00414 {
00415 if( isDialog())
00416 Notify::raise( Notify::TransNew );
00417 if( isNormalWindow())
00418 Notify::raise( Notify::New );
00419
00420
00421 if( workspace()->sessionSaving() && !isOnCurrentDesktop())
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( workspace()->allowClientActivation( this, userTime(), false, session && session->active ))
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 || session->fake ) && ( !isSpecialWindow() || isOverride()))
00448 demandAttention();
00449 }
00450 }
00451 }
00452 else
00453 {
00454 virtualDesktopChange();
00455 workspace()->raiseClient( this );
00456 if( ( !session || session->fake ) && !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 ungrabXServer();
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 }