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