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