• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KWin

manage.cpp

Go to the documentation of this file.
00001 /********************************************************************
00002  KWin - the KDE window manager
00003  This file is part of the KDE project.
00004 
00005 Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
00006 Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
00007 
00008 This program is free software; you can redistribute it and/or modify
00009 it under the terms of the GNU General Public License as published by
00010 the Free Software Foundation; either version 2 of the License, or
00011 (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 GNU General Public License for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with this program.  If not, see <http://www.gnu.org/licenses/>.
00020 *********************************************************************/
00021 
00022 // This file contains things relevant to handling incoming events.
00023 
00024 #include "client.h"
00025 
00026 #include <kstartupinfo.h>
00027 #include <kglobal.h>
00028 #include <X11/extensions/shape.h>
00029 
00030 #include "notifications.h"
00031 #include <QX11Info>
00032 #include "rules.h"
00033 #include "group.h"
00034 
00035 namespace KWin
00036 {
00037 
00043 bool Client::manage( Window w, bool isMapped )
00044     {
00045     StackingUpdatesBlocker stacking_blocker( workspace() );
00046 
00047     grabXServer();
00048 
00049     XWindowAttributes attr;
00050     if( !XGetWindowAttributes( display(), w, &attr ))
00051         {
00052         ungrabXServer();
00053         return false;
00054         }
00055 
00056     // From this place on, manage() must not return false
00057     block_geometry_updates = 1;
00058     pending_geometry_update = PendingGeometryForced; // Force update when finishing with geometry changes
00059 
00060     embedClient( w, attr );
00061 
00062     vis = attr.visual;
00063     bit_depth = attr.depth;
00064 
00065     // SELI TODO: Order all these things in some sane manner
00066 
00067     bool init_minimize = false;
00068     XWMHints* hints = XGetWMHints( display(), w );
00069     if( hints && ( hints->flags & StateHint ) && hints->initial_state == IconicState )
00070         init_minimize = true;
00071     if( hints )
00072         XFree( hints );
00073     if( isMapped )
00074         init_minimize = false; // If it's already mapped, ignore hint
00075 
00076     unsigned long properties[2];
00077     properties[WinInfo::PROTOCOLS] =
00078         NET::WMDesktop |
00079         NET::WMState |
00080         NET::WMWindowType |
00081         NET::WMStrut |
00082         NET::WMName |
00083         NET::WMIconGeometry |
00084         NET::WMIcon |
00085         NET::WMPid |
00086         NET::WMIconName |
00087         0;
00088     properties[WinInfo::PROTOCOLS2] =
00089         NET::WM2UserTime |
00090         NET::WM2StartupId |
00091         NET::WM2ExtendedStrut |
00092         NET::WM2Opacity |
00093         NET::WM2FullscreenMonitors |
00094         0;
00095 
00096     info = new WinInfo( this, display(), client, rootWindow(), properties, 2 );
00097 
00098     cmap = attr.colormap;
00099 
00100     getResourceClass();
00101     getWindowRole();
00102     getWmClientLeader();
00103     getWmClientMachine();
00104     getSyncCounter();
00105     // First only read the caption text, so that setupWindowRules() can use it for matching,
00106     // and only then really set the caption using setCaption(), which checks for duplicates etc.
00107     // and also relies on rules already existing
00108     cap_normal = readName();
00109     setupWindowRules( false );
00110     ignore_focus_stealing = options->checkIgnoreFocusStealing( this ); // TODO: Change to rules
00111     setCaption( cap_normal, true );
00112 
00113     if( Extensions::shapeAvailable() )
00114         XShapeSelectInput( display(), window(), ShapeNotifyMask );
00115     detectShape( window() );
00116     detectNoBorder();
00117     fetchIconicName();
00118     getWMHints(); // Needs to be done before readTransient() because of reading the group
00119     modal = ( info->state() & NET::Modal ) != 0; // Needs to be valid before handling groups
00120     readTransient();
00121     getIcons();
00122     getWindowProtocols();
00123     getWmNormalHints(); // Get xSizeHint
00124     getMotifHints();
00125 
00126     // TODO: Try to obey all state information from info->state()
00127 
00128     original_skip_taskbar = skip_taskbar = ( info->state() & NET::SkipTaskbar ) != 0;
00129     skip_pager = ( info->state() & NET::SkipPager ) != 0;
00130 
00131     setupCompositing();
00132 
00133     KStartupInfoId asn_id;
00134     KStartupInfoData asn_data;
00135     bool asn_valid = workspace()->checkStartupNotification( window(), asn_id, asn_data );
00136 
00137     workspace()->updateClientLayer( this );
00138 
00139     SessionInfo* session = workspace()->takeSessionInfo( this );
00140     if( session )
00141         {
00142         init_minimize = session->minimized;
00143         noborder = session->noBorder;
00144         }
00145 
00146     setShortcut( rules()->checkShortcut( session ? session->shortcut : QString(), true ));
00147 
00148     init_minimize = rules()->checkMinimize( init_minimize, !isMapped );
00149     noborder = rules()->checkNoBorder( noborder, !isMapped );
00150 
00151     // Initial desktop placement
00152     if( session )
00153         {
00154         desk = session->desktop;
00155         if( session->onAllDesktops )
00156             desk = NET::OnAllDesktops;
00157         }
00158     else
00159         {
00160         // If this window is transient, ensure that it is opened on the
00161         // same window as its parent.  this is necessary when an application
00162         // starts up on a different desktop than is currently displayed
00163         if( isTransient() )
00164             {
00165             ClientList mainclients = mainClients();
00166             bool on_current = false;
00167             Client* maincl = NULL;
00168             // This is slightly duplicated from Placement::placeOnMainWindow()
00169             for( ClientList::ConstIterator it = mainclients.constBegin();
00170                 it != mainclients.constEnd();
00171                 ++it )
00172                 {
00173                 if( mainclients.count() > 1 && (*it)->isSpecialWindow() )
00174                     continue; // Don't consider toolbars etc when placing
00175                 maincl = *it;
00176                 if( (*it)->isOnCurrentDesktop() )
00177                     on_current = true;
00178                 }
00179             if( on_current )
00180                 desk = workspace()->currentDesktop();
00181             else if( maincl != NULL )
00182                 desk = maincl->desktop();
00183             }
00184         if( info->desktop() )
00185             desk = info->desktop(); // Window had the initial desktop property, force it
00186         if( desktop() == 0 && asn_valid && asn_data.desktop() != 0 )
00187             desk = asn_data.desktop();
00188         }
00189     if( desk == 0 ) // Assume window wants to be visible on the current desktop
00190         desk = workspace()->currentDesktop();
00191     desk = rules()->checkDesktop( desk, !isMapped );
00192     if( desk != NET::OnAllDesktops ) // Do range check
00193         desk = qMax( 1, qMin( workspace()->numberOfDesktops(), desk ));
00194     info->setDesktop( desk );
00195     workspace()->updateOnAllDesktopsOfTransients( this ); // SELI TODO
00196     //onAllDesktopsChange(); // Decoration doesn't exist here yet
00197 
00198     QRect geom( attr.x, attr.y, attr.width, attr.height );
00199     bool placementDone = false;
00200 
00201     if ( session )
00202         geom = session->geometry;
00203 
00204     QRect area;
00205     bool partial_keep_in_area = isMapped || session;
00206     if( isMapped || session )
00207         area = workspace()->clientArea( FullArea, geom.center(), desktop() );
00208     else if( options->xineramaPlacementEnabled )
00209         {
00210         int screen = options->xineramaPlacementScreen;
00211         if( screen == -1 ) // Active screen
00212             screen = asn_data.xinerama() == -1 ? workspace()->activeScreen() : asn_data.xinerama();
00213         area = workspace()->clientArea( PlacementArea, workspace()->screenGeometry( screen ).center(), desktop());
00214         }
00215     else
00216         area = workspace()->clientArea( PlacementArea, cursorPos(), desktop() );
00217 
00218     if( int type = checkFullScreenHack( geom ))
00219         {
00220         fullscreen_mode = FullScreenHack;
00221         if( rules()->checkStrictGeometry( false ))
00222             {
00223             geom = type == 2 // 1 = It's xinerama-aware fullscreen hack, 2 = It's full area
00224                 ? workspace()->clientArea( FullArea, geom.center(), desktop() )
00225                 : workspace()->clientArea( ScreenArea, geom.center(), desktop() );
00226             }
00227         else
00228             geom = workspace()->clientArea( FullScreenArea, geom.center(), desktop() );
00229         placementDone = true;
00230         }
00231 
00232     if( isDesktop() )
00233         // KWin doesn't manage desktop windows
00234         placementDone = true;
00235 
00236     bool usePosition = false;
00237     if ( isMapped || session || placementDone )
00238         placementDone = true; // Use geometry
00239     else if( isTransient() && !isUtility() && !isDialog() && !isSplash() )
00240         usePosition = true;
00241     else if( isTransient() && !hasNETSupport() )
00242         usePosition = true;
00243     else if( isDialog() && hasNETSupport() )
00244         { // If the dialog is actually non-NETWM transient window, don't try to apply placement to it,
00245           // it breaks with too many things (xmms, display)
00246         if( mainClients().count() >= 1 )
00247             {
00248 #if 1
00249             // #78082 - Ok, it seems there are after all some cases when an application has a good
00250             // reason to specify a position for its dialog. Too bad other WMs have never bothered
00251             // with placement for dialogs, so apps always specify positions for their dialogs,
00252             // including such silly positions like always centered on the screen or under mouse.
00253             // Using ignoring requested position in window-specific settings helps, and now
00254             // there's also _NET_WM_FULL_PLACEMENT.
00255             usePosition = true;
00256 #else
00257             ; // Force using placement policy
00258 #endif
00259             }
00260         else
00261             usePosition = true;
00262         }
00263     else if( isSplash() )
00264         ; // Force using placement policy
00265     else
00266         usePosition = true;
00267     if( !rules()->checkIgnoreGeometry( !usePosition ))
00268         {
00269         bool ignorePPosition = options->ignorePositionClasses.contains(
00270             QString::fromLatin1( resourceClass() ));
00271 
00272         if((( xSizeHint.flags & PPosition ) && !ignorePPosition ) ||
00273             ( xSizeHint.flags & USPosition ))
00274             {
00275             placementDone = true;
00276             // Disobey xinerama placement option for now (#70943)
00277             area = workspace()->clientArea( PlacementArea, geom.center(), desktop() );
00278             }
00279         }
00280     //if( true ) // Size is always obeyed for now, only with constraints applied
00281     //    if(( xSizeHint.flags & USSize ) || ( xSizeHint.flags & PSize ))
00282     //        {
00283     //        // Keep in mind that we now actually have a size :-)
00284     //        }
00285 
00286     if( xSizeHint.flags & PMaxSize )
00287         geom.setSize( geom.size().boundedTo(
00288             rules()->checkMaxSize( QSize( xSizeHint.max_width, xSizeHint.max_height ))));
00289     if( xSizeHint.flags & PMinSize )
00290         geom.setSize( geom.size().expandedTo(
00291             rules()->checkMinSize( QSize( xSizeHint.min_width, xSizeHint.min_height ))));
00292 
00293     if( isMovable() && ( geom.x() > area.right() || geom.y() > area.bottom() ))
00294         placementDone = false; // Weird, do not trust.
00295 
00296     if( placementDone )
00297         move( geom.x(), geom.y() ); // Before gravitating
00298 
00299     updateDecoration( false ); // Also gravitates
00300     // TODO: Is CentralGravity right here, when resizing is done after gravitating?
00301     plainResize( rules()->checkSize( sizeForClientSize( geom.size() ), !isMapped ));
00302 
00303     QPoint forced_pos = rules()->checkPosition( invalidPoint, !isMapped );
00304     if( forced_pos != invalidPoint )
00305         {
00306         move( forced_pos );
00307         placementDone = true;
00308         // Don't keep inside workarea if the window has specially configured position
00309         partial_keep_in_area = true;
00310         area = workspace()->clientArea( FullArea, geom.center(), desktop() );
00311         }
00312     if( !placementDone )
00313         { // Placement needs to be after setting size
00314         workspace()->place( this, area );
00315         placementDone = true;
00316         }
00317 
00318     if(( !isSpecialWindow() || isToolbar() ) && isMovable() )
00319         keepInArea( area, partial_keep_in_area );
00320 
00321     updateShape();
00322 
00323     // CT: Extra check for stupid jdk 1.3.1. But should make sense in general
00324     // if client has initial state set to Iconic and is transient with a parent
00325     // window that is not Iconic, set init_state to Normal
00326     if( init_minimize && isTransient() )
00327         {
00328         ClientList mainclients = mainClients();
00329         for( ClientList::ConstIterator it = mainclients.constBegin();
00330             it != mainclients.constEnd();
00331             ++it )
00332             if( (*it)->isShown( true ))
00333                 init_minimize = false; // SELI TODO: Even e.g. for NET::Utility?
00334         }
00335     // If a dialog is shown for minimized window, minimize it too
00336     if( !init_minimize && isTransient() && mainClients().count() > 0 )
00337         {
00338         bool visible_parent = false;
00339         // Use allMainClients(), to include also main clients of group transients
00340         // that have been optimized out in Client::checkGroupTransients()
00341         ClientList mainclients = allMainClients();
00342         for( ClientList::ConstIterator it = mainclients.constBegin();
00343             it != mainclients.constEnd();
00344             ++it )
00345             if( (*it)->isShown( true ))
00346                 visible_parent = true;
00347         if( !visible_parent )
00348             {
00349             init_minimize = true;
00350             demandAttention();
00351             }
00352         }
00353 
00354     if( init_minimize )
00355         minimize( true ); // No animation
00356 
00357     // SELI TODO: This seems to be mainly for kstart and ksystraycmd
00358     // probably should be replaced by something better
00359     bool doNotShow = false;
00360     if ( workspace()->isNotManaged( caption() ))
00361         doNotShow = true;
00362 
00363     // Other settings from the previous session
00364     if( session )
00365         {
00366         // Session restored windows are not considered to be new windows WRT rules,
00367         // I.e. obey only forcing rules
00368         setKeepAbove( session->keepAbove );
00369         setKeepBelow( session->keepBelow );
00370         setSkipTaskbar( session->skipTaskbar, true );
00371         setSkipPager( session->skipPager );
00372         setShade( session->shaded ? ShadeNormal : ShadeNone );
00373         if( session->maximized != MaximizeRestore )
00374             {
00375             maximize( MaximizeMode( session->maximized ));
00376             geom_restore = session->restore;
00377             }
00378         if( session->fullscreen == FullScreenHack )
00379             ; // Nothing, this should be already set again above
00380         else if( session->fullscreen != FullScreenNone )
00381             {
00382             setFullScreen( true, false );
00383             geom_fs_restore = session->fsrestore;
00384             }
00385         }
00386     else
00387         {
00388         geom_restore = geometry(); // Remember restore geometry
00389         if( isMaximizable() && ( width() >= area.width() || height() >= area.height() ))
00390             { // Window is too large for the screen, maximize in the
00391               // directions necessary
00392             if( width() >= area.width() && height() >= area.height() )
00393                 {
00394                 maximize( Client::MaximizeFull );
00395                 geom_restore = QRect(); // Use placement when unmaximizing
00396                 }
00397             else if( width() >= area.width() )
00398                 {
00399                 maximize( Client::MaximizeHorizontal );
00400                 geom_restore = QRect(); // Use placement when unmaximizing
00401                 geom_restore.setY( y() ); // But only for horizontal direction
00402                 geom_restore.setHeight( height() );
00403                 }
00404             else if( height() >= area.height() )
00405                 {
00406                 maximize( Client::MaximizeVertical );
00407                 geom_restore = QRect(); // Use placement when unmaximizing
00408                 geom_restore.setX( x() ); // But only for vertical direction
00409                 geom_restore.setWidth( width() );
00410                 }
00411             }
00412 
00413         // Window may want to be maximized
00414         // done after checking that the window isn't larger than the workarea, so that
00415         // the restore geometry from the checks above takes precedence, and window
00416         // isn't restored larger than the workarea
00417         MaximizeMode maxmode = static_cast<MaximizeMode>(
00418             (( info->state() & NET::MaxVert ) ? MaximizeVertical : 0 ) |
00419             (( info->state() & NET::MaxHoriz ) ? MaximizeHorizontal : 0 ));
00420         MaximizeMode forced_maxmode = rules()->checkMaximize( maxmode, !isMapped );
00421 
00422         // Either hints were set to maximize, or is forced to maximize,
00423         // or is forced to non-maximize and hints were set to maximize
00424         if( forced_maxmode != MaximizeRestore || maxmode != MaximizeRestore )
00425             maximize( forced_maxmode );
00426 
00427         // Read other initial states
00428         setShade( rules()->checkShade( info->state() & NET::Shaded ? ShadeNormal : ShadeNone, !isMapped ));
00429         setKeepAbove( rules()->checkKeepAbove( info->state() & NET::KeepAbove, !isMapped ));
00430         setKeepBelow( rules()->checkKeepBelow( info->state() & NET::KeepBelow, !isMapped ));
00431         setSkipTaskbar( rules()->checkSkipTaskbar( info->state() & NET::SkipTaskbar, !isMapped ), true );
00432         setSkipPager( rules()->checkSkipPager( info->state() & NET::SkipPager, !isMapped ));
00433         if( info->state() & NET::DemandsAttention )
00434             demandAttention();
00435         if( info->state() & NET::Modal )
00436             setModal( true );
00437         if( fullscreen_mode != FullScreenHack && isFullScreenable() )
00438             setFullScreen( rules()->checkFullScreen( info->state() & NET::FullScreen, !isMapped ), false );
00439         }
00440 
00441     updateAllowedActions( true );
00442 
00443     // Set initial user time directly
00444     user_time = readUserTimeMapTimestamp( asn_valid ? &asn_id : NULL, asn_valid ? &asn_data : NULL, session );
00445     group()->updateUserTime( user_time ); // And do what Client::updateUserTime() does
00446 
00447     if( isTopMenu()) // They're shown in Workspace::addClient() if their mainwindow
00448         hideClient( true ); // Is the active one
00449 
00450     // This should avoid flicker, because real restacking is done
00451     // only after manage() finishes because of blocking, but the window is shown sooner
00452     XLowerWindow( display(), frameId() );
00453     if( session && session->stackingOrder != -1 )
00454         {
00455         sm_stacking_order = session->stackingOrder;
00456         workspace()->restoreSessionStackingOrder( this );
00457         }
00458 
00459     if( compositing() )
00460         // Sending ConfigureNotify is done when setting mapping state below,
00461         // Getting the first sync response means window is ready for compositing
00462         sendSyncRequest();
00463 
00464     if( isShown( true ) && !doNotShow )
00465         {
00466         if( isDialog() )
00467             Notify::raise( Notify::TransNew );
00468         if( isNormalWindow() )
00469             Notify::raise( Notify::New );
00470 
00471         bool allow;
00472         if( session )
00473             allow = session->active &&
00474                 ( !workspace()->wasUserInteraction() || workspace()->activeClient() == NULL ||
00475                 workspace()->activeClient()->isDesktop() );
00476         else
00477             allow = workspace()->allowClientActivation( this, userTime(), false );
00478 
00479         // If session saving, force showing new windows (i.e. "save file?" dialogs etc.)
00480         // also force if activation is allowed
00481         if( !isOnCurrentDesktop() && !isMapped && !session && ( allow || workspace()->sessionSaving() ))
00482             workspace()->setCurrentDesktop( desktop() );
00483 
00484         bool belongs_to_desktop = false;
00485         for( ClientList::ConstIterator it = group()->members().constBegin();
00486             it != group()->members().constEnd();
00487             ++it )
00488             if( (*it)->isDesktop() )
00489                 {
00490                 belongs_to_desktop = true;
00491                 break;
00492                 }
00493         if( !belongs_to_desktop && workspace()->showingDesktop() )
00494             workspace()->resetShowingDesktop( options->showDesktopIsMinimizeAll );
00495 
00496         if( isOnCurrentDesktop() && !isMapped && !allow && ( !session || session->stackingOrder < 0 ))
00497             workspace()->restackClientUnderActive( this );
00498 
00499         updateVisibility();
00500 
00501         if( !isMapped )
00502             {
00503             if( allow && isOnCurrentDesktop() )
00504                 {
00505                 if( !isSpecialWindow() )
00506                     if ( options->focusPolicyIsReasonable() && wantsTabFocus() )
00507                         workspace()->requestFocus( this );
00508                 }
00509             else if( !session && !isSpecialWindow())
00510                 demandAttention();
00511             }
00512         }
00513     else if( !doNotShow ) // if( !isShown( true ) && !doNotShow )
00514         updateVisibility();
00515     else // doNotShow
00516         hideClient( true ); // SELI HACK !!!
00517     assert( mapping_state != Withdrawn );
00518     blockGeometryUpdates( false );
00519 
00520     if( user_time == CurrentTime || user_time == -1U )
00521         { // No known user time, set something old
00522         user_time = xTime() - 1000000;
00523         if( user_time == CurrentTime || user_time == -1U ) // Let's be paranoid
00524             user_time = xTime() - 1000000 + 10;
00525         }
00526 
00527     updateWorkareaDiffs();
00528 
00529     //sendSyntheticConfigureNotify(); // Done when setting mapping state
00530 
00531     delete session;
00532 
00533     ungrabXServer();
00534 
00535     client_rules.discardTemporary();
00536     applyWindowRules(); // Just in case
00537     workspace()->discardUsedWindowRules( this, false ); // Remove ApplyNow rules
00538     updateWindowRules(); // Was blocked while !isManaged()
00539 
00540     // TODO: there's a small problem here - isManaged() depends on the mapping state,
00541     // but this client is not yet in Workspace's client list at this point, will
00542     // be only done in addClient()
00543     return true;
00544     }
00545 
00546 // Called only from manage()
00547 void Client::embedClient( Window w, const XWindowAttributes& attr )
00548     {
00549     assert( client == None );
00550     assert( frameId() == None );
00551     assert( wrapper == None );
00552     client = w;
00553 
00554     // We don't want the window to be destroyed when we are destroyed
00555     XAddToSaveSet( display(), client );
00556     XSelectInput( display(), client, NoEventMask );
00557     XUnmapWindow( display(), client );
00558     XWindowChanges wc; // Set the border width to 0
00559     wc.border_width = 0; // TODO: Possibly save this, and also use it for initial configuring of the window
00560     XConfigureWindow( display(), client, CWBorderWidth, &wc );
00561 
00562     XSetWindowAttributes swa;
00563     swa.colormap = attr.colormap;
00564     swa.background_pixmap = None;
00565     swa.border_pixel = 0;
00566 
00567     Window frame = XCreateWindow( display(), rootWindow(), 0, 0, 1, 1, 0,
00568         attr.depth, InputOutput, attr.visual, CWColormap | CWBackPixmap | CWBorderPixel, &swa );
00569     setWindowHandles( client, frame );
00570     wrapper = XCreateWindow( display(), frame, 0, 0, 1, 1, 0,
00571         attr.depth, InputOutput, attr.visual, CWColormap | CWBackPixmap | CWBorderPixel, &swa );
00572 
00573     XDefineCursor( display(), frame, QCursor( Qt::ArrowCursor ).handle() );
00574     // Some apps are stupid and don't define their own cursor - set the arrow one for them
00575     XDefineCursor( display(), wrapper, QCursor( Qt::ArrowCursor ).handle() );
00576     XReparentWindow( display(), client, wrapper, 0, 0 );
00577     XSelectInput( display(), frame,
00578         KeyPressMask | KeyReleaseMask |
00579         ButtonPressMask | ButtonReleaseMask |
00580         KeymapStateMask |
00581         ButtonMotionMask |
00582         PointerMotionMask |
00583         EnterWindowMask | LeaveWindowMask |
00584         FocusChangeMask |
00585         ExposureMask |
00586         PropertyChangeMask |
00587         StructureNotifyMask | SubstructureRedirectMask );
00588     XSelectInput( display(), wrapper, ClientWinMask | SubstructureNotifyMask );
00589     XSelectInput( display(), client,
00590         FocusChangeMask |
00591         PropertyChangeMask |
00592         ColormapChangeMask |
00593         EnterWindowMask | LeaveWindowMask |
00594         KeyPressMask | KeyReleaseMask
00595         );
00596 
00597     updateMouseGrab();
00598     }
00599 
00600 } // namespace

KWin

Skip menu "KWin"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal