diff options
Diffstat (limited to 'kwin/layers.cpp')
-rw-r--r-- | kwin/layers.cpp | 830 |
1 files changed, 0 insertions, 830 deletions
diff --git a/kwin/layers.cpp b/kwin/layers.cpp deleted file mode 100644 index 773ea2d58..000000000 --- a/kwin/layers.cpp +++ /dev/null @@ -1,830 +0,0 @@ -/***************************************************************** - KWin - the KDE window manager - This file is part of the KDE project. - -Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org> -Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org> - -You can Freely distribute this program under the GNU General Public -License. See the file "COPYING" for the exact licensing terms. -******************************************************************/ - -// SELI zmenit doc - -/* - - This file contains things relevant to stacking order and layers. - - Design: - - Normal unconstrained stacking order, as requested by the user (by clicking - on windows to raise them, etc.), is in Workspace::unconstrained_stacking_order. - That list shouldn't be used at all, except for building - Workspace::stacking_order. The building is done - in Workspace::constrainedStackingOrder(). Only Workspace::stackingOrder() should - be used to get the stacking order, because it also checks the stacking order - is up to date. - All clients are also stored in Workspace::clients (except for isDesktop() clients, - as those are very special, and are stored in Workspace::desktops), in the order - the clients were created. - - Every window has one layer assigned in which it is. There are 6 layers, - from bottom : DesktopLayer, BelowLayer, NormalLayer, DockLayer, AboveLayer - and ActiveLayer (see also NETWM sect.7.10.). The layer a window is in depends - on the window type, and on other things like whether the window is active. - - NET::Splash clients belong to the Normal layer. NET::TopMenu clients - belong to Dock layer. Clients that are both NET::Dock and NET::KeepBelow - are in the Normal layer in order to keep the 'allow window to cover - the panel' Kicker setting to work as intended (this may look like a slight - spec violation, but a) I have no better idea, b) the spec allows adjusting - the stacking order if the WM thinks it's a good idea . We put all - NET::KeepAbove above all Docks too, even though the spec suggests putting - them in the same layer. - - Most transients are in the same layer as their mainwindow, - see Workspace::constrainedStackingOrder(), they may also be in higher layers, but - they should never be below their mainwindow. - - When some client attribute changes (above/below flag, transiency...), - Workspace::updateClientLayer() should be called in order to make - sure it's moved to the appropriate layer ClientList if needed. - - Currently the things that affect client in which layer a client - belongs: KeepAbove/Keep Below flags, window type, fullscreen - state and whether the client is active, mainclient (transiency). - - Make sure updateStackingOrder() is called in order to make - Workspace::stackingOrder() up to date and propagated to the world. - Using Workspace::blockStackingUpdates() (or the StackingUpdatesBlocker - helper class) it's possible to temporarily disable updates - and the stacking order will be updated once after it's allowed again. - -*/ - -#include <assert.h> - -#include <kdebug.h> - -#include "utils.h" -#include "client.h" -#include "workspace.h" -#include "tabbox.h" -#include "group.h" -#include "rules.h" - -namespace KWinInternal -{ - -//******************************* -// Workspace -//******************************* - -void Workspace::updateClientLayer( Client* c ) - { - if( c == NULL ) - return; - if( c->layer() == c->belongsToLayer()) - return; - StackingUpdatesBlocker blocker( this ); - c->invalidateLayer(); // tqinvalidate, will be updated when doing restacking - for( ClientList::ConstIterator it = c->transients().begin(); - it != c->transients().end(); - ++it ) - updateClientLayer( *it ); - } - -void Workspace::updateStackingOrder( bool propagate_new_clients ) - { - if( block_stacking_updates > 0 ) - { - blocked_propagating_new_clients = blocked_propagating_new_clients || propagate_new_clients; - return; - } - ClientList new_stacking_order = constrainedStackingOrder(); - bool changed = ( new_stacking_order != stacking_order ); - stacking_order = new_stacking_order; -#if 0 - kdDebug() << "stacking:" << changed << endl; - if( changed || propagate_new_clients ) - { - for( ClientList::ConstIterator it = stacking_order.begin(); - it != stacking_order.end(); - ++it ) - kdDebug() << (void*)(*it) << *it << ":" << (*it)->layer() << endl; - } -#endif - if( changed || propagate_new_clients ) - { - propagateClients( propagate_new_clients ); - if( active_client ) - active_client->updateMouseGrab(); - } - } - -/*! - Propagates the managed clients to the world. - Called ONLY from updateStackingOrder(). - */ -void Workspace::propagateClients( bool propagate_new_clients ) - { - Window *cl; // MW we should not assume WId and Window to be compatible - // when passig pointers around. - - // restack the windows according to the stacking order -#if 0 - Window* new_stack = new Window[ stacking_order.count() + 2 ]; - int pos = 0; -#endif - NET::WindowType t; - Window shadow; - Window *dock_shadow_stack, *window_stack; - int i, numDocks, pos, topmenu_space_pos; - - dock_shadow_stack = new Window[ stacking_order.count() * 2 ]; - window_stack = new Window[ stacking_order.count() * 2 + 2 ]; - i = 0; - pos = 0; - topmenu_space_pos = 1; // not 0, that's supportWindow !!! - - // Stack all windows under the support window. The support window is - // not used for anything (besides the NETWM property), and it's not shown, - // but it was lowered after twin startup. Stacking all clients below - // it ensures that no client will be ever shown above override-redirect - // windows (e.g. popups). -#if 0 - new_stack[ pos++ ] = supportWindow->winId(); - int topmenu_space_pos = 1; // not 0, that's supportWindow !!! -#endif - window_stack[pos++] = supportWindow->winId(); - for( ClientList::ConstIterator it = stacking_order.fromLast(); - it != stacking_order.end(); - --it ) - { -#if 0 - new_stack[ pos++ ] = (*it)->frameId(); - if( (*it)->belongsToLayer() >= DockLayer ) - topmenu_space_pos = pos; -#endif - t = (*it)->windowType(); - switch (t) - { - case NET::Dock: - window_stack[pos++] = (*it)->frameId(); - if ((shadow = (*it)->shadowId()) != None) - dock_shadow_stack[i++] = shadow; - break; - case NET::Desktop: - numDocks = i; - for (i = 0; i < numDocks; i++) - // Shadows for dock windows go just above the desktop - window_stack[pos++] = dock_shadow_stack[i]; - window_stack[pos++] = (*it)->frameId(); - break; - case NET::TopMenu: - topmenu_space_pos = pos; - // fall through - default: - window_stack[pos++] = (*it)->frameId(); - if ((shadow = (*it)->shadowId()) != None) - // If the current window also has a shadow, place it - // immediately under the current window - window_stack[pos++] = shadow; - } - } - if( topmenu_space != NULL ) - { // make sure the topmenu space is below all topmenus, fullscreens, etc. - for( int i = pos; - i > topmenu_space_pos; - --i ) -#if 0 - new_stack[ i ] = new_stack[ i - 1 ]; - new_stack[ topmenu_space_pos ] = topmenu_space->winId(); -#endif - window_stack[ i ] = window_stack[ i - 1 ]; - window_stack[ topmenu_space_pos ] = topmenu_space->winId(); - ++pos; - } -#if 0 - // TODO isn't it too inefficient to restart always all clients? - // TODO don't restack not visible windows? - assert( new_stack[ 0 ] = supportWindow->winId()); -#endif -#if 0 - XRestackWindows(qt_xdisplay(), new_stack, pos); - delete [] new_stack; -#endif - XRestackWindows(qt_xdisplay(), window_stack, pos); - delete [] dock_shadow_stack; - delete [] window_stack; - - if ( propagate_new_clients ) - { - cl = new Window[ desktops.count() + clients.count()]; - pos = 0; - // TODO this is still not completely in the map order - for ( ClientList::ConstIterator it = desktops.begin(); it != desktops.end(); ++it ) - cl[pos++] = (*it)->window(); - for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it ) - cl[pos++] = (*it)->window(); - rootInfo->setClientList( cl, pos ); - delete [] cl; - } - - cl = new Window[ stacking_order.count()]; - pos = 0; - for ( ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it) - cl[pos++] = (*it)->window(); - rootInfo->setClientListStacking( cl, pos ); - delete [] cl; - } - - -/*! - Returns topmost visible client. Windows on the dock, the desktop - or of any other special kind are excluded. Also if the window - doesn't accept focus it's excluded. - */ -// TODO misleading name for this method -Client* Workspace::topClientOnDesktop( int desktop, bool unconstrained, bool only_normal ) const - { -// TODO Q_ASSERT( block_stacking_updates == 0 ); - ClientList::ConstIterator begin, end; - if( !unconstrained ) - { - begin = stacking_order.fromLast(); - end = stacking_order.end(); - } - else - { - begin = unconstrained_stacking_order.fromLast(); - end = unconstrained_stacking_order.end(); - } - for( ClientList::ConstIterator it = begin; - it != end; - --it ) - { - if( (*it)->isOnDesktop( desktop ) && (*it)->isShown( false )) - { - if( !only_normal ) - return *it; - if( (*it)->wantsTabFocus() && !(*it)->isSpecialWindow()) - return *it; - } - } - return 0; - } - -Client* Workspace::findDesktop( bool topmost, int desktop ) const - { -// TODO Q_ASSERT( block_stacking_updates == 0 ); - if( topmost ) - { - for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it) - { - if ( (*it)->isOnDesktop( desktop ) && (*it)->isDesktop() - && (*it)->isShown( true )) - return *it; - } - } - else // bottom-most - { - for ( ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it) - { - if ( (*it)->isOnDesktop( desktop ) && (*it)->isDesktop() - && (*it)->isShown( true )) - return *it; - } - } - return NULL; - } - -void Workspace::raiseOrLowerClient( Client *c) - { - if (!c) return; - Client* topmost = NULL; -// TODO Q_ASSERT( block_stacking_updates == 0 ); - if ( most_recently_raised && stacking_order.contains( most_recently_raised ) && - most_recently_raised->isShown( true ) && c->isOnCurrentDesktop()) - topmost = most_recently_raised; - else - topmost = topClientOnDesktop( c->isOnAllDesktops() ? currentDesktop() : c->desktop()); - - if( c == topmost) - lowerClient(c); - else - raiseClient(c); - } - - -void Workspace::lowerClient( Client* c ) - { - if ( !c ) - return; - if( c->isTopMenu()) - return; - - c->cancelAutoRaise(); - - StackingUpdatesBlocker blocker( this ); - - unconstrained_stacking_order.remove( c ); - unconstrained_stacking_order.prepend( c ); - if( c->isTransient()) - { - // lower also mainclients, in their reversed stacking order - ClientList mainclients = ensureStackingOrder( c->mainClients()); - for( ClientList::ConstIterator it = mainclients.fromLast(); - it != mainclients.end(); - ++it ) - lowerClient( *it ); - } - - if ( c == most_recently_raised ) - most_recently_raised = 0; - } - -void Workspace::lowerClientWithinApplication( Client* c ) - { - if ( !c ) - return; - if( c->isTopMenu()) - return; - - c->cancelAutoRaise(); - - StackingUpdatesBlocker blocker( this ); - - unconstrained_stacking_order.remove( c ); - bool lowered = false; - // first try to put it below the bottom-most window of the application - for( ClientList::Iterator it = unconstrained_stacking_order.begin(); - it != unconstrained_stacking_order.end(); - ++it ) - if( Client::belongToSameApplication( *it, c )) - { - unconstrained_stacking_order.insert( it, c ); - lowered = true; - break; - } - if( !lowered ) - unconstrained_stacking_order.prepend( c ); - // ignore mainwindows - } - -void Workspace::raiseClient( Client* c ) - { - if ( !c ) - return; - if( c->isTopMenu()) - return; - - c->cancelAutoRaise(); - - StackingUpdatesBlocker blocker( this ); - - if( c->isTransient()) - { - ClientList mainclients = ensureStackingOrder( c->mainClients()); - for( ClientList::ConstIterator it = mainclients.begin(); - it != mainclients.end(); - ++it ) - raiseClient( *it ); - } - - unconstrained_stacking_order.remove( c ); - unconstrained_stacking_order.append( c ); - if (options->shadowEnabled(c->isActive())) - { - c->removeShadow(); - c->drawDelayedShadow(); - } - - if( !c->isSpecialWindow()) - { - most_recently_raised = c; - pending_take_activity = NULL; - } - } - -void Workspace::raiseClientWithinApplication( Client* c ) - { - if ( !c ) - return; - if( c->isTopMenu()) - return; - - c->cancelAutoRaise(); - - StackingUpdatesBlocker blocker( this ); - // ignore mainwindows - - // first try to put it above the top-most window of the application - for( ClientList::Iterator it = unconstrained_stacking_order.fromLast(); - it != unconstrained_stacking_order.end(); - --it ) - { - if( *it == c ) // don't lower it just because it asked to be raised - return; - if( Client::belongToSameApplication( *it, c )) - { - unconstrained_stacking_order.remove( c ); - ++it; // insert after the found one - unconstrained_stacking_order.insert( it, c ); - return; - } - } - } - -void Workspace::raiseClientRequest( Client* c, NET::RequestSource src, Time timestamp ) - { - if( src == NET::FromTool || allowFullClientRaising( c, timestamp )) - raiseClient( c ); - else - { - raiseClientWithinApplication( c ); - c->demandAttention(); - } - } - -void Workspace::lowerClientRequest( Client* c, NET::RequestSource src, Time /*timestamp*/ ) - { - // If the client has support for all this focus stealing prevention stuff, - // do only lowering within the application, as that's the more logical - // variant of lowering when application requests it. - // No demanding of attention here of course. - if( src == NET::FromTool || !c->hasUserTimeSupport()) - lowerClient( c ); - else - lowerClientWithinApplication( c ); - } - -void Workspace::restackClientUnderActive( Client* c ) - { - if( c->isTopMenu()) - return; - if( !active_client || active_client == c ) - { - raiseClient( c ); - return; - } - - assert( unconstrained_stacking_order.contains( active_client )); - if( Client::belongToSameApplication( active_client, c )) - { // put it below the active window if it's the same app - unconstrained_stacking_order.remove( c ); - unconstrained_stacking_order.insert( unconstrained_stacking_order.find( active_client ), c ); - } - else - { // put in the stacking order below _all_ windows belonging to the active application - for( ClientList::Iterator it = unconstrained_stacking_order.begin(); - it != unconstrained_stacking_order.end(); - ++it ) - { // TODO ignore topmenus? - if( Client::belongToSameApplication( active_client, *it )) - { - if( *it != c ) - { - unconstrained_stacking_order.remove( c ); - unconstrained_stacking_order.insert( it, c ); - } - break; - } - } - } - assert( unconstrained_stacking_order.contains( c )); - for( int desktop = 1; - desktop <= numberOfDesktops(); - ++desktop ) - { // do for every virtual desktop to handle the case of onalldesktop windows - if( c->wantsTabFocus() && c->isOnDesktop( desktop ) && focus_chain[ desktop ].contains( active_client )) - { - if( Client::belongToSameApplication( active_client, c )) - { // put it after the active window if it's the same app - focus_chain[ desktop ].remove( c ); - focus_chain[ desktop ].insert( focus_chain[ desktop ].find( active_client ), c ); - } - else - { // put it in focus_chain[currentDesktop()] after all windows belonging to the active applicationa - focus_chain[ desktop ].remove( c ); - for( ClientList::Iterator it = focus_chain[ desktop ].fromLast(); - it != focus_chain[ desktop ].end(); - --it ) - { - if( Client::belongToSameApplication( active_client, *it )) - { - focus_chain[ desktop ].insert( it, c ); - break; - } - } - } - } - } - // the same for global_focus_chain - if( c->wantsTabFocus() && global_focus_chain.contains( active_client )) - { - if( Client::belongToSameApplication( active_client, c )) - { - global_focus_chain.remove( c ); - global_focus_chain.insert( global_focus_chain.find( active_client ), c ); - } - else - { - global_focus_chain.remove( c ); - for( ClientList::Iterator it = global_focus_chain.fromLast(); - it != global_focus_chain.end(); - --it ) - { - if( Client::belongToSameApplication( active_client, *it )) - { - global_focus_chain.insert( it, c ); - break; - } - } - } - } - updateStackingOrder(); - } - -void Workspace::circulateDesktopApplications() - { - if ( desktops.count() > 1 ) - { - bool change_active = activeClient()->isDesktop(); - raiseClient( findDesktop( false, currentDesktop())); - if( change_active ) // if the previously topmost Desktop was active, activate this new one - activateClient( findDesktop( true, currentDesktop())); - } - // if there's no active client, make desktop the active one - if( desktops.count() > 0 && activeClient() == NULL && should_get_focus.count() == 0 ) - activateClient( findDesktop( true, currentDesktop())); - } - - -/*! - Returns a stacking order based upon \a list that fulfills certain contained. - */ -ClientList Workspace::constrainedStackingOrder() - { - ClientList layer[ NumLayers ]; - -#if 0 - kdDebug() << "stacking1:" << endl; -#endif - // build the order from layers - TQMap< Group*, Layer > minimum_layer; - for( ClientList::ConstIterator it = unconstrained_stacking_order.begin(); - it != unconstrained_stacking_order.end(); - ++it ) - { - Layer l = (*it)->layer(); - // If a window is raised above some other window in the same window group - // which is in the ActiveLayer (i.e. it's fulscreened), make sure it stays - // above that window (see #95731). - if( minimum_layer.contains( (*it)->group()) - && minimum_layer[ (*it)->group() ] == ActiveLayer - && ( l == NormalLayer || l == AboveLayer )) - { - l = minimum_layer[ (*it)->group() ]; - } - minimum_layer[ (*it)->group() ] = l; - layer[ l ].append( *it ); - } - ClientList stacking; - for( Layer lay = FirstLayer; - lay < NumLayers; - ++lay ) - stacking += layer[ lay ]; -#if 0 - kdDebug() << "stacking2:" << endl; - for( ClientList::ConstIterator it = stacking.begin(); - it != stacking.end(); - ++it ) - kdDebug() << (void*)(*it) << *it << ":" << (*it)->layer() << endl; -#endif - // now keep transients above their mainwindows - // TODO this could(?) use some optimization - for( ClientList::Iterator it = stacking.fromLast(); - it != stacking.end(); - ) - { - if( !(*it)->isTransient()) - { - --it; - continue; - } - ClientList::Iterator it2 = stacking.end(); - if( (*it)->groupTransient()) - { - if( (*it)->group()->members().count() > 0 ) - { // find topmost client this one is transient for - for( it2 = stacking.fromLast(); - it2 != stacking.end(); - --it2 ) - { - if( *it2 == *it ) - { - it2 = stacking.end(); // don't reorder - break; - } - if( (*it2)->hasTransient( *it, true ) && keepTransientAbove( *it2, *it )) - break; - } - } // else it2 remains pointing at stacking.end() - } - else - { - for( it2 = stacking.fromLast(); - it2 != stacking.end(); - --it2 ) - { - if( *it2 == *it ) - { - it2 = stacking.end(); // don't reorder - break; - } - if( *it2 == (*it)->transientFor() && keepTransientAbove( *it2, *it )) - break; - } - } -// kdDebug() << "STACK:" << (*it) << ":" << ( it2 == stacking.end() ? ((Client*)0) : (*it2)) << endl; - if( it2 == stacking.end()) - { - --it; - continue; - } - Client* current = *it; - ClientList::Iterator remove_it = it; - --it; - stacking.remove( remove_it ); - if( !current->transients().isEmpty()) // this one now can be possibly above its transients, - it = it2; // so go again higher in the stack order and possibly move those transients again - ++it2; // insert after the mainwindow, it's ok if it2 is now stacking.end() - stacking.insert( it2, current ); - } -#if 0 - kdDebug() << "stacking3:" << endl; - for( ClientList::ConstIterator it = stacking.begin(); - it != stacking.end(); - ++it ) - kdDebug() << (void*)(*it) << *it << ":" << (*it)->layer() << endl; - kdDebug() << "\n\n" << endl; -#endif - return stacking; - } - -void Workspace::blockStackingUpdates( bool block ) - { - if( block ) - { - if( block_stacking_updates == 0 ) - blocked_propagating_new_clients = false; - ++block_stacking_updates; - } - else // !block - if( --block_stacking_updates == 0 ) - updateStackingOrder( blocked_propagating_new_clients ); - } - -// Ensure list is in stacking order -ClientList Workspace::ensureStackingOrder( const ClientList& list ) const - { -// TODO Q_ASSERT( block_stacking_updates == 0 ); - if( list.count() < 2 ) - return list; - // TODO is this worth optimizing? - ClientList result = list; - for( ClientList::ConstIterator it = stacking_order.begin(); - it != stacking_order.end(); - ++it ) - if( result.remove( *it ) != 0 ) - result.append( *it ); - return result; - } - -// check whether a transient should be actually kept above its mainwindow -// there may be some special cases where this rule shouldn't be enfored -bool Workspace::keepTransientAbove( const Client* mainwindow, const Client* transient ) - { - // When topmenu's mainwindow becomes active, topmenu is raised and shown. - // They also belong to the Dock layer. This makes them to be very high. - // Therefore don't keep group transients above them, otherwise this would move - // group transients way too high. - if( mainwindow->isTopMenu() && transient->groupTransient()) - return false; - // #93832 - don't keep splashscreens above dialogs - if( transient->isSplash() && mainwindow->isDialog()) - return false; - // This is rather a hack for #76026. Don't keep non-modal dialogs above - // the mainwindow, but only if they're group transient (since only such dialogs - // have taskbar entry in Kicker). A proper way of doing this (both twin and kicker) - // needs to be found. - if( transient->isDialog() && !transient->isModal() && transient->groupTransient()) - return false; - // #63223 - don't keep transients above docks, because the dock is kept high, - // and e.g. dialogs for them would be too high too - if( mainwindow->isDock()) - return false; - return true; - } - -//******************************* -// Client -//******************************* - -void Client::restackWindow( Window /*above TODO */, int detail, NET::RequestSource src, Time timestamp, bool send_event ) - { - switch ( detail ) - { - case Above: - case TopIf: - workspace()->raiseClientRequest( this, src, timestamp ); - break; - case Below: - case BottomIf: - workspace()->lowerClientRequest( this, src, timestamp ); - break; - case Opposite: - default: - break; - } - if( send_event ) - sendSyntheticConfigureNotify(); - } - -void Client::setKeepAbove( bool b ) - { - b = rules()->checkKeepAbove( b ); - if( b && !rules()->checkKeepBelow( false )) - setKeepBelow( false ); - if ( b == keepAbove()) - { // force hint change if different - if( bool( info->state() & NET::KeepAbove ) != keepAbove()) - info->setState( keepAbove() ? NET::KeepAbove : 0, NET::KeepAbove ); - return; - } - keep_above = b; - info->setState( keepAbove() ? NET::KeepAbove : 0, NET::KeepAbove ); - if( decoration != NULL ) - decoration->emitKeepAboveChanged( keepAbove()); - workspace()->updateClientLayer( this ); - updateWindowRules(); - } - -void Client::setKeepBelow( bool b ) - { - b = rules()->checkKeepBelow( b ); - if( b && !rules()->checkKeepAbove( false )) - setKeepAbove( false ); - if ( b == keepBelow()) - { // force hint change if different - if( bool( info->state() & NET::KeepBelow ) != keepBelow()) - info->setState( keepBelow() ? NET::KeepBelow : 0, NET::KeepBelow ); - return; - } - keep_below = b; - info->setState( keepBelow() ? NET::KeepBelow : 0, NET::KeepBelow ); - if( decoration != NULL ) - decoration->emitKeepBelowChanged( keepBelow()); - workspace()->updateClientLayer( this ); - updateWindowRules(); - } - -Layer Client::layer() const - { - if( in_layer == UnknownLayer ) - const_cast< Client* >( this )->in_layer = belongsToLayer(); - return in_layer; - } - -Layer Client::belongsToLayer() const - { - if( isDesktop()) - return DesktopLayer; - if( isSplash()) // no damn annoying splashscreens - return NormalLayer; // getting in the way of everything else - if( isDock() && keepBelow()) - // slight hack for the 'allow window to cover panel' Kicker setting - // don't move keepbelow docks below normal window, but only to the same - // layer, so that both may be raised to cover the other - return NormalLayer; - if( keepBelow()) - return BelowLayer; - if( isDock() && !keepBelow()) - return DockLayer; - if( isTopMenu()) - return DockLayer; - // only raise fullscreen above docks if it's the topmost window in unconstrained stacking order, - // i.e. the window set to be topmost by the user (also includes transients of the fullscreen window) - const Client* ac = workspace()->mostRecentlyActivatedClient(); // instead of activeClient() - avoids flicker - const Client* top = workspace()->topClientOnDesktop( desktop(), true, false ); - if( isFullScreen() && ac != NULL && top != NULL - && ( ac == this || this->group() == ac->group()) - && ( top == this || this->group() == top->group())) - return ActiveLayer; - if( keepAbove()) - return AboveLayer; - return NormalLayer; - } - -} // namespace |