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
00106 detectNoBorder();
00107 fetchName();
00108 fetchIconicName();
00109 getWMHints();
00110 getWmClientLeader();
00111 readTransient();
00112 getIcons();
00113 getWindowProtocols();
00114 getWmNormalHints();
00115 window_role = getStringProperty( w, qt_window_role );
00116
00117
00118
00119 original_skip_taskbar = skip_taskbar = ( info->state() & NET::SkipTaskbar) != 0;
00120 skip_pager = ( info->state() & NET::SkipPager) != 0;
00121 modal = ( info->state() & NET::Modal ) != 0;
00122
00123
00124 keep_above = ( info->state() & NET::KeepAbove ) != 0;
00125
00126 keep_below = ( info->state() & NET::KeepBelow ) != 0;
00127 if( keep_above && keep_below )
00128 keep_above = keep_below = false;
00129
00130 KStartupInfoData asn_data;
00131 bool asn_valid = workspace()->checkStartupNotification( window(), asn_data );
00132
00133 workspace()->updateClientLayer( this );
00134
00135 SessionInfo* session = workspace()->takeSessionInfo( this );
00136 if ( session )
00137 {
00138 if ( session->minimized )
00139 init_minimize = true;
00140 if( session->userNoBorder )
00141 setUserNoBorder( true );
00142 }
00143
00144
00145 if ( info->desktop() )
00146 desk = info->desktop();
00147 else if( asn_valid && asn_data.desktop() != 0 )
00148 desk = asn_data.desktop();
00149 if ( session )
00150 {
00151 desk = session->desktop;
00152 if( session->onAllDesktops )
00153 desk = NET::OnAllDesktops;
00154 }
00155 else if ( desk == 0 )
00156 {
00157
00158
00159
00160 if( isTransient())
00161 {
00162 ClientList mainclients = mainClients();
00163 bool on_current = false;
00164 Client* maincl = NULL;
00165
00166 for( ClientList::ConstIterator it = mainclients.begin();
00167 it != mainclients.end();
00168 ++it )
00169 {
00170 if( (*it)->isSpecialWindow() && !(*it)->isOverride())
00171 continue;
00172 maincl = *it;
00173 if( (*it)->isOnCurrentDesktop())
00174 on_current = true;
00175 }
00176 if( on_current )
00177 desk = workspace()->currentDesktop();
00178 else if( maincl != NULL )
00179 desk = maincl->desktop();
00180 }
00181 }
00182 if ( desk == 0 )
00183 desk = workspace()->currentDesktop();
00184 if( desk != NET::OnAllDesktops )
00185 desk = KMAX( 1, KMIN( workspace()->numberOfDesktops(), desk ));
00186 info->setDesktop( desk );
00187 workspace()->updateOnAllDesktopsOfTransients( this );
00188
00189
00190 QRect geom( attr.x, attr.y, attr.width, attr.height );
00191 bool placementDone = FALSE;
00192
00193 if ( session )
00194 geom = session->geometry;
00195
00196 QRect area;
00197 if( isMapped || session )
00198 area = workspace()->clientArea( WorkArea, geom.center(), desktop());
00199 else if( options->xineramaPlacementEnabled )
00200 area = workspace()->clientArea( PlacementArea, QCursor::pos(), desktop());
00201 else
00202 area = workspace()->clientArea( PlacementArea, geom.center(), desktop());
00203
00204
00205 if( ( geom.size() == workspace()->clientArea( FullArea, geom.center(), desktop()).size()
00206 || geom.size() == workspace()->clientArea( ScreenArea, geom.center(), desktop()).size())
00207 && noBorder() && !isUserNoBorder() && isFullScreenable( true ))
00208 {
00209 fullscreen_mode = FullScreenHack;
00210 geom = workspace()->clientArea( MaximizeFullArea, geom.center(), desktop());
00211 placementDone = true;
00212 }
00213
00214 if ( isDesktop() )
00215 {
00216
00217 geom = workspace()->clientArea( FullArea, geom.center(), desktop());
00218 placementDone = true;
00219 }
00220
00221 if ( isMapped || session || placementDone
00222 || ( isTransient() && !isUtility() && !isDialog() && !isSplash()))
00223 {
00224 placementDone = TRUE;
00225 }
00226 else if( isTransient() && !hasNETSupport())
00227 placementDone = true;
00228 else if( isDialog() && hasNETSupport())
00229 ;
00230 else if( isSplash())
00231 ;
00232 else
00233 {
00234 bool ignorePPosition = ( options->ignorePositionClasses.contains(QString::fromLatin1(resourceClass())));
00235
00236 if ((xSizeHint.flags & PPosition) && ! ignorePPosition)
00237 {
00238 int tx = geom.x();
00239 int ty = geom.y();
00240
00241
00242 if (tx < 0)
00243 tx = area.right() + tx;
00244 if (ty < 0)
00245 ty = area.bottom() + ty;
00246 geom.moveTopLeft(QPoint(tx, ty));
00247 }
00248
00249 if ( ( (xSizeHint.flags & PPosition) && !ignorePPosition ) ||
00250 (xSizeHint.flags & USPosition) )
00251 {
00252 placementDone = TRUE;
00253 }
00254 if ( (xSizeHint.flags & USSize) || (xSizeHint.flags & PSize) )
00255 {
00256
00257 }
00258 }
00259
00260 if (xSizeHint.flags & PMaxSize)
00261 geom.setSize( geom.size().boundedTo( QSize(xSizeHint.max_width, xSizeHint.max_height ) ) );
00262 if (xSizeHint.flags & PMinSize)
00263 geom.setSize( geom.size().expandedTo( QSize(xSizeHint.min_width, xSizeHint.min_height ) ) );
00264
00265 if( isMovable())
00266 {
00267 if( geom.x() > area.right() || geom.y() > area.bottom())
00268 placementDone = FALSE;
00269 }
00270
00271 if ( placementDone )
00272 move( geom.x(), geom.y() );
00273
00274 updateDecoration( false );
00275
00276 plainResize( sizeForClientSize( geom.size()));
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();
00309
00310
00311
00312 bool doNotShow = false;
00313 if ( workspace()->isNotManaged( caption() ) )
00314 doNotShow = TRUE;
00315
00316
00317 if ( session )
00318 {
00319 setKeepAbove( session->keepAbove );
00320 setKeepBelow( session->keepBelow );
00321 setSkipTaskbar( session->skipTaskbar, true );
00322 setSkipPager( session->skipPager );
00323 setShade( session->shaded ? ShadeNormal : ShadeNone );
00324 if( session->maximized != MaximizeRestore )
00325 {
00326 maximize( (MaximizeMode) session->maximized );
00327 geom_restore = session->restore;
00328 }
00329 if( session->fullscreen == FullScreenHack )
00330 ;
00331 else if( session->fullscreen != FullScreenNone )
00332 {
00333 setFullScreen( true, false );
00334 geom_fs_restore = session->fsrestore;
00335 }
00336 }
00337 else
00338 {
00339 geom_restore = geometry();
00340 if ( isMaximizable()
00341 && ( width() >= area.width() || height() >= area.height() ) )
00342 {
00343
00344
00345 if ( width() >= area.width() && height() >= area.height() )
00346 {
00347 maximize( Client::MaximizeFull );
00348 geom_restore = QRect();
00349 }
00350 else if ( width() >= area.width() )
00351 {
00352 maximize( Client::MaximizeHorizontal );
00353 geom_restore = QRect();
00354 geom_restore.setY( y());
00355 geom_restore.setHeight( height());
00356 }
00357 else if ( height() >= area.height() )
00358 {
00359 maximize( Client::MaximizeVertical );
00360 geom_restore = QRect();
00361 geom_restore.setX( x());
00362 geom_restore.setWidth( width());
00363 }
00364 }
00365
00366
00367
00368
00369 if ( (info->state() & NET::Max) == NET::Max )
00370 maximize( Client::MaximizeFull );
00371 else if ( info->state() & NET::MaxVert )
00372 maximize( Client::MaximizeVertical );
00373 else if ( info->state() & NET::MaxHoriz )
00374 maximize( Client::MaximizeHorizontal );
00375
00376
00377 if( info->state() & NET::Shaded )
00378 setShade( ShadeNormal );
00379 if( info->state() & NET::KeepAbove )
00380 setKeepAbove( true );
00381 if( info->state() & NET::KeepBelow )
00382 setKeepBelow( true );
00383 if( info->state() & NET::SkipTaskbar )
00384 setSkipTaskbar( true, true );
00385 if( info->state() & NET::SkipPager )
00386 setSkipPager( true );
00387 if( info->state() & NET::DemandsAttention )
00388 demandAttention();
00389 if( info->state() & NET::Modal )
00390 setModal( true );
00391 if( fullscreen_mode != FullScreenHack )
00392 {
00393 if(( info->state() & NET::FullScreen ) != 0 && isFullScreenable())
00394 setFullScreen( true, false );
00395 }
00396 }
00397
00398 updateAllowedActions( true );
00399
00400
00401
00402
00403 XLowerWindow( qt_xdisplay(), frameId());
00404
00405 user_time = readUserTimeMapTimestamp( asn_valid ? &asn_data : NULL, session );
00406
00407 if( isTopMenu())
00408 hideClient( true );
00409
00410 if ( isShown( true ) && !doNotShow )
00411 {
00412 if( isDialog())
00413 Notify::raise( Notify::TransNew );
00414 if( isNormalWindow())
00415 Notify::raise( Notify::New );
00416
00417
00418 if( workspace()->sessionSaving() && !isOnCurrentDesktop())
00419 workspace()->setCurrentDesktop( desktop());
00420
00421 if( isOnCurrentDesktop())
00422 {
00423 setMappingState( NormalState );
00424
00425 if( isMapped )
00426 {
00427 workspace()->raiseClient( this );
00428 rawShow();
00429 }
00430 else
00431 {
00432 if( workspace()->allowClientActivation( this, userTime(), false, session && session->active ))
00433 {
00434 workspace()->raiseClient( this );
00435 rawShow();
00436 if( !isSpecialWindow() || isOverride())
00437 if ( options->focusPolicyIsReasonable() && wantsTabFocus() )
00438 workspace()->requestFocus( this );
00439 }
00440 else
00441 {
00442 workspace()->restackClientUnderActive( this );
00443 rawShow();
00444 if( ( !session || session->fake ) && ( !isSpecialWindow() || isOverride()))
00445 demandAttention();
00446 }
00447 }
00448 }
00449 else
00450 {
00451 virtualDesktopChange();
00452 workspace()->raiseClient( this );
00453 if( ( !session || session->fake ) && !isMapped )
00454 demandAttention();
00455 }
00456 }
00457 else if( !doNotShow )
00458 {
00459 rawHide();
00460 setMappingState( IconicState );
00461 }
00462 else
00463 {
00464 hideClient( true );
00465 setMappingState( IconicState );
00466 }
00467 assert( mappingState() != WithdrawnState );
00468
00469 if( user_time == CurrentTime || user_time == -1U )
00470 {
00471 user_time = qt_x_time - 1000000;
00472 if( user_time == CurrentTime || user_time == -1U )
00473 user_time = qt_x_time - 1000000 + 10;
00474 }
00475
00476 updateWorkareaDiffs();
00477
00478
00479
00480 delete session;
00481
00482 ungrabXServer();
00483
00484 return true;
00485 }
00486
00487
00488 void Client::embedClient( Window w, const XWindowAttributes &attr )
00489 {
00490 assert( client == None );
00491 assert( frame == None );
00492 assert( wrapper == None );
00493 client = w;
00494
00495 XAddToSaveSet( qt_xdisplay(), client );
00496 XSelectInput( qt_xdisplay(), client, NoEventMask );
00497 XUnmapWindow( qt_xdisplay(), client );
00498 XWindowChanges wc;
00499 wc.border_width = 0;
00500 XConfigureWindow( qt_xdisplay(), client, CWBorderWidth, &wc );
00501
00502 XSetWindowAttributes swa;
00503 swa.colormap = attr.colormap;
00504 swa.background_pixmap = None;
00505 swa.border_pixel = 0;
00506
00507 frame = XCreateWindow( qt_xdisplay(), qt_xrootwin(), 0, 0, 1, 1, 0,
00508 attr.depth, InputOutput, attr.visual,
00509 CWColormap | CWBackPixmap | CWBorderPixel, &swa );
00510 wrapper = XCreateWindow( qt_xdisplay(), frame, 0, 0, 1, 1, 0,
00511 attr.depth, InputOutput, attr.visual,
00512 CWColormap | CWBackPixmap | CWBorderPixel, &swa );
00513
00514 XDefineCursor( qt_xdisplay(), frame, arrowCursor.handle());
00515
00516 XDefineCursor( qt_xdisplay(), wrapper, arrowCursor.handle());
00517 XReparentWindow( qt_xdisplay(), client, wrapper, 0, 0 );
00518 XSelectInput( qt_xdisplay(), frame,
00519 KeyPressMask | KeyReleaseMask |
00520 ButtonPressMask | ButtonReleaseMask |
00521 KeymapStateMask |
00522 ButtonMotionMask |
00523 PointerMotionMask |
00524 EnterWindowMask | LeaveWindowMask |
00525 FocusChangeMask |
00526 ExposureMask |
00527 PropertyChangeMask |
00528 StructureNotifyMask | SubstructureRedirectMask |
00529 VisibilityChangeMask );
00530 XSelectInput( qt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
00531 XSelectInput( qt_xdisplay(), client,
00532 FocusChangeMask |
00533 PropertyChangeMask |
00534 ColormapChangeMask |
00535 EnterWindowMask | LeaveWindowMask |
00536 KeyPressMask | KeyReleaseMask
00537 );
00538 updateMouseGrab();
00539 }
00540
00541 }