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