• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kwin
 

kwin

manage.cpp

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 You can Freely distribute this program under the GNU General Public
00009 License. See the file "COPYING" for the exact licensing terms.
00010 ******************************************************************/
00011 
00012 /*
00013 
00014  This file contains things relevant to handling incoming events.
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 namespace KWinInternal
00029 {
00030 
00036 bool Client::manage( Window w, bool isMapped )
00037     {
00038     XWindowAttributes attr;
00039     if( !XGetWindowAttributes(qt_xdisplay(), w, &attr))
00040         return false;
00041 
00042     grabXServer();
00043 
00044     // from this place on, manage() mustn't return false
00045     postpone_geometry_updates = 1;
00046     pending_geometry_update = true; // force update when finishing with geometry changes
00047 
00048     embedClient( w, attr );
00049 
00050     // SELI order all these things in some sane manner
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; // if it's already mapped, ignore hint
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         // Qt3.2 and older had this all lowercase, Qt3.3 capitalized resource class
00087         // force lowercase, so that workarounds listing resource classes still work
00088         resource_name = TQCString( classHint.res_name ).lower();
00089         resource_class = TQCString( classHint.res_class ).lower();
00090         XFree( classHint.res_name );
00091         XFree( classHint.res_class );
00092         }
00093     ignore_focus_stealing = options->checkIgnoreFocusStealing( this ); // TODO change to rules
00094 
00095     window_role = staticWindowRole( w );
00096     getWmClientLeader();
00097     getWmClientMachine();
00098     // first only read the caption text, so that setupWindowRules() can use it for matching,
00099     // and only then really set the caption using setCaption(), which checks for duplicates etc.
00100     // and also relies on rules already existing
00101     cap_normal = readName();
00102     setupWindowRules( false );
00103     setCaption( cap_normal, true );
00104 
00105     detectNoBorder();
00106     detectShapable();
00107     fetchIconicName();
00108     getWMHints(); // needs to be done before readTransient() because of reading the group
00109     modal = ( info->state() & NET::Modal ) != 0; // needs to be valid before handling groups
00110     readTransient();
00111     getIcons();
00112     getWindowProtocols();
00113     getWmNormalHints(); // get xSizeHint
00114     getMotifHints();
00115 
00116     // TODO try to obey all state information from info->state()
00117 
00118     original_skip_taskbar = skip_taskbar = ( info->state() & NET::SkipTaskbar) != 0;
00119     skip_pager = ( info->state() & NET::SkipPager) != 0;
00120 
00121     KStartupInfoId asn_id;
00122     KStartupInfoData asn_data;
00123     bool asn_valid = workspace()->checkStartupNotification( window(), asn_id, asn_data );
00124 
00125     workspace()->updateClientLayer( this );
00126 
00127     SessionInfo* session = workspace()->takeSessionInfo( this );
00128     
00129     if ( session )
00130         {
00131         if ( session->minimized )
00132             init_minimize = true;
00133         if( session->userNoBorder )
00134             setUserNoBorder( true );
00135         }
00136 
00137     setShortcut( rules()->checkShortcut( session ? session->shortcut : TQString::null, true ));
00138 
00139     init_minimize = rules()->checkMinimize( init_minimize, !isMapped );
00140     if( rules()->checkNoBorder( false, !isMapped ))
00141         setUserNoBorder( true );
00142     
00143     checkAndSetInitialRuledOpacity();
00144 
00145     // initial desktop placement
00146     if ( session ) 
00147         {
00148         desk = session->desktop;
00149         if( session->onAllDesktops )
00150             desk = NET::OnAllDesktops;
00151         }
00152     else
00153         {
00154         // if this window is transient, ensure that it is opened on the
00155         // same window as its parent.  this is necessary when an application
00156         // starts up on a different desktop than is currently displayed
00157         if( isTransient())
00158             {
00159             ClientList mainclients = mainClients();
00160             bool on_current = false;
00161             Client* maincl = NULL;
00162             // this is slightly duplicated from Placement::placeOnMainWindow()
00163             for( ClientList::ConstIterator it = mainclients.begin();
00164                  it != mainclients.end();
00165                  ++it )
00166                 {
00167                 if( mainclients.count() > 1 && (*it)->isSpecialWindow())
00168                     continue; // don't consider toolbars etc when placing
00169                 maincl = *it;
00170                 if( (*it)->isOnCurrentDesktop())
00171                     on_current = true;
00172                 }
00173             if( on_current )
00174                 desk = workspace()->currentDesktop();
00175             else if( maincl != NULL )
00176                 desk = maincl->desktop();
00177             }
00178         if ( info->desktop() )
00179             desk = info->desktop(); // window had the initial desktop property, force it
00180         if( desktop() == 0 && asn_valid && asn_data.desktop() != 0 )
00181             desk = asn_data.desktop();
00182         }
00183     if ( desk == 0 ) // assume window wants to be visible on the current desktop
00184         desk = workspace()->currentDesktop();
00185     desk = rules()->checkDesktop( desk, !isMapped );
00186     if( desk != NET::OnAllDesktops ) // do range check
00187         desk = KMAX( 1, KMIN( workspace()->numberOfDesktops(), desk ));
00188     info->setDesktop( desk );
00189     workspace()->updateOnAllDesktopsOfTransients( this ); // SELI
00190 //    onAllDesktopsChange(); decoration doesn't exist here yet
00191 
00192     TQRect geom( attr.x, attr.y, attr.width, attr.height );
00193     bool placementDone = FALSE;
00194 
00195     if ( session )
00196         geom = session->geometry;
00197 
00198     TQRect area;
00199     bool partial_keep_in_area = isMapped || session;
00200     if( isMapped || session )
00201         area = workspace()->clientArea( FullArea, geom.center(), desktop());
00202     else if( options->xineramaPlacementEnabled )
00203         {
00204         int screen = options->xineramaPlacementScreen;
00205         if( screen == -1 ) // active screen
00206             screen = asn_data.xinerama() == -1 ? workspace()->activeScreen() : asn_data.xinerama();
00207         area = workspace()->clientArea( PlacementArea, workspace()->screenGeometry( screen ).center(), desktop());
00208         }
00209     else
00210         area = workspace()->clientArea( PlacementArea, TQCursor::pos(), desktop());
00211 
00212     if( int type = checkFullScreenHack( geom ))
00213         {
00214         fullscreen_mode = FullScreenHack;
00215         if( rules()->checkStrictGeometry( false ))
00216             {
00217             geom = type == 2 // 1 - it's xinerama-aware fullscreen hack, 2 - it's full area
00218                 ? workspace()->clientArea( FullArea, geom.center(), desktop())
00219                 : workspace()->clientArea( ScreenArea, geom.center(), desktop());
00220             }
00221         else
00222             geom = workspace()->clientArea( FullScreenArea, geom.center(), desktop());
00223         placementDone = true;
00224         }
00225 
00226     if ( isDesktop() ) 
00227         {
00228         // desktops are treated slightly special
00229         geom = workspace()->clientArea( FullArea, geom.center(), desktop());
00230         placementDone = true;
00231         }
00232 
00233     bool usePosition = false;
00234     if ( isMapped || session || placementDone )
00235         placementDone = true; // use geometry
00236     else if( isTransient() && !isUtility() && !isDialog() && !isSplash())
00237         usePosition = true;
00238     else if( isTransient() && !hasNETSupport())
00239         usePosition = true;
00240     else if( isDialog() && hasNETSupport())
00241     // if the dialog is actually non-NETWM transient window, don't try to apply placement to it,
00242     // it breaks with too many things (xmms, display)
00243         {
00244         if( mainClients().count() >= 1 )
00245             {
00246 #if 1
00247             // TODO #78082 - Ok, it seems there are after all some cases when an application has a good
00248             // reason to specify a position for its dialog. Too bad other WMs have never bothered
00249             // with placement for dialogs, so apps always specify positions for their dialogs,
00250             // including such silly positions like always centered on the screen or under mouse.
00251             // Using ignoring requested position in window-specific settings helps, but at least
00252             // for Qt apps this should work better.
00253             usePosition = true;
00254 #else
00255             ; // force using placement policy
00256 #endif
00257             }
00258         else
00259             usePosition = true;
00260         }
00261     else if( isSplash())
00262         ; // force using placement policy
00263     else
00264         usePosition = true;
00265     if( !rules()->checkIgnoreGeometry( !usePosition ))
00266         {
00267         bool ignorePPosition = ( options->ignorePositionClasses.contains(TQString::fromLatin1(resourceClass())));
00268 
00269         if ( ( (xSizeHint.flags & PPosition) && !ignorePPosition ) ||
00270              (xSizeHint.flags & USPosition) ) 
00271             {
00272             placementDone = TRUE;
00273             // disobey xinerama placement option for now (#70943)
00274             area = workspace()->clientArea( PlacementArea, geom.center(), desktop());
00275             }
00276         }
00277     if( true ) // size is always obeyed for now, only with constraints applied
00278         if ( (xSizeHint.flags & USSize) || (xSizeHint.flags & PSize) ) 
00279             {
00280             // keep in mind that we now actually have a size :-)
00281             }
00282 
00283     if (xSizeHint.flags & PMaxSize)
00284         geom.setSize( geom.size().boundedTo(
00285             rules()->checkMaxSize( TQSize(xSizeHint.max_width, xSizeHint.max_height ) ) ) );
00286     if (xSizeHint.flags & PMinSize)
00287         geom.setSize( geom.size().expandedTo(
00288             rules()->checkMinSize( TQSize(xSizeHint.min_width, xSizeHint.min_height ) ) ) );
00289 
00290     if( isMovable())
00291         {
00292         if( geom.x() > area.right() || geom.y() > area.bottom())
00293             placementDone = FALSE; // weird, do not trust.
00294         }
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     TQPoint 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     XShapeSelectInput( qt_xdisplay(), window(), ShapeNotifyMask );
00322     is_shape = Shape::hasShape( window());
00323     updateShape();
00324     
00325     //CT extra check for stupid jdk 1.3.1. But should make sense in general
00326     // if client has initial state set to Iconic and is transient with a parent
00327     // window that is not Iconic, set init_state to Normal
00328     if( init_minimize && isTransient())
00329         {
00330         ClientList mainclients = mainClients();
00331         for( ClientList::ConstIterator it = mainclients.begin();
00332              it != mainclients.end();
00333              ++it )
00334             if( (*it)->isShown( true ))
00335                 init_minimize = false; // SELI even e.g. for NET::Utility?
00336         }
00337     // if a dialog is shown for minimized window, minimize it too
00338     if( !init_minimize && isTransient() && mainClients().count() > 0 )
00339         {
00340         bool visible_parent = false;
00341         ClientList mainclients = mainClients();
00342         for( ClientList::ConstIterator it = mainclients.begin();
00343              it != mainclients.end();
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 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         setShadowed( session->shadowed );
00374         if( session->maximized != MaximizeRestore )
00375             {
00376             maximize( (MaximizeMode) session->maximized );
00377             geom_restore = session->restore;
00378             }
00379         if( session->fullscreen == FullScreenHack )
00380             ; // nothing, this should be already set again above
00381         else if( session->fullscreen != FullScreenNone )
00382             {
00383             setFullScreen( true, false );
00384             geom_fs_restore = session->fsrestore;
00385             }
00386         }
00387     else 
00388         {
00389         geom_restore = geometry(); // remember restore geometry
00390         if ( isMaximizable()
00391              && ( width() >= area.width() || height() >= area.height() ) ) 
00392             {
00393             // window is too large for the screen, maximize in the
00394             // directions necessary
00395             if ( width() >= area.width() && height() >= area.height() ) 
00396                 {
00397                 maximize( Client::MaximizeFull );
00398                 geom_restore = TQRect(); // use placement when unmaximizing
00399                 }
00400             else if ( width() >= area.width() ) 
00401                 {
00402                 maximize( Client::MaximizeHorizontal );
00403                 geom_restore = TQRect(); // use placement when unmaximizing
00404                 geom_restore.setY( y()); // but only for horizontal direction
00405                 geom_restore.setHeight( height());
00406                 }
00407             else if ( height() >= area.height() ) 
00408                 {
00409                 maximize( Client::MaximizeVertical );
00410                 geom_restore = TQRect(); // use placement when unmaximizing
00411                 geom_restore.setX( x()); // but only for vertical direction
00412                 geom_restore.setWidth( width());
00413                 }
00414             }
00415         // window may want to be maximized
00416         // done after checking that the window isn't larger than the workarea, so that
00417         // the restore geometry from the checks above takes precedence, and window
00418         // isn't restored larger than the workarea
00419         MaximizeMode maxmode = static_cast< MaximizeMode >
00420             ((( info->state() & NET::MaxVert ) ? MaximizeVertical : 0 )
00421             | (( info->state() & NET::MaxHoriz ) ? MaximizeHorizontal : 0 ));
00422         MaximizeMode forced_maxmode = rules()->checkMaximize( maxmode, !isMapped );
00423         // either hints were set to maximize, or is forced to maximize,
00424         // or is forced to non-maximize and hints were set to maximize
00425         if( forced_maxmode != MaximizeRestore || maxmode != MaximizeRestore )
00426             maximize( forced_maxmode );
00427 
00428         // read other initial states
00429         setShade( rules()->checkShade( info->state() & NET::Shaded ? ShadeNormal : ShadeNone, !isMapped ));
00430         setKeepAbove( rules()->checkKeepAbove( info->state() & NET::KeepAbove, !isMapped ));
00431         setKeepBelow( rules()->checkKeepBelow( info->state() & NET::KeepBelow, !isMapped ));
00432         setSkipTaskbar( rules()->checkSkipTaskbar( info->state() & NET::SkipTaskbar, !isMapped ), true );
00433         setSkipPager( rules()->checkSkipPager( info->state() & NET::SkipPager, !isMapped ));
00434         if( info->state() & NET::DemandsAttention )
00435             demandAttention();
00436         if( info->state() & NET::Modal )
00437             setModal( true );
00438         if( fullscreen_mode != FullScreenHack && isFullScreenable())
00439             setFullScreen( rules()->checkFullScreen( info->state() & NET::FullScreen, !isMapped ), false );
00440         }
00441 
00442     updateAllowedActions( true );
00443 
00444     // TODO this should avoid flicker, because real restacking is done
00445     // only after manage() finishes, but the window is shown sooner
00446     // - keep it?
00447     XLowerWindow( qt_xdisplay(), frameId());
00448 
00449     // set initial user time directly
00450     user_time = readUserTimeMapTimestamp( asn_valid ? &asn_id : NULL, asn_valid ? &asn_data : NULL, session );
00451     group()->updateUserTime( user_time ); // and do what Client::updateUserTime() does
00452 
00453     if( isTopMenu()) // they're shown in Workspace::addClient() if their mainwindow
00454         hideClient( true ); // is the active one
00455 
00456     if( isShown( true ) && !doNotShow )
00457         {
00458         if( isDialog())
00459             Notify::raise( Notify::TransNew );
00460         if( isNormalWindow())
00461             Notify::raise( Notify::New );
00462 
00463         bool allow;
00464         if( session )
00465             allow = session->active
00466                 && ( !workspace()->wasUserInteraction()
00467                     || workspace()->activeClient() == NULL || workspace()->activeClient()->isDesktop());
00468         else
00469             allow = workspace()->allowClientActivation( this, userTime(), false );
00470 
00471         // if session saving, force showing new windows (i.e. "save file?" dialogs etc.)
00472         // also force if activation is allowed
00473         if( !isOnCurrentDesktop() && !isMapped && !session && ( allow || workspace()->sessionSaving()))
00474             workspace()->setCurrentDesktop( desktop());
00475 
00476         bool belongs_to_desktop = false;
00477         for( ClientList::ConstIterator it = group()->members().begin();
00478              it != group()->members().end();
00479              ++it )
00480             if( (*it)->isDesktop())
00481                 {
00482                 belongs_to_desktop = true;
00483                 break;
00484                 }
00485         if( !belongs_to_desktop && workspace()->showingDesktop())
00486             workspace()->resetShowingDesktop( options->showDesktopIsMinimizeAll );
00487 
00488         if( isOnCurrentDesktop() && !isMapped && !allow )
00489             workspace()->restackClientUnderActive( this );
00490         else
00491             workspace()->raiseClient( this );
00492 
00493         updateVisibility();
00494 
00495         if( !isMapped )
00496             {
00497             if( allow && isOnCurrentDesktop())
00498                 {
00499                 if( !isSpecialWindow())
00500                     if ( options->focusPolicyIsReasonable() && wantsTabFocus() )
00501                         workspace()->requestFocus( this );
00502                 }
00503             else
00504                 {
00505                 if( !session && !isSpecialWindow())
00506                         demandAttention();
00507                 }
00508             }
00509         }
00510     else if( !doNotShow ) // if( !isShown( true ) && !doNotShow )
00511         {
00512         updateVisibility();
00513         }
00514     else // doNotShow
00515         { // SELI HACK !!!
00516         hideClient( true );
00517         setMappingState( IconicState );
00518         }
00519     assert( mappingState() != WithdrawnState );
00520 
00521     if( user_time == CurrentTime || user_time == -1U ) // no known user time, set something old
00522         {
00523         user_time = GET_QT_X_TIME() - 1000000;
00524         if( user_time == CurrentTime || user_time == -1U ) // let's be paranoid
00525             user_time = GET_QT_X_TIME() - 1000000 + 10;
00526         }
00527 
00528     updateWorkareaDiffs();
00529 
00530 //    sendSyntheticConfigureNotify(); done when setting mapping state
00531 
00532     delete session;
00533 
00534     ungrabXServer();
00535     
00536     client_rules.discardTemporary();
00537     applyWindowRules(); // just in case
00538     workspace()->discardUsedWindowRules( this, false ); // remove ApplyNow rules
00539     updateWindowRules(); // was blocked while !isManaged()
00540 
00541 // TODO there's a small problem here - isManaged() depends on the mapping state,
00542 // but this client is not yet in Workspace's client list at this point, will
00543 // be only done in addClient()
00544     return true;
00545     }
00546 
00547 // called only from manage()
00548 void Client::embedClient( Window w, const XWindowAttributes &attr )
00549     {
00550     assert( client == None );
00551     assert( frame == None );
00552     assert( wrapper == None );
00553     client = w;
00554     // we don't want the window to be destroyed when we are destroyed
00555     XAddToSaveSet( qt_xdisplay(), client );
00556     XSelectInput( qt_xdisplay(), client, NoEventMask );
00557     XUnmapWindow( qt_xdisplay(), 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( qt_xdisplay(), client, CWBorderWidth, &wc );
00561 
00562     XSetWindowAttributes swa;
00563     swa.colormap = attr.colormap;
00564     swa.background_pixmap = None;
00565     swa.border_pixel = 0;
00566 
00567     frame = XCreateWindow( qt_xdisplay(), qt_xrootwin(), 0, 0, 1, 1, 0,
00568             attr.depth, InputOutput, attr.visual,
00569             CWColormap | CWBackPixmap | CWBorderPixel, &swa );
00570     wrapper = XCreateWindow( qt_xdisplay(), frame, 0, 0, 1, 1, 0,
00571             attr.depth, InputOutput, attr.visual,
00572             CWColormap | CWBackPixmap | CWBorderPixel, &swa );
00573 
00574     XDefineCursor( qt_xdisplay(), frame, tqarrowCursor.handle());
00575     // some apps are stupid and don't define their own cursor - set the arrow one for them
00576     XDefineCursor( qt_xdisplay(), wrapper, tqarrowCursor.handle());
00577     XReparentWindow( qt_xdisplay(), client, wrapper, 0, 0 );
00578     XSelectInput( qt_xdisplay(), frame,
00579             KeyPressMask | KeyReleaseMask |
00580             ButtonPressMask | ButtonReleaseMask |
00581             KeymapStateMask |
00582             ButtonMotionMask |
00583             PointerMotionMask |
00584             EnterWindowMask | LeaveWindowMask |
00585             FocusChangeMask |
00586             ExposureMask |
00587             PropertyChangeMask |
00588             StructureNotifyMask | SubstructureRedirectMask );
00589     XSelectInput( qt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
00590     XSelectInput( qt_xdisplay(), client,
00591                   FocusChangeMask |
00592                   PropertyChangeMask |
00593                   ColormapChangeMask |
00594                   EnterWindowMask | LeaveWindowMask |
00595                   KeyPressMask | KeyReleaseMask
00596                   );
00597     updateMouseGrab();
00598     }
00599 
00600 } // namespace

kwin

Skip menu "kwin"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members

kwin

Skip menu "kwin"
  • kate
  • kwin
  •   lib
  • libkonq
Generated for kwin by doxygen 1.6.3
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |